iOS APNS接收逻辑梳理

2020-03-30  本文已影响0人  Tenloy

# 第一步:设置 注册远程通知


[[UIApplication sharedApplication] registerForRemoteNotifications];
如果使用极光的话,[JPUSHService registerForRemoteNotificationConfig:entity delegate:self]; 包装实现了上述api的功能

# 第二步:处理 注册远程通知成功、失败回调


/**
 Typically, the system calls this method only after you call your WKExtension object’s registerForRemoteNotifications method, but WatchKit may call it under other rare circumstances. For example, WatchKit calls the method when the user launches an app after setting up the watch using a different device’s backup. In this case, the app doesn’t know the new device’s token until the user launches it.
 如果这个方法不调用,那么APNS通知是收不到的,当然`应用内消息`可以照常使用
 */
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken API_AVAILABLE(ios(3.0));
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error API_AVAILABLE(ios(3.0));

有时候,会出现上面两个方法都不调用,导致推送接收不到。极光打印出Not get deviceToken yet. 可以从以下几个问题排查:

  1. 推送证书
  2. 是真机,且应用推送权限开启
  3. 确定调用了registerForRemoteNotification(不管是极光的还是原生的)
  4. 网络问题
    可以参考极光的文档:https://docs.jiguang.cn/jpush/client/iOS/ios_faq/
    我的解决方案:飞行模式开启-关闭,然后就好使了(更新:飞行模式、关机重启已经解决不了这个网络问题了,只能设置-还原网络设置了,好使了...)
极光:JPush iOS 调试思维导图

极光在能正确获取到deviceToken但收不到推送的情况:
我们是使用alias进行推送的,极光的逻辑是:

# 第三步:处理 设备接收到通知的回调


## iOS 10之前

/**
 * 方法1: 兼容iOS 3 — iOS 10
 * 过期后,分别由方法4 5来代替处理`用户可见远程通知`,由方法3来代替处理`静默远程通知silent remote notifications`
 * If a remote notification arrives while your app is active, WatchKit calls this method to deliver the notification payload. 即只有当APP处于活跃状态时,收到远程通知,才会触发这个方法。
 * 活跃分为:前台、后台活跃,当处于前台时不显示通知alert,直接触发这个方法(iOS 10之后如果想在前台显示alert,需要实现方法4,iOS10之前,则需要自己发local notification来显示alert)。当处于后台活跃状态时,会显示,点击通知才会触发这个方法
 * 注意:如果实现了方法3,这个方法就不会被回调
*/
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;

/**
 * 方法2: 兼容iOS 4 — iOS 10
 * 过期后, 分别由方法4 5来代替处理本地通知
 * If a local notification arrives while your app is active, WatchKit calls this method to deliver the notification payload. 更详细的没测试
*/
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;


/**
 * 方法3: 兼容iOS 7及以后
 * Tells the delegate that a background notification has arrived. 即APP处于挂起、kill状态都会触发这个方法。触发 与alert显示情况与方法1相同:处于前台时,不alert,直接调用;挂起或kill状态,点击通知会触发
 * 实现此方法来处理传入的后台通知。当通知到达时,系统会启动您的应用程序或将其从挂起状态唤醒,您的应用程序会收到在后台运行的一小段时间。
 * 可以使用后台执行时间处理通知并下载其相关内容。一旦完成对通知的处理,就必须调用fetchCompletionHandler完成处理程序。您的应用程序有30秒的挂钟时间来处理通知并调用处理程序,时间到了系统会终止您的应用程序。请尽可能快地调用处理程序,因为系统会跟踪应用程序后台通知的运行时间、功耗和数据成本。
 * 后台通知是低优先级的,系统根据目标设备的功率考虑限制这些通知。APNs不保证设备会收到推送通知,而那些在处理后台通知时消耗大量能量或时间的应用程序可能不会收到后台时间来处理未来的通知。
 * 应用程序因为远程通知而启动或恢复,也将调用此方法。注意,此方法与方法1冲突,如果实现了此方法,则不会调用方法1
 */
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;

## iOS 10及以后

/**
 * 方法4: 兼容iOS 10及以后
 * 只有当应用程序位于前台时,才会在收到通知时调用该方法。如果方法没有实现,或者没有及时调用处理程序,则前台不会显示通知。应用程序可以选择以声音、徽章、警报和/或在通知列表中显示通知。取决于通知中的信息是否对用户可见
 * 实现了该方法后,方法1 3会收到影响,在前台时,不再是不显示+直接触发方法1 3,而是触发本方法,点击之后触发方法1 3
*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler;

/**
 * 方法5: 兼容iOS 10及以后
 * 当用户通过打开应用程序、取消通知或选择UNNotificationAction来响应通知时,会调用该方法。必须在应用程序从application:didFinishLaunchingWithOptions:返回之前设置delegate。
*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler;

/**
 * 方法6: 兼容iOS 12及以后
 * 极光的解释:当从应用外部通知界面或通知设置界面进入应用时,该方法将回调。
*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center openSettingsForNotification:(nullable UNNotification *)notification;

# 测试接收到APNS时,API的调用


  实现方法1345
    前台
      显示+调用willPresent  点击调用didReceiveNotificationResponse
    后台/非active状态
      显示+谁都不调  点击调用didReceiveNotificationResponse

  实现方法135
    前台
      不显示+调用didReceiveRemoteNotification:fetchCompletionHandler
    后台/非active状态
      显示+谁都不调  点击调用didReceiveNotificationResponse

  实现方法134
    前台
      显示+调用willPresent  点击调用didReceiveRemoteNotification:fetchCompletionHandler
    后台/非active状态
      显示+谁都不调  点击调用didReceiveRemoteNotification:fetchCompletionHandler

  只实现方法1 3
    前台
      不显示+调用didReceiveRemoteNotification:fetchCompletionHandler
    后台/非active状态
      显示+谁都不调  点击调用didReceiveRemoteNotification:fetchCompletionHandler

# 总结


# 静默推送(silent/background remote notification)


iOS 7在推送方面最大的变化就是允许,应用收到通知后在后台(background)状态下运行一段代码,可用于从服务器获取内容更新。功能使用场景:(多媒体)聊天,Email更新,基于通知的订阅内容同步等功能,提升了终端用户的体验。用户不允许应用的推送,静默推送依然会送达用户设备。

如果只携带content-available: 1,不携带任何badge,sound 和消息内容等参数,alert字段可以有,但value必须为空,则可以不打扰用户的情况下进行内容更新等操作即为“Silent/Background Remote Notifications”,如果不携带此字段则是普通的Remote Notification。可以查看苹果文档Pushing Background Updates to Your App

客户端设置:需要在Xcode 中修改应用的Capabilities ,在Background Modes里面勾选Remote notifications(推送唤醒)

限制与注意
上一篇 下一篇

猜你喜欢

热点阅读