zoukankan      html  css  js  c++  java
  • Push:iOS基于APNS的消息推送

    APNS,即Apple Push Notification Service苹果推送通知服务,是苹果的服务器。

    推送通知可以分为三个阶段:

    第一阶段:应用程序把要发送的消息、目的iPhone的标识打包,发给APNS。

    第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。

    第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。

     

    1. Push的三个步骤

    如下图所示:

    (1)Push服务应用程序把要发送的消息、目的iPhone的标识打包,发给APNS;

    (2)APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发到iPhone;

    (3) iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。

     具体如下图5个步骤,无论是iPhone客户端跟APNS,还是Push服务器和APNS都需要通过证书进行连接的:

    2. native端代码实现

    推送消息时,不同时机点击,代码调用情况:
     
    1. 当程序处于关闭状态收到推送消息时,点击图标会调用- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 这个方法,那么消息给通过launchOptions这个参数获取到。

    2. 当程序处于前台工作时,这时候若收到消息推送,会调用- (void)application:(UIApplication*)application

    didReceiveRemoteNotification:(NSDictionary *)userInfo这个方法。

    3. 当程序处于后台运行时,这时候若收到消息推送,如果点击消息或者点击消息图标时,也会调用- (void)application:(UIApplication*)application

    didReceiveRemoteNotification:(NSDictionary *)userInfo这个方法。

    4. 当程序处于后台运行时,这时候若收到消息推送,如果点击桌面应用图标,则不会调用didFinishLaunchingWithOptions和didReceiveRemoteNotification方法,所以无法获取消息。

    (1)注册通知(当然,程序关闭,推送消息时点击图标的逻辑也应该写在这里)

    // 1.注册通知
      #import <UserNotifications/UserNotifications.h>
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
        if ([[UIDevice currentDevice].systemVersion floatValue] >8.0){
          //iOS8 - iOS10
              [[UIApplication sharedApplication] registerForRemoteNotifications]; 
          [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:
                      UIUserNotificationTypeAlert |       
                      UIUserNotificationTypeSound |
                      UIUserNotificationTypeBadge categories:nil]];    }
    else if ([[UIDevice currentDevice].systemVersion floatValue] < 8.0) {     //iOS8系统以下     [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge |
    UIRemoteNotificationTypeAlert
    |
    UIRemoteNotificationTypeSound];    }          
    return YES; }

     补充知识点:

      iOS 程序启动时总会调用application:didFinishLaunchingWithOptions:,其中第二个参数launchOptions为NSDictionary类型的对象,里面存储有此程序启动的原因。

      • 若用户直接启动,lauchOptions内无数据;
      • 若由其他应用程序通过openURL:启动,则UIApplicationLaunchOptionsURLKey对应的对象为启动URL(NSURL),UIApplicationLaunchOptionsSourceApplicationKey对应启动的源应用程序的bundle ID (NSString);
      • 若由本地通知启动,则UIApplicationLaunchOptionsLocalNotificationKey对应的是为启动应用程序的的本地通知对象(UILocalNotification);
      • 若由远程通知启动,则UIApplicationLaunchOptionsRemoteNotificationKey对应的是启动应用程序的的远程通知信息userInfo(NSDictionary);
      • 其他key还有UIApplicationLaunchOptionsAnnotationKey,UIApplicationLaunchOptionsLocationKey,
        UIApplicationLaunchOptionsNewsstandDownloadsKey。

         所以,可以根据上面的key将lauchOptions取出来:

    //apple push启动
    NSDictionary *applePushDic = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    //本地通知启动
    UILocalNotification *localNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];

    (2)获得Device Token

    // 2.获得Device Token
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{
    NSLog(@"regisger success:%@", pToken);   
        // 注册成功,将deviceToken保存到应用服务器数据库中,因为在写向ios推送信息的服务器端程序时要用到这个
    }
    
    // 3.获得Device Token失败
     - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    }
    

      如果总是失败的话,即push总是到didFailToRegisterForRemoteNotificationsWithError:里面。除了我们知道的模拟器不能接受apple push,报的3010错误之外,经常会遇到“Error: Error Domain=NSCocoaErrorDomain Code=3000 "no valid 'aps-environment' entitlement string found for application" ”这个错误。解决步骤主要有以下三步:

      (2.1)确保证书开通了push的功能:

           可以在开发者网站上的App ID下查看,其Development、Distribution是否都已经开通了Push的功能。Development Push是你用Xcode调试时用的Debug使用的,Distribution的Push是正式包使用的。

          一个Bundle ID开通了Development、Distribution的push是要生成对应的两个证书的。此时,正式证书的类型是"Apple Push Services",Development对应的证书的类型是"APNs Development iOS"。你的pp文件后面也要用的是对应的证书文件。

      (2.2)确保配置文件信息正确:

          证书开通了push之后,你的配置文件要使用的是你的对应的证书,对应的app id等,都要对应起来。本地如果重新安装配置文件的话,确保老的删掉后,重新安装,重新在Target》build setting》Provision Profile下选择你刚安装的证书。能重新选择才能确定这里选择的是新的而不是旧的。PS:删除老的provision文件的方法,可以在Xcode》Preference》Accounts》对应的Apple Id,对应的Team》View Details》Provision Profile,然后点击右键就可以选择在finder中查看,可以删除对应的Provision Profile文件了。

      (2.3)确保Xcode的push设置正确:

          Target》Capabilities下面,找到你的Push Notification,确保你的push功能开着。并且"Add the Push Notification feature to your App ID"和"Add the Push Notifications entitlement to your entitlements file"这两个steps是ok的。

    (3)处理推送消息

    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{ 
     //4. 处理推送消息 
    }
  • 相关阅读:
    Alibaba 阿里组件 nacos注册中心 gateway网关 flowable流程引擎 vue.js前后分离 spring cloud微服务
    Java JDBC 连接 MySQL8 数据库
    Java设计模式【命令模式】
    Spring Boot内嵌tomcat关于getServletContext().getRealPath获取得到临时路径的问题
    Java代理模式学习 (Proxy模式)
    Java单例模式浅析 (Singleton模式)
    由歌词引发的模式思考之中篇(AbstractFactory模式)
    Java模拟FilterChain的实现 (Chain Of Responsibility模式)
    由歌词引发的模式思考之上篇(FactoryMethod模式)
    由歌词引发的模式思考之下篇(模拟Spring的BeanFactory)
  • 原文地址:https://www.cnblogs.com/Xylophone/p/5996005.html
Copyright © 2011-2022 走看看