今天遇到个客户端没有收到服务器APNS推送的问题,联调了一下发现,是服务端与客户端的device token不一致造成的,
而不一致的原因是客户端没有及时把device token发送到服务器,
客户端是在- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken NS_AVAILABLE_IOS(3_0);
方法中将device token发送到服务器的,
所以问题是app又是什么时候才调用这个方法呢?
打断点试了试发现:
在调用UIApplication.shared.registerForRemoteNotifications()
方法后,系统才会调用
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken NS_AVAILABLE_IOS(3_0);
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error NS_AVAILABLE_IOS(3_0);
其中一个
也就是说,如果没有主动调用UIApplication.shared.registerForRemoteNotifications()
方法,那客户端就不会再次吧device token发送到服务器了。
理论上这个device token不会轻易变,但也不是不会变
(https://stackoverflow.com/questions/40169404/does-a-ios-push-notification-device-token-change有提到,当用户擦除数据或者系统升级时,就会变,我自己的感觉是,隔一段时间就会变。。。)
所以苹果的建议是,每次启动app都向apns服务器获取device token 并发送到自己的服务器。
但考虑到如果用户刚安装app的时候就弹出推送通知的提醒,90%会被拒掉,所以我们产品的设计是,当用户需要推送时,再提示用户开启推送,比如用户订阅某个订阅号时,告诉用户可以开启推送来第一时间知道该订阅号有更新。
所以这里就需要一个判断,app启动时,如果用户还没有开启过通知,就不要调用UIApplication.shared.registerForRemoteNotifications()
注册通知,如果用户已经开启了通知,那每次启动都要调用这个方法更新device token;
注意:如果app还没有注册过通知,即app的通知状态是notDetermined
,那系统设置的app设置里面都不会有通知设置的选项,这时候调用UIApplication.shared.registerForRemoteNotifications()
会弹出系统的“XXX想要给您发送通知”那个alert出来,如果是已经注册过了,不管状态是denied
还是authorized
,都不会在弹那个alert出来了,但是还是会触发系统的didRegisterForRemoteNotificationsWithDeviceToken
或者didFailToRegisterForRemoteNotificationsWithError
方法
网友评论