当应用在前台登录后,IM消息通过长连接到达应用。此时,当应用进入后台时,IM消息通过苹果的APNS通道到达。您必须完成以下步骤,才能够收到APNS推送:
iOS的推送依赖于Apple Push Notification Service,即APNS系统。因此要想获得消息推送能力,开发者需要上传iOS Push证书:
您可以在开发者中心上传服务器推送证书,如下图所示:
设置并上传DeviceToken章节中,设置给OpenIMSDKproduction作为生产环境的证书名,因为OpenIMSDK运行时默认使用production名称上传DeviceTokensand开头关于APNS的更多信息,请参考:Apple的开发者文档
**注意:**在iOS10 以上,你需要在Xcode中手动开启push,如图所示:
开发者首先需要在App中向系统申请DeviceToken。
注意:如果你已经实现了申请DeviceToken的代码,则可以跳过这一步。
你需要根据不同的iOS SDK版本及不同的iOS系统,通过不同的函数申请DeviceToken,一般可以在AppDelegate的didFinishLaunchingWithOptions函数中添加如下代码:
/// 需要区分iOS SDK版本和iOS版本。
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)])
{
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeAlert|UIUserNotificationTypeSound) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else
#endif
{
/// 去除warning
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
#pragma clang diagnostic pop
} 对于iOS8及以上系统,您需要额外添加这个函数实现:
/// iOS8下申请DeviceToken
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerForRemoteNotifications)]) {
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
}
#endif 现在,当你的app获取到DeviceToken时,IMSDK会自动得到该DeviceToken,你无须手动传给IMSDK。
注意点:
application:didFinishLaunchingWithOptions:函数中手动设置当前打包证书及provision所对应的推送证书名- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[[[YWAPI sharedInstance] getGlobalPushService] setXPushCertName:@"production1"];
/// 其他初始化代码
}
请务必确保xcode打包所使用的证书及provision、你设置的证书名以及该证书名对应的推送证书这三者是匹配的。IMSDK的服务端会根据你设置的证书名,查找对应的推送证书进行推送。
成功获取到DeviceToken,登录IM成功后,设备控制台会打印DeviceToken上传成功的Log,请确认是否有该日志
现在你只需要在-[AppDelegate didFinishLoadingWithOptions:]函数中调用IYWPushService的setHandlePushBlockV4:方法,在其中根据回调传入的参数,即可完成APNS消息的处理。
注意:如果你使用快速集成文档进行集成,你会在SPKitExample.m中看到`exampleHandleAPNSPush`方法,请参考该方法在Demo中的调用时机。
例如:
/**
* 您需要在-[AppDelegate application:didFinishLaunchingWithOptions:]中第一时间设置此回调
* 在IMSDK截获到Push通知并需要您处理Push时,IMSDK会自动调用此回调
*/
- (void)exampleHandleAPNSPush
{
__weak typeof(self) weakSelf = self;
[[[YWAPI sharedInstance] getGlobalPushService] addHandlePushBlockV4:^(NSDictionary *aResult, BOOL *aShouldStop) {
BOOL isLaunching = [aResult[YWPushHandleResultKeyIsLaunching] boolValue];
UIApplicationState state = [aResult[YWPushHandleResultKeyApplicationState] integerValue];
NSString *conversationId = aResult[YWPushHandleResultKeyConversationId];
Class conversationClass = aResult[YWPushHandleResultKeyConversationClass];
if (conversationId.length <= 0) {
return;
}
if (conversationClass == NULL) {
return;
}
if (isLaunching) {
/// 用户划开Push导致app启动
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.3f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if ([self exampleIsPreLogined]) {
/// 说明已经预登录成功
YWConversation *conversation = nil;
if (conversationClass == [YWP2PConversation class]) {
conversation = [YWP2PConversation fetchConversationByConversationId:conversationId creatIfNotExist:YES baseContext:weakSelf.ywIMKit.IMCore];
} else if (conversationClass == [YWTribeConversation class]) {
conversation = [YWTribeConversation fetchConversationByConversationId:conversationId creatIfNotExist:YES baseContext:weakSelf.ywIMKit.IMCore];
}
if (conversation) {
[weakSelf exampleOpenConversationViewControllerWithConversation:conversation fromNavigationController:[weakSelf conversationNavigationController]];
}
}
});
} else {
/// app已经启动时处理Push
if (state != UIApplicationStateActive) {
if ([self exampleIsPreLogined]) {
/// 说明已经预登录成功
YWConversation *conversation = nil;
if (conversationClass == [YWP2PConversation class]) {
conversation = [YWP2PConversation fetchConversationByConversationId:conversationId creatIfNotExist:YES baseContext:weakSelf.ywIMKit.IMCore];
} else if (conversationClass == [YWTribeConversation class]) {
conversation = [YWTribeConversation fetchConversationByConversationId:conversationId creatIfNotExist:YES baseContext:weakSelf.ywIMKit.IMCore];
}
if (conversation) {
[weakSelf exampleOpenConversationViewControllerWithConversation:conversation fromNavigationController:[weakSelf conversationNavigationController]];
}
}
} else {
/// 应用处于前台
/// 建议不做处理,等待IM连接建立后,收取离线消息。
}
}
} forKey:self.description ofPriority:YWBlockPriorityDeveloper];
} 请按照如下CheckList依次检查每一步是否正确:
didFinishLaunchingWithOptions函数中调用setXPushCertName:接口设置了证书名setXPushCertName:设置的证书名、在百川后台上传证书时设置的证书名、以及所上传的推送证书,这四项都是匹配的目前OpenIM已经支持使用沙箱环境测试推送:
sand开头,例如sandboxdidFinishLaunchingWithOptions中调用setXPushCertName:设置正确的证书名