美文网首页
有关iOS 推送的总结

有关iOS 推送的总结

作者: yezhouxiang | 来源:发表于2017-01-25 17:32 被阅读172次

    首先有关于证书的问题我们这里就不一一讨论了,证书有关的可以在百度上一找一大把的,就是需要注意将环境区分开就可以了。

    这里可以将APP的运行状态分成两种状态:

    1、APP处于前台的状态,顾名思义,就是APP在运行的状态下,处于一个长连接的一个状态下。

    2、当APP被杀死之后,或者是处于非活跃的状态。非活跃的状态一般的可以理解为是APP在进入后台后一定的时间里所处于的状态,具体的可以参考我的另一篇文章iOS 后台机制。那么我们现在要讨论的就是关于APP处于非活跃(被杀死)的状态下的时候,收到远程推送的处理。当APP的长链接被断开的时候,Server 会通过APNs将消息以远程推送的形式下发到客户端。 此状态下如果有人给该用户发送消息,服务器会根据deviceToken和推送证书将消息发送到苹果推送服务器,苹果服务器会将该消息推送到客户端。

    一、开发环境与生产环境

    苹果推送服务器区分开发环境(Development)和生产环境(Production),两个环境的服务器不同,使用的 P12 证书不同,完全隔离。

    有几点需要注意的。

    1、deviceToken是唯一标识客户端的凭证,所以必须上传应用服务器才能使用远程推送。

    2、模拟器收不到远程推送。

    3、越狱的设备APNs服务不能保证,所以不一定能收到远程推送。

    4、APNs 使用BundleID区分 App,使用通配符BundleID的 App 将无法使用远程推送。

    二、现在当我们在不同的情况下接收到通知的时候:

    在不同的系统中对远程推送的处理是不一样的。这里先讨论的是iOS 6和iOS 7以后的,iOS 10的改变很大,我们可以单独讨论:

    1. 客户端在前台。通常是弹窗

    ● iOS6 的-(void) application: didReceiveRemoteNotification:被调用

    ● iOS7 的-(void) application: didReceiveRemoteNotification: fetchCompletionHandler:被调用

    所以,为了兼容iOS6.通常的做法是,在-(void) application: didReceiveRemoteNotification: fetchCompletionHandler:中调用-(void) application: didReceiveRemoteNotification: 方法。

    ● push处理模块,判断一下程序是否是活跃 [UIApplication sharedApplication].applicationState == UIApplicationStateActive。

    进而判断是否需要弹出对话框。

    2. 客户端在后台,但是还活着

    大致原理同第一条,注意处理是否弹框。

    3. 客户端被杀死的状态,进来push消息;滑动(点击)push消息调起客户端。

    ● iOS 6调用 -(void) application: didFinishLaunchingWithOptions:带有launchDictionary,里面包含了push消息

    需要简单处理一下,获取真正的内容[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]

    ● iOS 7以后调用两个方法:

    -(void) application: didFinishLaunchingWithOptions:

    -(void) application: didReceiveRemoteNotification: fetchCompletionHandler:

    但是这样就有一个坑。在项目中也遇到了,特别是在推一个H5的页面的时候,你会发现可以进入到相关的页面,但是当返回或者是进入下一层级就会出现视图加载到window上去了;iOS7以上,这样做就重复处理同一个push消息了。

    【解决】:由于只有iOS7以上都会调用-(void) application: didReceiveRemoteNotification: fetchCompletionHandler:方法。

    那么,为了兼容iOS6:在-(void) application: didFinishLaunchingWithOptions:中只处理iOS6。

    4.现在的APP都有一个启动图过程。如果push消息过来,APP正好是被杀死状态,且假设启动后有启动图。

    这中push拉起APP后是直接处理push的,不弹框。

    【解决】首先想到的方法是:暂存这个push消息,然后等启动图完了再展示push内容。注意,等到启动图完成,再使用push模块

    [UIApplication sharedApplication].applicationState == UIApplicationStateActive就不好用了,因为此时APP应该是活跃的了,就需要弹框了。所以,需要push模块支持一个强制不弹框的接口。

    三、iOS 10推送的适配

    1.首先需要到项目工程的target中的Capabilities中打开后台的开关

    2.iOS 10中新增了UserNotifications Framework

    当APP在前台的时候调用的是下面的这个方法,而不是原来的那个方法了

    - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void(^)(UNNotificationPresentationOptions))completionHandler

    当退出APP的时候调用的方法是:

    - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler

    而且在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中注册通知的方法也是不一样的:

    if(IOS10) {

    UNUserNotificationCenter *center =[UNUserNotificationCenter currentNotificationCenter];        

    center.delegate =self;  

     [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError *_Nullable error) {if (!error) {                NSLog(@"succeeded!");            }        }];  

    回调方法中,进行数据的处理:

    - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler {

    NSDictionary*userInfo =response.notification.request.content.userInfo;

    //消息处理

    }

    对于本地通知来说并没有什么太大的改变

    -(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification

    相关文章

      网友评论

          本文标题:有关iOS 推送的总结

          本文链接:https://www.haomeiwen.com/subject/nvmtittx.html