比别人多一点志气,你就会多一份出息 [登录·注册]

吕滔博客

首页 开发 运维 工具 摄影

苹果推送(APNs)ios push小结

iOS memory 发布于July 14, 2015 标签: iOS

苹果的推送服务APNs基本原理简单来说就是:苹果利用自己专门的推送服务器(APNs)接收来自我们自己的应用服务器的需要被推送的信息,然后推送到指定的iOS设备上,然后由设备通知到我们的应用程序,设备以通知或者声音的形式通知用户有新的消息。推送的前提是装有我们应用的设备需要向APNs服务器注册,注册成功后APNs服务器会返给我们一个device_token,拿到这个token后我们将这个token发给我们自己的应用服务器,当有需要被推送的消息时,我们的应用服务器会将消息按指定的格式打包,然后结合设备的device_token一并发给APNs服务器,由于我们的应用和APNs维持一个基于TCP的长连接,APNs将新消息推送到我们设备上,然后在屏幕上显示出新消息来。
1.Device连接APNs服务器并携带设备序列号
2.连接成功,APNs产生device_token并返回给Device
3.Device携带获取的device_token向我们自己的应用服务器注册,一定要将device_token发送给我们的应用服务器,因为在推送过程中,首先是由我们的应用服务器将需要推送的消息结合device_token按指定格式(后面会提到)打包然后发送给APNS服务器,然后由APNS服务器推送给我们的设备。

推送消息是个JSON结构体,最大值是 256 字节。alert标签的内容就是会显示在用户手机上的推送信息,badge显示的数量(注意是整型)是会在应用Icon右上角显示的数量,提示有多少条未读消息等,sound就是当推送信息送达是手机播放的声音,传defalut就标明使用系统默认声音,如果传比如“beep.wav”就会播放在我们应用工程目录下名称为beep.wav的音频文件。

要在这个结构中新增自定义数据,请加在aps空间之外。比如后台推送消息给应用同时要求应用打开某个页面:

{
    "aps": {
        "alert": "张三:国庆回家吗?", 
        "sound": "default"
    }, 
    "msg": "这里是额外消息,不显示在通知界面上。"
}

具体步骤

打开“钥匙串”程序,(证书助理->从证书颁发机构请求证书),只填邮箱和常用名称,ca不用填,然后保存.certSigningRequest文件到磁盘

在iOS Dev Center 点击App IDs进入App ID列表。

为 App 开启 Push Notification 功能。(推送证书分为两个版本,一个是Development版,一个是Production版,分别对应开发证书和发布证书。)

上传刚才生成的.certSigningRequest文件,生成aps_development.cer推送证书,双击安装。

打开“钥匙串”程序,(选择登录与我的证书选项后)找到IOS Push Services那条。

右键导出,存储为cert.p12,(输入密码P*d),然后将该证书的折叠打开,导出“专用密钥”。存储为key.p12

接下来打开终端

生成cert.pem
openssl pkcs12 -clcerts -nokeys -out cert.pem -in cert.p12
生成key.pem(先输出导出key.p12时设置的密码P*d, 然后设置一个新的密码,如pushpwd,这个密码后面php推送时要设置)
openssl pkcs12 -nocerts -out key.pem -in key.p12
合并成ck.pem
cat cert.pem key.pem > ck.pem

将这个ck.pem放在服务器上,与发送脚本放在同一个目录下。 测试这个key

openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert cert.pem -key ck.pem

iOS程序处理

应用如何获取deviceToken。应用必须先注册使用push功能。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //Let teh device know we want to receive push notifications
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
    return YES;
}
 
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSLog(@"My token is:%@", deviceToken);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    NSLog(@"Failed tp get token, error:%@", error);
}

客户端接收push消息

如果应用已经启动,将调用AppDelegate的方法:

 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
      // userInfo 就是push消息的Payload
  }

如果应用还没有启动,通过push冷启动后,仍然能在启动后获取Payload:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      NSDictionary* userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
      NSLog(@"Payload: %@", userInfo);
  }

PHP推送程序

<?php
/* ini_set("display_errors", "On");
error_reporting(E_ALL | E_STRICT); */
 
// Put your device token here (without spaces):
$deviceToken = 'af93167751347b0909a05b97fefa1c7525dbbad0608cd63d19b11cbeb4a7878c';
// Put your private key's passwd here:
$passphrase = '这时填你生成key.pem时设置的密码';
 
// Put your alert message here:
$message = 'Welcome to www.elesos.com';
 
////////////////////////////////////////////////////////////////////////////////
 
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'client.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
 
// Open a connection to the APNS server
$fp = stream_socket_client(
    'ssl://gateway.sandbox.push.apple.com:2195', $err,
    $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
 
if (!$fp)
    exit("Failed to connect: $err $errstr" . PHP_EOL);
 
echo 'Connected to APNS' . PHP_EOL;
 
// Create the payload body
$body['aps'] = array(
    'alert' => $message,
    'badge'=>1,
    'sound' => 'default'
    );
 
// Encode the payload as JSON
$payload = json_encode($body);
 
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
 
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
 
if (!$result)
    echo 'Message not delivered' . PHP_EOL;
else
    echo 'Message successfully delivered' . PHP_EOL;
 
// Close the connection to the server
fclose($fp);

相关推荐

添加新评论

网站状态

  • 栏目分类:49个
  • 发布文章:1560篇
  • 用户评论:853条
  • 开博至今:4435天

正则速查

[abc] 匹配中括号中的单个字符,如a或b或c
[^abc] 匹配除了a、b、c等字符的其他单个字符
[a-z] 匹配一个字符范围,如a到z
[a-zA-Z] 匹配一个字符范围,如a-z 或 A-Z
^ 匹配行的开始
$ 匹配行的结束
\A 匹配一个字符串的开始
\z 匹配一个字符串的结束
. 匹配任意单个字符
\s 匹配空白字符,如空格,TAB
\S 匹配非空白字符
\d 匹配一个数字
\D 匹配非数字
\w 匹配一个字母
\W 匹配非字母
\b 匹配字符边界
(...) 引用所有括号中的内容
(a|b) a或者b
a? 零个或1个a
a* 零个或多个a
a+ 1个或多个a
a{3} 3次重复的a
a{3,} 3次或3次以上重复的a
a{3,6} 3到6次重复的a

修正符

/g 查找所有可能的匹配
/i 不区分大小写
/m 多行匹配
/s 单行匹配
/x 忽略空白模式
/e 可执行模式,PHP专有
/A 强制从目标字符串开头匹配
/D 使用$限制结尾字符,则不允许结尾有换行
/U 只匹配最近的一个字符串;不重复匹配

最新回复

  • chen: 感谢大师,搞定
  • memory: 你把采集和文章相关content的字段text类型改为bigte...
  • chen: 请教大师,phpcms采集超过1万2字就无法采集,哪里可以修改?
  • 11: 很棒
  • s站: 学习了
  • 基地小组: 好文章,非常详细,博主辛苦了
  • memory: 没事儿,这个插件有些问题。我现在已经不使用了。。。
  • 小白: 还有会缓存用户状态给下一位用户!我评论留个记录而已,,,,,
  • 小白: 再次留个记录,不知道为什么缓存页面点击文章或者分类会跳转自己解析...
  • weich: 用数据库那个缓存就正常了!有得用不错了!作者也幸苦了!
  • weich: 有点奇怪,,,哈哈哈哈!原来是那个模板登陆标签被我注释了,所以不...
  • weich: 很强大,就是有个问题登陆了可用看见网页底部模板,不登陆就看不到,...
  • J Zhiguang: valued article for a new learnner.
  • VPS234: 写得不错啊,支持一下,证书现在很多免费的吧
  • 游客: 感谢,我终于明白了markdown原来就是快捷键啊。
  • 楚狂人博客: 感谢博主分享干货
  • 天津网站建设: 写的很棒,感谢博主