有奖捉虫:办公协同&微信生态&物联网文档专题 HOT

概述

即时通信 IM 的终端用户需要随时都能够得知最新的消息,而由于移动端设备的性能与电量有限,当 App 处于后台时,为了避免维持长连接而导致的过多资源消耗,即时通信 IM 推荐您使用 Apple 提供的系统级推送通道(APNs)来进行消息通知,APNs 相比第三方推送拥有更稳定的系统级长连接,可以做到随时接受推送消息,且资源消耗大幅降低。
注意
在没有主动退出登录的情况下,应用退后台、手机锁屏、或者应用进程被用户主动杀掉三种场景下,如果想继续接收到 IM 消息提醒,可以接入即时通信 IM 离线推送。
如果应用主动调用 logout 退出登录,或者多端登录被踢下线,即使接入了 IM 离线推送,也收不到离线推送消息。

集成 TUIOfflinePush 跑通离线推送功能

集成 TUIOfflinePush 组件之前,需要先向 Apple 申请 APNs 推送证书,然后 上传推送证书到 IM 控制台。之后按照如下步骤操作即可快速接入 IM 离线推送。
说明
如果您想尽可能简单地接入 TUIOfflinePush 组件,您需要使用 TUICore 组件中的 TUILogin 提供的 login/logout 接口登录/登出,此时 TUIOfflinePush 组件会自动感知登录/登出事件。如果您不想使用 TUILogin 提供的接口,可参见 TUIOfflinePush 的 高级用法-自定义登录/登出

步骤1:集成 TUIOfflinePush 组件

1. TUIOfflinePush 组件支持 cocoapods 集成,您需要在 Podfile 中添加组件依赖。
# 防止 TUI 组件里的 *.xcassets 与您项目里面冲突。
install! 'cocoapods', :disable_input_output_paths => true

# TUI 组件依赖了静态库,需要屏蔽如下设置,如果报错,请参见常见问题说明。
# use_frameworks!

# 集成离线推送组件
pod 'TUIOfflinePush'
2. 执行以下命令,安装 TUIOfflinePush 组件。
pod install
如果无法安装 TUIKit 最新版本,执行以下命令更新本地的 CocoaPods 仓库列表。
pod repo update

步骤2:配置推送参数

1. 当您 上传证书到 IM 控制台 后,IM 控制台会为您分配一个证书 ID ,见下图。



2. 您需要在 AppDelegate 中,调用宏 TUIOfflinePushCertificateIDForAPNS 设置下证书 ID 即可。
@implementation AppDelegate

#ifdef DEBUG
// 配置开发环境证书
TUIOfflinePushCertificateIDForAPNS(31287)
#else
// 配置生产环境证书
TUIOfflinePushCertificateIDForAPNS(31288)
#endif

@end
说明
TUIOfflinePushCertificateIDForAPNS 是组件内置的宏定义,您只需要在 AppDelegate@implementation 中的任意位置中调用即可。

步骤3:单击离线推送后自定义跳转

1. 单击通知栏的离线推送后,TUIOfflinePush 组件已支持推送内容的解析。
2. 如果要实现跳转到聊天列表,您只需要在 AppDelegate 中实现 -navigateToTUIChatViewController:groupID: 跳转方法即可。
说明
TUIOfflinePush 组件默认已经从离线推送中解析出当前推送的 userID 和 groupID。
如果 groupID 不为空,说明当前单击的是群聊离线消息。
如果 groupID 为空且 userID 不为空,说明当前单击的是单聊离线消息。
您需要在 AppDelegate 的 @implementation 中实现 - navigateToTUIChatViewController:groupID: 方法。
以下是示例代码,当单击离线推送后先获取当前的会话页面,然后通过会话页面 push 到聊天页面。您可以按需实现自己的跳转逻辑。
// 统一点击跳转
// 您可以直接拷贝当前的方法名到您的 AppDelegate 中
- (void)navigateToTUIChatViewController:(NSString *)userID groupID:(NSString *)groupID
{
// 示例: 点击推送通知后,首先跳转到会话列表页面,然后再会话列表页跳转到聊天页面
// 1. 获取当前 app 的 tabBarController
// 2. 获取 tabBarController 的 firstObject,也即 ConversationController
// 3. 执行 pushToViewController: 跳转到 ChatViewController
// 跳转到聊天页面后,支持点击左上角的返回按钮回退到主页面

UITabBarController *tab = [self getMainController];
if (![tab isKindOfClass: UITabBarController.class]) {
// 正在登录中
return;
}
if (tab.selectedIndex != 0) {
[tab setSelectedIndex:0];
}
self.window.rootViewController = tab;
UINavigationController *nav = (UINavigationController *)tab.selectedViewController;
if (![nav isKindOfClass:UINavigationController.class]) {
return;
}

UIViewController *vc = nav.viewControllers.firstObject;
if (![vc isKindOfClass:NSClassFromString(@"ConversationController")]) {
return;
}
if ([vc respondsToSelector:NSSelectorFromString(@"pushToChatViewController:userID:")]) {
[vc performSelector:NSSelectorFromString(@"pushToChatViewController:userID:") withObject:groupID withObject:userID];
}
}

高级用法

自定义登录/登出

TUIOfflinePush 默认使用了 TUICore 组件中的 TUILogin 提供的 login/logout 接口。如果您想自己实现 App/IM 的登录,不依赖 TUILogin,您需要在完成登录或登出操作后,手动调用 registerServiceunregisterService 接口。
说明
如果您使用了 TUILogin 的登录或登出,无需再调用上述两个接口。
// 您登录完成后的回调
- (void)onLoginSuccess
{
// 调用 TUIOfflinePush 组件的登录
[TUIOfflinePushManager.shareManager registerService];
}

// 您登出成功后的回调
- (void)onLogoutSuccess
{
// 调用 TUIOfflinePush 的登出
[TUIOfflinePushManager.shareManager unregisterService];
}

自定义离线内容解析

TUIOfflinePush 默认参与解析了离线推送的内容,并通过 - navigateToTUIChatViewController:groupID: 接口回调给业务层自定义跳转。
如果您想自定义解析离线推送的内容,或者查看收到的离线推送,可以在您的 AppDelegate 中实现 - processTUIOfflinePushNotification: 方法。
说明
关于方法的返回值
如果返回 YES,那么组件将不再执行默认解析逻辑,完全交由业务层自行处理。
如果返回 NO,组件会继续执行默认解析逻辑,继续回调 - navigateToTUIChatViewController:groupID: 方法。
// 统一收到离线推送
- (BOOL)processTUIOfflinePushNotification:(NSDictionary *)userInfo
{
// 自定义解析收到的 userInfo
NSLog(@">>> 您可以在此处自定义解析, %@", userInfo);

// 如果您不想执行 TUIOfflinePush 默认的解析逻辑,直接返回 YES
// 如果您只是想查看推送的内容,依然依赖 TUIOfflinePush 的默认解析及统一跳转逻辑,直接返回 NO
return NO;
}

常见问题

普通消息为什么收不到离线推送?

首先,请检查下 App 的运行环境和证书的环境是否一致,如果不一致,收不到离线推送。
其次,检查下 App 和证书的环境是否为生产环境。如果是开发环境,向苹果申请 deviceToken 可能会失败,生产环境暂时没有发现这个问题,请切换到生产环境测试。

自定义消息为什么收不到离线推送?

自定义消息的离线推送和普通消息不太一样,自定义消息的内容我们无法解析,不能确定推送的内容,所以默认不推送,如果您有推送需求,需要您在 sendMessage 的时候设置 offlinePushInfodesc字段,推送的时候会默认展示 desc 信息。

如何关闭离线推送消息的接收?

如果您想关闭离线推送消息的接收,可以通过设置 setAPNS 接口的 config 参数为 nil 来实现。该功能从5.6.1200 版本开始支持。

收不到推送,且后台报错 bad devicetoken。

Apple 的 deviceToken 与当前编译环境有关。如果 登录 IMSDK 后上传 deviceToken 到腾讯云 所使用的证书 ID 和 token 不一致,就会报错。
如果使用的是 Release 环境编译,则 - application:didRegisterForRemoteNotificationsWithDeviceToken: 回调返回的是发布环境的 token,此时 businessID 需要设置生产环境的 证书 ID
如果使用的是 Debug 环境编译,则- application:didRegisterForRemoteNotificationsWithDeviceToken: 回调返回的是开发环境的 token,此时 businessID 需要设置开发环境的 证书 ID
V2TIMAPNSConfig *confg = [[V2TIMAPNSConfig alloc] init];
/* 用户自己到苹果注册开发者证书,在开发者账号中下载并生成证书(p12 文件),将生成的 p12 文件传到腾讯证书管理控制台,控制台会自动生成一个证书 ID,将证书 ID 传入以下 busiId 参数中。*/
//推送证书 ID
confg.businessID = sdkBusiId;
confg.token = self.deviceToken;
[[V2TIMManager sharedInstance] setAPNS:confg succ:^{
NSLog(@"%s, succ, %@", __func__, supportTPNS ? @"TPNS": @"APNS");
} fail:^(int code, NSString *msg) {
NSLog(@"%s, fail, %d, %@", __func__, code, msg);
}];

iOS 开发环境下,注册偶现不返回 deviceToken 或提示 APNs 请求 token 失败?

此问题现象是由于 APNs 服务不稳定导致的,可尝试通过以下方式解决:
1. 给手机插入 SIM 卡后使用4G网络测试。
2. 卸载重装、重启 App、关机重启后测试。
3. 打生产环境的包测试。
4. 更换其它 iOS 系统的手机测试。