背景:最近连续几周被项目中的APNS实现所折腾,服务器和客户端都存在坑,服务器升级导致一堆bug,修复完后客户端这边收到消息通知但是不符合业务逻辑,在项目经理再三沟通和协调的下,在服务器和客户端同事们的全力排查代码逻辑终于完成此功能点。
一、实现原理:
苹果推送的实现原理就是有一个触发者(服务器)触发用户关联信息,通过APNs精确传递到用户的设备上,具体以消息推送的形式呈现出来。
二、项目实践
1、客户端项目配置
在项目对应target栏目中capabilities的Push Notifications打开。
在项目对应target栏目中General Signing(release)选择你要发布的证书
2、 客户端代码
在AppDelegate.m文件中需要做如下配置
2.1注册远程推送
这里需要兼容iOS10、iOS8、iOS8以下系统注册远程推送
-(void)registerForRemoteNotification
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {
#ifdef __IPHONE_10_0
//进行用户权限的申请
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:UNAuthorizationOptionBadge|UNAuthorizationOptionSound|UNAuthorizationOptionAlert|UNAuthorizationOptionCarPlay completionHandler:^(BOOL granted, NSError * _Nullable error) {
//在block中会传入布尔值granted,表示用户是否同意
if (granted) {
//如果用户权限申请成功,设置通知中心的代理
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
}
}];
#endif
}
UIApplication *application = [UIApplication sharedApplication];
if([application respondsToSelector:@selector(registerUserNotificationSettings:)]){
UIUserNotificationType notificationTypes = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:notificationTypes categories:nil];
[application registerUserNotificationSettings:settings];
}
#if !TARGET_IPHONE_SIMULATOR
//ios8 注册APNS
if ([application respondsToSelector:@selector(registerForRemoteNotifications)]){
[application registerForRemoteNotifications];
}else{//ios8以下
UIRemoteNotificationType notificationTypes = UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert;
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:notificationTypes];
}
#endif
}
2.2注册远程推送返回代理
注册远程推送成功
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
将注册成功的deviceToken 注册到推送服务器中,可以获取到一个唯一的标志码
注册远程推送失败
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
将error 传给相关模块执行再次申请注册远程推送
2.3获取到远程推送的几个场景
需要兼容IOS 7以及IOS7以上系统
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
#ifdef __IPHONE_7_0
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler
其中userInfo是由推送服务器发的内容
aps = {
alert = "sdhsflsflsaksakaskgkasglkasdjglkadsglknasdgdksal";//推送内容
badge = 3;//应用右上角数字
sound = "msg.mp3";//推送的声音
};
//一下是服务器自定义的json数据格式
}
/*__IOS_AVAILABLE(10.0) 必须使用xcode8
App在前台的时候收到推送执行的回调方法*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
/*__IOS_AVAILABLE(10.0) 必须使用xcode8
App在后台的时候,点击推送信息,进入App后执行的 回调方法*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler
业务逻辑就是将收到的远程推送的内容(自定义字段表示内容)展现在该app中。
三、总结
所谓总结就是分享我自己从这个坑里爬出来的感受
我所负责的app有两个推送模式,远程推送和本地IM推送,我负责远程推送,他负责本地IM消息管理,其实推送devicetoken已经在IM那边已经注册了,但是我还重复注册了一次,因为我之前的项目没有集成IM,所以就顺理成章按照之前的做法做了,得到的结果就是我可以收到远程推送,就是我同事负责的消息管理模块没有任何关于我远程推送的消息记录,后来经过调试发现远程推送和本地推送的标识码不一样,解决方法是以IM注册为主,远程推送和本地消息管理共用一个标识码进行业务上操作。
其实这个问题本身不是一个很大的问题,关键在于开发人员双方沟通不够顺畅,当时项目经理开了一个电话会议后将所涉及的开发人员召集在一起全力解决。
代码实现结果其实是团队沟通成效的体现。
参考文献
1.《APNs Overview》https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1
2.《Maintaining Your Signing Identities and Certificates》https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingCertificates/MaintainingCertificates.html
3.《Payload Key Reference》https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1
4.《手把手教你配置苹果APNS推送服务》https://my.oschina.net/hejunbinlan/blog/494721