博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS 推送总结
阅读量:5112 次
发布时间:2019-06-13

本文共 7012 字,大约阅读时间需要 23 分钟。

苹果推送分为两种情况,一种时离线推送,一种是在线推送(包括后台在线推送);

然后有两种推送模式:1.走苹果APNS推送。2.走第三方推送

其中走苹果推送肯定可以应对两种推送情况;

然后走第三方推送的话,在线推送(包括后台在线推送)可以实现,但是离线推送就无法实现了(不可能让程序一直在后台运行,那样太费手机)

因此我们推送一般都是用的苹果APNS推送.

 

然后就是看看推送总体流程:

1、首先是客户端注册APNS推送(客户端跟APNS Server要deviceToken(用来区别设备的标识))。
2、客户端接受deviceToken。
3、客户端将deviceToken发送给后台服务器程序。
4、后台服务器程序向APNS服务发送消息(根据deviceToken区别给哪个设备发消息)。
5、APNS服务将消息发送给iPhone应用程序(根据deviceToken发给相应设备)。
 
下面来看具体开发流程
1、首先是客户端注册APNS推送(客户端跟APNS Server要deviceToken(用来区别设备的标识))。
要注册APNS推送,需要到苹果证书申请网站(即打包证书注册网站)注册APNS证书,然后要重新生成齿轮文件(即Provisioning Profiles文件);
如果有CSR文件则注册时使用原先的,没有则重新生成个就行了(如下图,点击后填邮箱、姓名然后保存到本地磁盘就生成了CSR文件)

有CSR文件后开始注册APNS证书

 

上图那个Apple Push Services 即是生产环境下注册的APNS证书,下面那个就是开发环境下的APNS证书,个人感觉生产环境下的证书就能当开发环境下的证书使,不过为了区别还是分开比较规范。

 

证书注册完,下载下来双击就安装了。 如下图所示方框内即为两个APNS证书

 

然后需要在用地的证书右键->导出 ,生成p12文件给后台服务器,因为后台服务器给APNS发消息也是要证书认证的;(后台服务器是测试环境则配development的证书,正式环境则配生产证书)

 

 

 

 

 

到此APNS证书配置结束
证书弄好后开始代码进行客户端注册注册APNS推送
在每次启动

didFinishLaunchingWithOptions方法中,进行判断用户设备是否已经注册,因为第一次启动需要注册同时需要存本地一个deviceToken的值通常存UserDefaults中即可,再次启动就检测下是否已经注册,已经注册就直接使用已经注册的deviceToken就行

其中 kEZApnsToken 为自己宏定义deviceToken的在UserDefaults中存储的Key

- (void)checkApns{    //已经注册    if ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications]) {        if ([[UIApplication sharedApplication] currentUserNotificationSettings].types  == UIRemoteNotificationTypeNone) {            //如果用户打开了推送 但是设置解锁后的提醒样式为"无"并且没有打开声音或者应用图标标记任何一个的时候 系统判断的是用户关闭推送(现在暂时没有更好的方法解决这一问题,所以暂时任务此种情况为用户关闭了推送)            // 用户关闭了推送        }else{            //用户打开了推送 如果本地设备的token为空 则重新注册推送//            NSString *token =[[NSUserDefaults standardUserDefaults] objectForKey:kEZApnsToken];//            NSLog(@"%@",token);            if (![[NSUserDefaults standardUserDefaults] objectForKey:kEZApnsToken]) {                                UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound) categories:nil];                                [[UIApplication sharedApplication] registerUserNotificationSettings:settings];                                [[UIApplication sharedApplication] registerForRemoteNotifications];            }else{                [self syncApns];  //注册过了将deviceToken发送给后台服务器  同时通知服务器用户推送是打开状态,可以进行推送            }                    }    //未注册    }else{        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound) categories:nil];                [[UIApplication sharedApplication] registerUserNotificationSettings:settings];                [[UIApplication sharedApplication] registerForRemoteNotifications];    }}
- (void)syncApns{         NSString *apnsToken = [[NSUserDefaults standardUserDefaults] objectForKey:kEZApnsToken];         if ([[UIApplication sharedApplication] currentUserNotificationSettings].types  == UIRemoteNotificationTypeNone) {             //如果用户打开了推送 但是设置解锁后的提醒样式为"无"并且没有打开声音或者应用图标标记任何一个的时候 系统判断的是用户关闭推送(现在暂时没有更好的方法解决这一问题,所以暂时任务此种情况为用户关闭了推送)             // 用户关闭了推送             /*将deviceToken及用户关闭推送的状态发送给后台服务器,此时不能推送*/         }else{               /*将deviceToken及用户允许推送的状态发送给后台服务器,此时可以推送*/         }}
2、客户端接受deviceToken。
3、客户端将deviceToken发送给后台服务器程序。
#pragma mark - APNS 获取tokenAPNS- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {        NSString *apnstoken = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<" withString:@""]stringByReplacingOccurrencesOfString:@">" withString:@""]                           stringByReplacingOccurrencesOfString:@" " withString:@""];    [self saveApnsToken:apnstoken]; //存储deviceToken,并检测用户是否允许推送,将状态同步给后台服务器}
//获取token失败回掉的方法- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {    NSLog(@"获取设备token失败");}
- (void)saveApnsToken:(NSString *)data{    [[NSUserDefaults standardUserDefaults] setObject:data forKey:kEZApnsToken];        [[NSUserDefaults standardUserDefaults] synchronize];        [self syncApns];   //检测用户是否允许推送,同时将用户推送允许状态及deviceToken同步到后台服务器,方便后台服务器推送}
 
4、后台服务器程序向APNS服务发送消息(根据deviceToken区别给哪个设备发消息)。
array("alert" => 'message',"badge" => 2,"sound"=>'default')); //推送方式,包含内容和声音$$ctx = stream_context_create();//如果在Windows的服务器上,寻找pem路径会有问题,路径修改成这样的方法://$pem = dirname(__FILE__) . '/' . 'apns-dev.pem';//linux 的服务器直接写pem的路径即可stream_context_set_option($ctx,"ssl","local_cert","apns-dev.pem");$pass = "xxxxxx";stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);////此处有两个服务器需要选择,如果是开发测试用,选择第二名sandbox的服务器并使用Dev的pem证书,如果是正式发布,使用Product的pem并选用正式的服务器$fp = stream_socket_client("ssl://gateway.push.apple.com:2195", $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);$fp = stream_socket_client("ssl://gateway.sandbox.push.apple.com:2195", $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);if (!$fp) {echo "Failed to connect $err $errstrn";return;}print "Connection OK\n"; $payload = json_encode($body);$msg = chr(0) . pack("n",32) . pack("H*", str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload; echo "sending message :" . $payload ."\n";fwrite($fp, $msg); fclose($fp);?>

 

5、APNS服务将消息发送给iPhone应用程序(根据deviceToken发给相应设备)。
如果是在线推送进入程序后会直接调用下面方法。通过下面方法进行推送操作处理。
 
#pragma mark  - 用户切换到后台收到推送时点击通知栏调用的方法  用户处于前台工作时接受到推送调用的方法- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{//    application.applicationState == UIApplicationStateActive;//程序处在前台    [UIApplication sharedApplication].applicationIconBadgeNumber = 0;   /*从userinfo中获取自己服务器设定好的字段比如:一个通知的ID,然后从请求后台服务器获取相应数据进行相应操作(页面跳转、弹框等等)*/}

 

userinfo中数据如下: 

从userinfo中获取自己服务器设定好的字段比如:一个通知的ID,然后从请求后台服务器获取相应数据进行相应操作(页面跳转、弹框等等)

 

 

如果是离线推送,点击推送进入程序后会调用didFinishLaunchingWithOptions,此时推送信息会包含在didFinishLaunchingWithOptions的参数launchOptions中,格式如下:

我们需要根据key值取出推送信息

NSDictionary *pushInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];    /*从userinfo中获取自己服务器设定好的字段比如:一个通知的ID,然后从请求后台服务器获取相应数据进行相应操作(页面跳转、弹框等等)     注意:由于在执行didFinishLaunchingWithOptions方法时,客户端UI界面等工作可能还没执行,直接进行UI操作可能会崩溃,所以此处进行UI操作最好加个延迟执行,或者在页面加载出来后初始页面中进行UI操作     */

注意:由于在执行didFinishLaunchingWithOptions方法时,客户端UI界面等工作可能还没执行,直接进行UI操作可能会崩溃,所以此处进行UI操作最好加个延迟执行,或者在页面加载出来后初始页面中进行UI操作,否则可能崩溃

 

 

 

 

 补充:

当然在客户端代码写完后,客户端可以先将与后台服务器交互的代码注释掉,客户端利用一些第三方工具进行APNS测试。

这里使用的是SmartPush,

下载链接 - 

 

下载后直接运行就行:

 

如图所示

选择证书时选择注册的证书即可;

然后deviceToken需要运行一下程序,然后第二步获取真机的deviceToken后将其打印填入SmartPush中即可;

然后PayLoad中可以填写json数据,除了"aps"字段外,我们可以添加自己后台服务器字段(按需求)

然后环境根据证书选择(一般都选测试,因为真机调试)。

最后点击连接服务器,然后推送即可;

然后就走步骤5、了;

 

其中 APNS所接受的json数据格式大概例如:

{     "aps":{        "alert":{           "title":"标题", // iOS7、8设置无效,iOS9一般设置为appName         "subtitle":"子标题", // 一般使用title就能满足需求         "body":"内容"      },      "badge":1, //角标数      "sound":"default", //声音      "userinfo":{ //通知内容信息           "playid":"123",           "username":"tom",           "sex":1      }   }}

 

更加详细格式可查看苹果官网 - 

转载于:https://www.cnblogs.com/Ganggang888/p/7268384.html

你可能感兴趣的文章
Weka中数据挖掘与机器学习系列之基本概念(三)
查看>>
Win磁盘MBR转换为GUID
查看>>
大家在做.NET B/S项目的时候多用什么设技术啊?
查看>>
Java SE和Java EE应用的性能调优
查看>>
Android设计模式系列--原型模式
查看>>
免费的论文查重网站
查看>>
C语言程序第一次作业
查看>>
leetcode-Sort List
查看>>
中文词频统计
查看>>
了解node.js
查看>>
想做移动开发,先看看别人怎么做
查看>>
Eclipse相关集锦
查看>>
虚拟化架构中小型机构通用虚拟化架构
查看>>
继承条款effecitve c++ 条款41-45
查看>>
linux 内核参数VM调优 之 参数调节和场景分析
查看>>
HTML+CSS学习笔记(九)
查看>>
笑谈人生的哲理和智慧
查看>>
【BZOJ2286】【SDOI2011】消耗战 [虚树][树形DP]
查看>>
【Foreign】Game [博弈论][DP]
查看>>
3.13上午 听力BLOCK3、4 写作形容词,连字符,名词动化大词
查看>>