推送通知(一)-iOS<10的推送通知

简介

  1. 推送通知跟NSNotification区别
    1. NSNotification是抽象的,不可见的
    2. 推送通知是可见的(能用肉眼看到)
  2. iOS中提供了2种推送通知
    1. 本地推送通知(Local Notification)
    2. 远程推送通知(Remote Notification)
  3. 推送通知的作用
    1. 可以让不在前台运行的app,告知用户app内部发生了什么事情
  4. 推送通知的呈现效果
    1. 在屏幕顶部显示一块横幅(显示具体内容)
    2. 在屏幕中间弹出一个UIAlertView(显示具体内容)
    3. 在锁屏界面显示一块横幅(锁屏状态下,显示具体内容)
    4. 更新app图标的数字(说明新内容的数量)
    5. 播放音效(提醒作用)
  5. 推送通知呈现的效果设置.
    1. 显示横幅还是UIAlertView,取决于用户的设置
    2. 手机->设置->通知中心-> 相应应用-> 选择通知样式.
    3. 在该界面,用户也可以决定是否要开启以下4个功能:
      1. 显示App图标数字
      2. 播放音效
      3. 锁屏显示
      4. 显示在“通知中心”
  6. 推送通知的使用细节
    1. 发出推送通知时,如果程序正运行在前台,那么推送通知就不会被呈现出来
    2. 点击推送通知后,默认会自动打开发出推送通知的app
    3. 不管app打开还是关闭,推送通知都能如期发出

本地推送通知

  1. 定义:
    1. 顾名思义,就是不需要联网就能发出的推送通知(不需要服务器的支持)
  2. 本地推送通知的使用场景
    1. 常用来定时提醒用户完成一些任务,比如:清理垃圾、记账、买衣服、看电影、玩游戏

如何发送本地通知

  1. 创建本地推送通知对象

     UILocalNotification *ln = [[UILocalNotification alloc] init];
    
  2. 设置本地推送通知属性
    1. 推送通知的触发时间(何时发出推送通知)

       @property(nonatomic,copy) NSDate *fireDate;
      
    2. 推送通知的具体内容

       @property(nonatomic,copy) NSString *alertBody;
      
    3. 锁屏界面显示的小标题(完整小标题:“滑动来” + alertAction)

       @property(nonatomic,copy) NSString *alertAction;
      
    4. 音效文件名(有通知时发送声音)

       @property(nonatomic,copy) NSString *soundName;
      
    5. app图标数字

       @property(nonatomic) NSInteger applicationIconBadgeNumber;
      
  3. 调度本地推送通知(调度完毕后,推送通知会在特地时间fireDate发出)

     [[UIApplication sharedApplication] scheduleLocalNotification:ln];
    
  4. 获得被调度的所有本地推送通知(等待发出的通知)
    1. (已经发出且过期的推送通知就算调度结束,会自动从这个数组中移除)
     @property(nonatomic,copy) NSArray *scheduledLocalNotifications;
    
  5. 取消调度本地推送通知

     - (void)cancelLocalNotification:(UILocalNotification *)notification;
     - (void)cancelAllLocalNotifications;
    
  6. 立即发出本地推送通知(使用价值:app在后台运行的时候)

     - (void)presentLocalNotificationNow:(UILocalNotification *)notification;
    

本地推送通知的其他属性

  1. 每隔多久重复发一次推送通知

     @property(nonatomic) NSCalendarUnit repeatInterval;
    
  2. 点击推送通知打开app时显示的启动图片
    1. 注意: 该字符串无论写什么,都会显示app最初设置的那个启动图片
    2. 使用场景: 当程序是杀死状态时,点击通知打开app时,默认会看到启动图片,但是当程序在后台时,点击时看不到启动图片的,因此为了让用户也看到启动图片,就可以设置这个属性
     @property(nonatomic,copy) NSString *alertLaunchImage;
    
  3. 附加的额外信息

     @property(nonatomic,copy) NSDictionary *userInfo;
    
  4. 时区

     @property(nonatomic,copy) NSTimeZone *timeZone;
    (一般设置为[NSTimeZone defaultTimeZone] ,跟随手机的时区)
    

点击本地推送通知

  1. 当用户点击本地推送通知,会自动打开app,这里有2种情况
  2. app并没有关闭,一直隐藏在后台
    1. 让app进入前台,并会调用AppDelegate的下面方法(并非重新启动app)

       - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;
      
    2. 方法说明:

      1. 应用程序从前台或者后台进入都会调用该方法
  3. app已经被关闭(进程已死)
    1. 启动app,启动完毕会调用AppDelegate的下面方法

       - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
      
    2. 该方法说明:

      1. launchOptions参数:
        1. 点击本地/远程/URL(应用间跳转)等通知时,当程序在后台或者在前台进入时,该值都为null,但是程序由杀死状态进入时,有值,该值就是发出的通知
      2. launchOptions 常用的key
        1. UIApplicationLaunchOptionsLocalNotificationKey:
          1. 通过本地通知把我打开,该值就是本地通知的值
        2. UIApplicationLaunchOptionsRemoteNotificationKey:
          1. 远程通知
        3. UIApplicationLaunchOptionsURLKey:
          1. URL应用建跳转
  4. 当拿到本地通知时,通常作如下处理:
    1. 根据当前app进入的不同状态,进行不同的处理
    2. application.applicationStatekey值获取进入状态:
      1. UIApplicationStateActive : 应用程序在前台
      2. UIApplicationStateInactive: 应用程序由后台进入前台
      3. UIApplicationStateBackground: 应用程序在后台

iOS8的配置

  1. 在iOS8.0以后,如果要使用本地通知需要得到用户的许可
  2. 具体操作,在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法中加入以下代码:

     //判断iOS版本,iOS8.0以上版本需要的到用户的许可
     if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
            
         UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert |UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil];
         [application registerUserNotificationSettings:settings];
     }
    

代码举例:

  1. 控制器中发送通知(延时5秒)

     #import "ViewController.h"
    
     @interface ViewController ()
     @property (nonatomic,assign) NSInteger number;
     @end
        
     @implementation ViewController
        
        
     //延迟5秒发送本地通知
     - (IBAction)locationNotificationAction:(id)sender {
         //1.创建本地通知
         UILocalNotification * localNote = [[UILocalNotification alloc] init];
         //2.设置本地通知内容
         //2.1设置通知发出的时间
         localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
         //2.2 设置通知的内容
         localNote.alertBody = @"吃饭了吗???";
         //2.3 设置滑块的文字
         localNote.alertAction = @"快点";
         //2.4 决定alertAction是否生效
         localNote.hasAction = YES;
         //2.5 设置点击通知的启动图片(随便写)
         localNote.alertLaunchImage = @"随便写";
         //2.6 设置alertTitle
         localNote.alertTitle = @"777777777777";
         //2.7 设置有通知时的音效
     //    localNote.soundName = @"buyao.wav";
         //也可以用系统自带的
         localNote.soundName = UILocalNotificationDefaultSoundName;
         //2.8 设置应用程序图标右上角的数字
         localNote.applicationIconBadgeNumber = self.number++;
         //2.9 设置额外信息(比如:告诉app点击通知时跳转到哪一个界面)
         localNote.userInfo = @{@"type" : @1 };
            
         //3.调用本地通知
         [[UIApplication sharedApplication] scheduleLocalNotification:localNote];
     }
        
     @end#import "ViewController.h"
        
     @interface ViewController ()
     @property (nonatomic,assign) NSInteger number;
     @end
        
     @implementation ViewController
        
        
     //延迟5秒发送本地通知
     - (IBAction)locationNotificationAction:(id)sender {
         //1.创建本地通知
         UILocalNotification * localNote = [[UILocalNotification alloc] init];
         //2.设置本地通知内容
         //2.1设置通知发出的时间
         localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
         //2.2 设置通知的内容
         localNote.alertBody = @"吃饭了吗???";
         //2.3 设置滑块的文字
         localNote.alertAction = @"快点";
         //2.4 决定alertAction是否生效
         localNote.hasAction = YES;
         //2.5 设置点击通知的启动图片(随便写)
         localNote.alertLaunchImage = @"随便写";
         //2.6 设置alertTitle
         localNote.alertTitle = @"777777777777";
         //2.7 设置有通知时的音效
     //    localNote.soundName = @"buyao.wav";
         //也可以用系统自带的
         localNote.soundName = UILocalNotificationDefaultSoundName;
         //2.8 设置应用程序图标右上角的数字
         localNote.applicationIconBadgeNumber = self.number++;
         //2.9 设置额外信息(比如:告诉app点击通知时跳转到哪一个界面)
         localNote.userInfo = @{@"type" : @1 };
            
         //3.调用本地通知
         [[UIApplication sharedApplication] scheduleLocalNotification:localNote];
     }
        
     @end
    
  2. AppDelegate配置/处理

        
     - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
         //设置程序右上角的数字
         [application setApplicationIconBadgeNumber:0];
         //判断iOS版本,iOS8.0以上版本需要的到用户的许可
         if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
                
             UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert |UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil];
             [application registerUserNotificationSettings:settings];
         }
            
         //launchOptions 点击本地/远程/URL(应用间跳转)等通知时,当程序在后台或者在前台进入时,该值都为null,但是程序又杀死状态进入时,有值,该值就是发出的通知
         //launchOptions 常用的key
        // UIApplicationLaunchOptionsLocalNotificationKey,通过本地通知把我打开,该值就是本地通知的值
        // UIApplicationLaunchOptionsRemoteNotificationKey,远程通知
        // UIApplicationLaunchOptionsURLKey ,URL应用建跳转
         if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {
             //获得本地通知
             UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
     //        NSNumber *type = notification.userInfo[@"type"];
             //有type可以判断跳转到哪一个界面
             UILabel *redView = [[UILabel alloc] init];
             redView.frame = CGRectMake(0, 0, 200, 300);
             redView.numberOfLines  = 0;
             redView.font = [UIFont systemFontOfSize:12.0];
             redView.backgroundColor = [UIColor redColor];
             redView.text = [NSString stringWithFormat:@"%@",notification];
             [self.window.rootViewController.view addSubview:redView];
         }
         return YES;
     }
     //应用程序从前台或者后台进入都会调用该方法
     -(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
         //针对应用程序在后台的时候进行跳转
         //UIApplicationStateActive,应用程序在前台
     //    UIApplicationStateInactive,应用程序由后台进入前台
     //    UIApplicationStateBackground应用程序在后台
         if (application.applicationState == UIApplicationStateInactive) {
             //进行界面的跳转:跳转到指定的界面
             //通知的额外信息可以再这里获得
             UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
             redView.backgroundColor = [UIColor redColor];
             [self.window.rootViewController.view addSubview:redView];
         }
     }
    

远程推送通知

  1. 定义:
    1. 就是从远程服务器推送给客户端的通知(需要联网)
    2. 远程推送服务,又称为APNs(Apple Push Notification Services
  2. 与本地的区别
    1. 本地推送通知是app自己给自己发送的.
    2. 远程是由服务器发送过来的.
  3. 为什么需要远程推送通知?
    1. 传统获取数据的局限性
      1. 只要用户关闭了app,就无法跟app的服务器沟通,无法从服务器上获得最新的数据内容
    2. 远程推送通知可以解决以上问题
      1. 不管用户打开还是关闭app,只要联网了,都能接收到服务器推送的远程通知
  4. 所有的苹果设备,在联网状态下,都会与苹果的服务器建立长连接
    1. 什么是长连接
      1. 只要联网了,就一直建立连接
    2. 长连接的作用
      1. 时间校准:(保证手机时间是最准的)
      2. 系统升级:(提示用户系统升级)
      3. 查找我的iPhone(iPhone丢了,可以通过苹果官网查找出来在哪)
    3. 长连接的好处
      1. 数据传输速度快
      2. 数据保持最新状态
  5. 推送通知的基本原理
    1. 用户app关闭状态下
    2. qq服务器将消息推送给苹果的APNS服务器
    3. 苹果的APNS服务器通过devicetoken找到对应设备,并且推送给相应的应用qq
    4. 如下图:
      图1
  6. 远程推送的详细流程
    图1
    说明:
    1. 客户端发送设备的UDID和应用的Bundle Identifier给APNs服务器
      1. UDID: 苹果手机的唯一标识
      2. Bundle Identifier: 客户端的唯一标识
      3. 也由此可以看到,苹果的APNS服务器直接可以通过这个deviceToken就可以找到对应设备和设备上的对应应用
    2. 经苹果APNS加密生成一个deviceToken
    3. 发送当前用户的deviceToken和用户的标志(比如id或者qq)
    4. qq服务器将数据存进数据库
    5. 有人发送消息:李四的手机(昵称:李四 QQ:56789),发给张三(QQ12345):吃饭没?
    6. qq服务器去数据库查询张三的deviceToken
    7. 通知苹果服务器APNS:deviceTokoen:888;body:李四:吃饭没?
    8. 苹果服务器APNS通过deviceToken找到张三现在的设备推送消息

开发步骤

  1. 开发iOS程序的推送功能, iOS端需要做的事
    1. 请求苹果获得deviceToken
    2. 得到苹果返回的deviceToken
    3. 发送deviceToken给公司的服务器
    4. 监听用户对通知的点击
  2. 调试iOS的远程推送功能, 必备条件:
    1. 真机
    2. 调试推送需要的证书文件
      1. aps_development.cer : 某台电脑就能调试某个app的推送服务
      2. iphone5_qq.mobileprovision : 某台电脑就能利用某台设备调试某个程序
  3. 发布具有推送服务的app
    1. aps_production.cer : 如果发布的程序中包含了推送服务,就必须安装这个证书
    2. qq.mobileprovision : 某台电脑就能发布某个程序

请求苹果获的deviceToken

  1. 在app启动方法中注册远程通知

         - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
         //1. 在程序启动那一刻向苹果的APNS服务器获取devicetoken
         //1.1 判断iOS版本,iOS8.0以上版本需要的到用户的许可
         if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
             //申请用户许可
             UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil];
             [application registerUserNotificationSettings:settings];
             //1.2 注册远程通知(调用该方法就是向苹果的apns服务器发送该设备的udid和bundle id,返回deviceToken)
             [application registerForRemoteNotifications];
         }else{//iOS7不需要请示用户,直接注册
             [application registerForRemoteNotificationTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound];
         }
         return YES;
     }
    
  2. 监听deviceToken的获取情况

     //2. 在这拿到苹果返回devicetoken发送给服务器    
     -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
         // 将DeviceToken传给服务器
         NSLog(@"%@", deviceToken.description);
     }
        
     //向apns请求失败
     -(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
         NSLog(@"===请求devicetoken失败==%@",error);
     }
    
    1. 会发现在在这里拿不到deviceToken
    2. 如果这么容易就能拿到,苹果的APNS服务器都爆了,那么多设备都可以访问了.
    3. 因此,苹果需要你买开发者账号,然后配置证书
  3. 配置证书

    1. 结论: (推送必备条件,必须告诉苹果)
      1. 哪个应用(app)需要推送
      2. 在哪台电脑上调试(发布)推送服务
      3. 在哪些设备(手机)上调试推送服务
      4. 在哪台电脑上用哪台设备调试哪个应用(app)
      5. 在哪台电脑上发布哪个应用(app)
    2. 配置步骤
      1. 用你购买的开发者账号,登录苹果的开发者中心,然后进入证书中心
      2. 告诉苹果是哪个应用需要推送
        1. 注册一个appid:
          1. 进入App IDs->添加->输入你的appid名字(随便起名,比如:ZhonghuaRemoteTest)和你的appID(即bundle identifier)->continue->register->done
        2. 给你刚才注册的app添加推送服务:
          1. 进入App IDs->找到你刚才注册的app点击->会看到一个列表,这个列表展示了你的这个app都有哪些服务(通常默认的只有:Game Center和In-App-Purchase这两个服务,绿色表示可用,黄色/没选择表示不可用)->点解编辑(Edit)->勾选你想要的服务->Push Notifications->done
      3. 告诉苹果哪台电脑需要调试这个app:
        1. 仍然回到上一步的Edit->找到Push Notifications->Development SSL Certificate->Create …-> Continue->ChooseFile…
        2. 这里就是要拿到你的是那一台电脑,即你的电脑的唯一标志(CSR文件)
        3. 如何生成CSR文件:
          1. 打开钥匙串-> 顶部工具栏中->钥匙串访问->证书助理->从证书颁发机构请求证书->邮件地址随便写/常用名(随便写)/勾选存储到磁盘-> 确定->保存到桌面即可
        4. 选择刚才保存的CSR文件->continue->down即可->得到一个aps_development.cer
      4. 告诉苹果哪台电脑需要发布这个app:
        1. 同理,重复第3步(但是不需要再次生成CSR了)…Production SSL Certificate->…得到aps.cer
      5. 告诉苹果哪台设备需要调试:
        1. 注册设备: 进入Devices,点击加号,将设备添加进去(一般情况下只要你用这个开发者账号调试过真机,他就会自动注册到这里面了)
      6. 生成描述文件:
        1. 调试描述文件: 告诉苹果,在哪台电脑上用哪台设备调试那个应用(app)
          1. 点击provisioning Profiles中的All->添加-> 勾选iOS APP Development-> contuine-> 选择你的APP ID->continue->选择调试证书(注意:这里是调试证书,可不是调试推送证书哦)->选择设备(selectAll)->取一个名字->down即可.
        2. 发布描述文件: 告诉苹果,在哪台电脑上可以发布哪个应用(app)
          1. 点击provisioning Profiles中的All->添加-> 勾选 App Store ->contuine-> 选择你的APP ID->continue->选择发布证书(注意:这里是发布证书,可不是发布推送证书哦)->取一个名字->down即可.
        3. 打包测试描述文件ADHoc:(用于蒲公英上传打包使用) 告诉苹果,在哪台电脑上可以打包哪个应用(app),并且那些设备可以下载调试
          1. 点击provisioning Profiles中的All->添加-> 勾选Ad Hoc -> 选择你的APP ID->continue->选择发布证书(注意:这里是发布证书,可不是发布推送证书哦)->选择设备(selectAll)->取一个名字->down即可
        4. 从上面的区别就可以看出: 生成调试/打包测试描述文件时,要选择你要调试的设备,生成发布描述文件时不需要选择设备
      7. 双击安装上面的所有证书(除了CSR)
      8. iOS10 配置(注意啊!!!!!!!!)
        1. 在工程Target中的Push Notifications 的开关要开启!否则死活获取不到token,打开后会发现项目中多了一个”项目名.entitlements”文件夹
    3. 经过以上步骤,再次运行程序,就可以获取到deviceToken了
    4. 证书说明:(此时,应该有8个证书)
      1. CSR: mac唯一标志
      2. ios_development.cer 调试证书
      3. ios_distribution.cer 发布证书
      4. aps_development.cer 调试推送证书
      5. aps.cer 发布推送证书
      6. 3个描述文件
      7. 注意: 注意生成调试/发布证书的过程这里就不在多说

发送deviceToken给公司的服务器

  1. 由于远程推送需要服务器来搭配测试,为了方面别人写好了一个运行在mac上的服务器
  2. PushMeBaby是一款用来测试ANPs的开源Mac项目
    1. 它充当了服务器的作用,用法非常简单
    2. 它负责将内容提交给苹果的APNs服务器,苹果的APNs服务器再将内容推送给用户的设备
  3. PushMeBaby的使用步骤
    1. 直接注释掉不要的错误

        //#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
      
    2. 填写必要信息
      1. 打开ApplicationDelegate.m文件
      2. deviceToken:用于找到设备的令牌(填入你获取到的devicetoken,注意不带”<>”)
      3. payload:推送的内容
        1. 这个是公司服务器推送给苹果APNS的标准格式:

            @"{\"aps\":{\"alert\":\"This is some fancy message.\",\"badge\":1}}";
          
        2. alert:是你要推送的内容
        3. badge: 推动的未读消息数量
    3. 将推送的调试证书(aps_development.cer)改为名apns.cer,添加到PushMeBaby项目中
      1. 注意:由此可以看出,服务器端必须有你的推送证书,这也就是为什么极光推送需要你上传P12的原因
    4. command + R启动程序,然后点击Push
    5. 接下来就可以在设备上接收到远程推送通知

SmartPush更好使用

监听用户对通知的点击

注意: 用户点击通知才会拿到通知,直接点击app是拿不到通知的.

  1. 方法1:

     - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
    
    1. 当程序杀死状态,点击本地通知调用
  2. 方法2:

     -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
    
    1. iOS7之前用这个方法(<iOS7)
    2. (程序在前台/在后台)前后台都会调用,杀死状态不会调用,只会调用方法1
    3. 实现后台调用:(即不点击通知也会调用)
      1. 推送的消息中包含content-available字段: 后台时,不点击也会调用
  3. 方法3:

     //iOS7之后用这个方法(>iOS7)
     -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
    
    1. 是在iOS 7之后新增的方法,可以说是2的升级版本,如果app最低支持iOS 7的话可以不用添加 2了。
    2. 如果实现了该方法,2方法不会调用
    3. 使用条件
      1. 打开后台模式-> capablititles->background Modes->打开->勾选Remote notifications
      2. 告诉系统是否有新的更新->completionHandler(UIBackgroundFetchResultNewData);
    4. 调用时刻:
      1. (程序在前台/在后台)前后台都会调用,杀死也会调用,先调用1,在调用3
      2. 实现后台调用:(即不点击通知也会调用)
        1. 推送的消息中包含content-available字段: 后台时,不点击也会调用
    5. 与方法2的区别是: app关闭(杀死)状态下,点击推送通知也会调用该方法.
  4. 测试代码如下:

     @implementation AppDelegate
    
    
     - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
         //1. 在程序启动那一刻向苹果的APNS服务器获取devicetoken
         //1.1 判断iOS版本,iOS8.0以上版本需要的到用户的许可
         if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
             //申请用户许可
             UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil];
             [application registerUserNotificationSettings:settings];
             //1.2 注册远程通知(调用该方法就是向苹果的apns服务器发送该设备的udid和bundle id,返回deviceToken)
             [application registerForRemoteNotifications];
         }else{//iOS7不需要请示用户,直接注册
             [application registerForRemoteNotificationTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound];
         }
        // 5.1 当程序杀死状态,点击本地通知调用
         if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
             //跳转
             //获得本地通知
             UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
             //有type可以判断跳转到哪一个界面
             UILabel *redView = [[UILabel alloc] init];
             redView.frame = CGRectMake(0, 0, 200, 300);
             redView.numberOfLines  = 0;
             redView.font = [UIFont systemFontOfSize:12.0];
             redView.backgroundColor = [UIColor redColor];
             redView.text = [NSString stringWithFormat:@"%@",notification];
             [self.window.rootViewController.view addSubview:redView];
         }
            
         return YES;
     }
     //2. 监听苹果返回devicetoken
     /*
      注意: 仅仅通过第一步是拿不到devicetoken的.
      要不然苹果的APNS服务器都爆了,那么多设备都可以访问了.
      因此,苹果需要你买开发者账号,然后配置证书
      3. 配置证书
      */
     -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
         //4.将DeviceToken传给服务器
         NSLog(@"%@", deviceToken.description);
     }
     //向apns请求失败
     -(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
         NSLog(@"===请求devicetoken失败==%@",error);
     }
     //5. 接收远程推送
     //前后台点击进入时调用
     //iOS7之前用这个方法(<iOS7)
     /*
      调用时刻:
      点击通知:前后台都会调用,杀死不会调用,只会调用1
      推送的消息中包含content-available字段: 后台时,不点击也会调用
      */
     -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
          NSLog(@"------调用了99999999");
         if (application.applicationState == UIApplicationStateBackground) {
             //进行界面的跳转
             //通知的额外信息可以再这里获得userInfo
             UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(150, 0, 100, 100)];
             redView.backgroundColor = [UIColor blueColor];
             [self.window.rootViewController.view addSubview:redView];
         }
     }
     /*
      是在iOS 7之后新增的方法,可以说是2的升级版本,如果app最低支持iOS 7的话可以不用添加 2了。
      如果实现了该方法,2方法不会调用
      点击应用程序图标无法获取推送消息,只有点击通知才会得到
         
      使用条件
      1.打开后台模式-> capablititles->background Modes->打开->勾选Remote notifications
      2.告诉系统是否有新的更新->completionHandler(UIBackgroundFetchResultNewData);
         
      调用时刻:
      点击通知:前后台都会调用,杀死也会调用,先调用1,在调用3
      推送的消息中包含content-available字段: 后台时,不点击也会调用
        
      */
     //iOS7之后用这个方法(>iOS7)
     -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
         //可以在这个方法中做些数据下载操作,争取在用户点击通知前,就将数据下载完毕
         //进行界面的跳转
         //通知的额外信息可以再这里获得userInfo
         UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(150, 0, 100, 100)];
         redView.backgroundColor = [UIColor blueColor];
         [self.window.rootViewController.view addSubview:redView];
         NSLog(@"------调用了");
         //下载完毕要调用completionHandler这个block,告知下载完毕
         completionHandler(UIBackgroundFetchResultNewData);
     }
     @end
    

极光推送

  1. 什么是极光推送
    1. 一套远程推送解决方案,支持android和iOS两个平台
    2. 它能够快捷地为iOS App增加推送功能,减少集成APNs需要的工作量、开发复杂度
    3. 安卓做推送不需要经过Google服务器,可以通过自己的服务器直接推送
  2. 为何使用极光推送?
    1. 将远程通知推送中那个专门接收deviceToken的服务器替换成(不自己建了)第三方服务器->极光推送服务器.
    2. 通过第三方的服务器(极光推送)来给后台推送消息,而不是通过自己公司的服务器.一般第三方服务器都有个管理的后台(图形化界面).
  3. 原理:若要发送消息,到该第三方的后台中把推送的消息写上去,然后发送推送,那么该第三方服务器会自动推送消息(内部实现:极光服务器把你需要推送的消息内容发送给苹果的apns,然后苹果的apns在推送给你的设备),我们代码操作时,就是操作极光推送的服务器了
  4. 整体流程实现:
    1. 服务器方单向发送推送消息:(后台操作)
      1. 服务器将消息(消息+devicetoken)发送给极光服务器-极光服务器根据(devicetoken)到内存中找到对应的app->极光服务器将消息与devicetoken发送给Apns — apns发送推送给相应的设备(手机)
    2. 客户端双向发消息(患者端->医生端):
      1. 患者端通过(自己服务器)服务器提供接口,将消息传递给服务器,服务器向医生端推送消息(内部实现与上面一样)
  5. 集成简介:
    1. 创建应用:
      1. 百度-极光推送- 注册账号-登录-创建应用- 填写应用名称-上传图标(可以不传,不是推送给用户的图标,而是当该账户下有多个应用时,为了方便区分展示的图片)->此时可以拿到AppKey(有用)
    2. 到处调试/发布推送证书P12
      1. 打开钥匙串->找到当前应用的调试推送与发布推送证书
      2. 分别右击导出(切记千万不要展开!!!)->设置密码->导出2个p12
    3. 配置iOS应用(同样安卓也得配置)
      1. 点击推送设置->iOS->上传调试/发布推送P12证书->输入密码->保存->显示已验证,则成功了
    4. 下载SDK,根据开发文档集成即可.
  6. 极光推送上传P12注意事项 iOS开发极光引用后台(官网上)显示,开发证书没有通过验证,是否重新上传证书? 解决办法
    1. 当前上传的P12证书密码输入错误,
    2. 证书导出的时候展开了证书,把个人私钥导了出来,导证书的时候请不要展开证书
    3. 当前上传的证书环境不对,如: 在上传开发证书地方上传了生产证书
    4. 该证书已在本账号的其他应用使用
    5. 现上传的证书与当前应用已上传成功的证书BundleID不一致.
    6. 注意到处的是调试推送证书开发推送证书,千万不要导成调试证书开发证书了(这俩导出来是给其他同事公用的p12)
  7. 利用JPush发送通知
    1. JPush会自动记录和管理所有安装过此app的设备deviceToken
    2. 利用JPush,可以轻易地给所有设备发送远程推送通知
Table of Contents