当应用在前台登录后,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
开头,例如sandbox
didFinishLaunchingWithOptions
中调用setXPushCertName:
设置正确的证书名