陈江川

邮箱:jiangchuanc@gmail.com

iOS推送遇到的坑

最近在做推送这块,遇到了一些比较深的坑,所以记下来,供大家参考,如果有问题或者需要补充的请随时联系我。公司使用的是个推,但推送原理是一样的。

iOS突然接收不到推送

使用第三方SDK,都需要上传推送证书,推送证书分为调试和发布两种,我们在调试阶段使用的是调试推送证书,怎么生成可以去google。
然后导入第三方SDK,按照第三方提供的文档进行配置,这些就不说了。之前APP不论是在前台还是后台状态下,都可以接收到推送。但是这周准备发布的版本,APP在后台可以收到透传消息,但是没有系统的推送提示,感觉很奇怪,实在想不出原因,然后联系了个推的技术支持,找到问题所在。下面是关键部分!!!

  1. 当APP在前台,第三方服务器直接推送消息给我们,这是没有系统推送提示的!!!
  2. 当APP在后台,clientID离线状态,第三方推送的消息才会经过苹果的APNS服务器,这时才会有系统推送提示!!!

我的问题就是,APP切换到后台,clientID并没有处于离线状态(这个可以自行在个推官网查询当前clientID状态),所以没有系统推送提示。现在知道原因,但是不知道为何会这样。然后我找到APP进入后台时调用的方法:

- (void)applicationDidEnterBackground:(UIApplication *)application 

在该方法中,有如下代码:

 UIBackgroundTaskIdentifier sBackgroundTask = [[UIApplication sharedApplication] 
                            beginBackgroundTaskWithExpirationHandler:sExpirationHandler];
 ......
 [application setKeepAliveTimeout:600 handler: ^{
 }];

看到这知道了什么原因,这几行代码是为了让APP在后台能继续的工作(最多10分钟)。所以APP不会被挂起,因此clientID在这个时间段不会处于离线状态,最终获取到的推送是第三方直接推过来的,不会有系统推送提示!!!

如何解决

因为APP功能特殊,需要在后台继续运行。所以不能把这些代码注释掉,另辟蹊径。上面有说到,APP无论在前/后台都是可以接收到推送的,只是都是由第三方服务器直接推送过来,不走苹果的APNS。

解决思路:
既然能收到透传消息,那么当APP处于后台的时候,把接收到的透传信息通过本地推送推给系统,这样就会有系统推送提示,下面是伪代码:

// 这个是个推接收透传消息回调方法,其他的第三方SDK也会有类似的方法
- (void) GeTuiSdkDidReceivePayloadData ... {
    // APP在后台
    if (APP == background) {
        // 创建本地推送,
        // 这里要注意,如果noti属性alertBody为null/nil,那么不会弹出系统推送提示。只会有声音提示
        UILocalNotification *noti = [UILocalNotification new];
        // 把创建的本地推送推出去
        [presentLocalNotificationNow:noti];
    }
}

// 在这个代理方法中可以收取到本地的推送消息
- (void)application:(UIApplication *)application
didReceiveLocalNotification:(UILocalNotification *)notification;

iOS10推送遇到的坑

ios10推送新添加了一个代理UNUserNotificationCenterDelegate,提供了两个方法代理方法:

// App在前台获取到通知调用的方法
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler;
         
// 点击通知进入App时触发。iOS10之前,点击通知是系统处理点击事件;
// iOS10开始,点击通知需要手动处理事件。
// 比如跳到相应的界面,这里就需要我们自己处理。
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)())completionHandler;

« iOS - VoIP推送<一> git-flow常用命令 »