iOS推送

1.推送过程简介

8325A44F-2047-44C1-8B0B-CFCA4DB2C2E4.png

< 1.iPhone向APNS索取DeviceToken
<2.APNS返回Token
<3.iPhone将获取的Token上传至App对应的服务器
<4.服务器将Token和推送的要闻上传至APNS
<5.APNS将消息推送给iPhone用户

  1. 用到的证书文件及生成过程

    (1)certSigningRequest文件,该文件在MAC系统中生成,用于在Apple网站上申请推送证书文件。
    生成过程:
    打开应用程序中的“钥匙串访问”软件,从菜单中选择 “钥匙串访问”-》“证书助理”-》“从证书颁发机构请求证书”,邮箱和名称随便填写,然后选择保存到磁盘,就可以在本地生成一个CertificateSigningRequest.certSigningRequest文件。

    (2)注册一个支持push的app id,后面会用到。
    生成过程:
    进入developer.apple.com,选择member center - Certificates, Identifiers & Profiles - Identifiers- App Ids,然后选择注册app id,设置appid名称,同时,app id suffix一栏必须选择explicit app id,然后设置bundle id,最后勾选 App Services中的 Push Notifications,这样就可以注册一个支持push的aphid。

(3) 推送证书cer文件,该文件在developer.apple.com中生成,用于生成服务端需要的文件。
生成过程:
进入developer.apple.com,选择member center - Certificates, Identifiers & Profiles - Certificates,然后选择创建certificate,类型分为Development和Product。这里以Development为例,选择Apple Push Notification service SSL (Sandbox) ,然后下一步,选择之前生成的支持push的AppId,然后下一步,提交之前创建的CSR文件,再下一步就可以生成cer文件,然后保存到本地。

(4)生成服务端使用的证书文件。如果是使用网上的mac 版PushMeBaby工具,在mac机器上进行推送消息的发送,那么有上面的cer文件就够了。如果是使用PHP、java/c#开发自己的服务端,那么还需要将上面的cer文件做一个转换,生成pem文件或者p12文件。

   生成php用的pem文件过程为:
    首先双击前面保存的cer文件,此时会打开“钥匙串访问”软件,里面会出现一个Apple Development  IOS push services证书,一个公用密钥和一个专用秘钥,秘钥的名称与证书助理中填写的名称一致。
  选中证书,导出为 apns-dev-cert.p12 文件
  选中专有秘钥,导出为apns-dev-key.p12文件
  通过终端命令将这些文件转换为PEM格式:
  openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
  openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12
  最后, 需要将两个pem文件合并成一个apns-dev.pem文件,此文件在连接到APNS时需要使用:
  cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem

  生成java/c#用的p12文件过程为:

  openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
  openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12
  openssl pkcs12 -export -in apns-dev-cert.pem -inkey apns-dev-key.pem -certfile CertificateSigningRequest.certSigningRequest -name "push" -out push.p12

(5)生成XCODE使用的provisioning文件,该文件用于真机调试。
生成过程:
进入developer.apple.com,选择member center - Certificates, Identifiers & Profiles - Provisioning Profiles,然后选择创建Provisioning file,接着选择iOS App Development ,下一步选择AppId,选中之前建立的支持push的appid,接着下一步选择支持push的certificate,下一步勾选需要支持的device id,最后一步设置provisioning文件的文件名,这样provisioning文件就生成了。

3. 服务端的开发
 (1)如果只是希望在mac电脑上测试一下消息的推送,可以使用PushMeBaby工具,使用起来比较简单。该工具是开源的,可以从https://github.com/stefanhafeneger/PushMeBaby 下载,代码的执行过程实际上就是设置一下SSL证书,然后连接APNS,接着发送JSON数据。由于要处理SSL逻辑,因此代码稍微多点。在使用工具时,将工程资源中的cer文件替换成自己的cer文件,然后将代码中的deviceToken替换成自己设备的deviceToken即可。


 (2)使用php开发服务端
   由于php已经内置了ssl模块,因此使用php连接APNS服务器来发送json的过程实际上是很简单的,代码如下:

该文件可以放到服务器中通过浏览器来访问,也可以通过命令行的方式来解释执行,代码为:$ php -f Pusher.php

复制以下代码
<?php
$deviceToken= ‘自己的deviceToken'; //没有空格
$body = array("aps" => 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);
?>

4. 客户端的开发
 (1)下载前面建立的cer文件和provisioning文件,双击,导入到xcode中,在build setting中code signing一栏里选择这两个文件的名称,这样就可以将支持push的app部署到真机中。
 

 (2)处理推送消息
       客户端对推送消息的处理分两种情况:
      一. 在App没有运行的情况下,系统收到推送消息,用户点击推送消息,启动App。此时,不会执行前面提到的          didReceiveRemoteNotification函数,而是在App的applicationDidFinishLaunching函数中处理推送,通过以下代码可以获取推送消息中的数据: NSDictionary *userInfo =[launchOptionsobjectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];


      二. 当APP处于前台时,系统收到推送消息,此时系统不会弹出消息提示,会直接触发application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo函数,推送数据在userInfo字典中。

      三. 当App处于后台时,如果系统收到推送消息,当用户点击推送消息时,会执行application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo函数,此时AppDelegate中函数执行的顺序为:
          applicationWillEnterForeground
          application:didReceiveRemoteNotification
          applicationDidBecomeActive



 (3):将设备DeviceToken数据提供给服务商,以供推送到具体的手机上面. 如果远程推送消息来了,用户点击了推送消息,或者应用已经处于打开状态,系统都会自动调用以下委托:

  //点击某条远程通知时调用的委托 如果界面处于打开状态,那么此委托会直接响应
    -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
    {
        NSLog(@"远程通知");
        [self PMD_uesPushMessage:userInfo];
    }

  //第三点里面的介绍的情况是应用程序已经处于运行状态,上面的委托才会被执行,如果应用程序处于未启用状态,此时又需要响应消息,那么需要以下委托处理.
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        //这里处理应用程序如果没有启动,但是是通过通知消息打开的,此时可以获取到消息.
        if (launchOptions != nil) {
            NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
            [self doSomeThingWith:userInfo];
        }
        return YES;
    }
5:清空通知中心已有的推送消息,只需要将指定App 的 Badge 设置为 0即可
    [[UIApplication sharedApplication ] setApplicationIconBadgeNumber:0];

6:主动推送的字符串必须符合如下Json数组的格式,才能正确推送到手机当中.
{
    
//自定义参数
\\"userinfo":
{
    \\"name":\\"remote notice"
},
//标准写法
"aps":
{
    "alert":
    {
        "action-loc-key":"Open",//支持多语言
        "body":"messgae content"//消息正文
    },
    "badge":1,//为App 的icon  标记 具体数值
    "sound":"default" //播放的音频文件,default 表示系统默认的选择列铃声
}
}


{"aps":{"alert":{"action-loc-key": "Open","body": "Hello, world!"},
        "badge":9,
        "sound":"default"
        }
}




deviceToken输出不能用 [[NSString alloc] initWithData:deviceToken encoding:NSUTF8StringEncoding];

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
  //传递直接传递 deviceToken 以下是输出
  NSString *tokenString = [NSString stringWithFormat:@"%@",deviceToken];
  NSLog(@"tokenString - %@",tokenString);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容