我们的IOS移动应用要实现消息推送,告诉用户有多少条消息未读,类似下图的效果(笑果),特把APNS和Erlang相关解决方案笔记于此备忘.
 
   
   上面图片中是Apple Notification在UI展现的形式之一,Notification共有三种形式:图标显示更新数字(badge),提示信息(alert),提示音(sound);
 
   iOS Apple Push Notification Services (APNs)官方的开发文档位置在:[Apple Push Notification Services],iOS团队的Matthijs Hollemans写的入门文档:Apple Push Notification Services in iOS 6 Tutorial 从这两份文档中,可以了解APNs的设计和开发的各种细节.首先是APNS的设计初衷:当用户没有启动应用,或者没有开机那么应用Server想要推送的消息就无法到达,需要其他的机制来完成消息的投递.
 
  Apple Push Notification service (APNs)把消息推送到设备上,设备上有应用已经注册过要接受此类消息.这里会有三种角色:Provider, APNs,Device . 见下图:
 
   
  
 
     上图说明:消息提供者(Provider),Provider接入到APNs,把最新的消息推送到 APNs,然后由APNs推送到目标设备(Device)的指定应用(Client APP).
 
      从上面的图,可以提出很多问题,特别是考虑到一些极端情况的时候,很有意思,可以通过这些问题驱动阅读Apple开发文档:
  1. Provider,APNs,Device 这三者之间的信任关系是怎么建立?
  2. 如何标识消息是给哪台机器的哪个应用的?消息传递的协议是怎么设计的(如何承载要发送的消息)?
  3. 在Device离线的情况下,Provider提交N条要发送给该Device的消息到APNs,APNs如何处理?
  4. 对于一些极端情况:比如Device做了系统恢复,应用卸载,Device硬件损坏,APNs有哪些应对机制?
  
    首先解决三者的信任关系,Provider(APP Server)的开发方要从Apple Dev Center获得SSL证书, 每个证书一个应用,甚至开发和生产环境的证书都要分别申请. Provider要在APNs中进行认证注册,目前注册使用的是应用程序的唯一标识(bundle identifier).Provider Connection的是对应到指定应用的,certificate中包含了应用程序的标识信息(bundle ID),APNs维护了一个废弃列表,如果一个Provider上了名单,APNs就会移除对该应用的信任. Provider和APNs通信协议是二进制协议,使用TCP流协议建立SSL(TLS)安全连接,官方文档称这种信任为Connection Trust. 
 
    对于用户设备APNs使用的是Token Trust.用户安装一个APP的时候,如果APP需要消息推送功能通常在安装成功之后会经由用户设备发起注册请求,用户设备将此请求转发到APNs, APNs生成唯一的device certificate,其中包含了device token.Device Token 中包含了设备的唯一标识,使用Token key加密Device Token返回到Device.用户设备把device token返回给发起注册请求的应用程序,应用程序把Device Token的信息传递给Provider.用户设备上安装的APP从APNs 获得device token之后每一次连接到ANPs都要提供这个token. APNs解密device token并验证这个token是从连接过来的设备生成的:APNs保证实际连接过来的设备标识和certificate文件中里面包含的标识一致.
 
   Provider提交到APNS的notification两个必要的信息:把什么消息投递给谁,即包含设备标识(Device Token)和实际消息体(Payload).APNS使用token Key解密token,从中提取设备ID来决定最终消息投递到哪个设备.Device Token有一个非常贴切的类比:手机号,它包含的信息可以让APNs来定位安装了指定应用的设备.APNs还使用Device Token来路由消息,Payload的消息组织形式是类JSON的,它包含的信息包括推送给设备什么内容以及如何提示;Payload内容大小限制是 256 bytes.
  注意:Device Token和设备的UDID不是一回事,用户恢复系统,重装都会导致device token变化.
 
    APNs有一个 Feedback Service的设计,它维护应用消息推送失败的设备列表,如果应用已经卸载了就无法投递成功,这样Feedback Service里面就会有记录.Provider的开发方应定期从该服务拉取这个失败列表来调整自己的发送行为:不要再给一个总是失败的设备推送消息了.如果设备离线,notification会在APNs上保存有限的一段时间,设备上线之后完成推送.如果设备离线期间同一个应用推送了多条notification,那么只会保存最新的notification,如果设备长期离线,任何离线消息都会被抛弃掉.这样如果iPhone掉海里面,需要推送给它的消息在过期之后就会被清理掉,不会长久占用APNs的资源.
 
 
  
 
经过上面的分析基本可以列出Erlang实现消息推送的技术要点了:
[1] JSON数据解析构造 mochijson mochijson2之类的模块就可以搞定  mochijson:encode --> list_to_binary
[3] 二进制协议实现 (Apple Binary Iterface)
Packet = [<<1:8, MsgId/binary, Expiry:4/big-unsigned-integer-unit:8,
                32:16/big,
                BinToken/binary,
                PayloadLength:16/big,
                BinPayload/binary>>]
 
[4] deviceToken -> binary 需要hexstr_to_bin的方法,这个代码片段之前说过多次了
bin_to_hexstr(Bin) ->
lists:flatten([io_lib:format("~2.16.0B", [X]) ||
X <- binary_to_list(Bin)]). hexstr_to_bin(S) ->
hexstr_to_bin(S, []).
hexstr_to_bin([], Acc) ->
list_to_binary(lists:reverse(Acc));
hexstr_to_bin([X,Y|T], Acc) ->
{ok, [V], []} = io_lib:fread("~16u", [X,Y]),
hexstr_to_bin(T, [V | Acc]).
[5] 维护TCP连接,重连机制
 
按照上面的要点完成了基本的验证之后,在Github上找到了开源项目apns4erl (地址:https://github.com/inaka/apns4erl),这个项目对APNS服务做了良好的实现和封装.下面介绍下apns4erl的使用:
 
 

开源项目APNS4erl

 
证书制作:
  APP Server和Apple Server中间建立信任关系需要通过各种证书,apns4erl作者在项目中提供了生成证书的脚本,不过在项目首页提到.cer和.p12文件生成pem证书的脚本地址是错的,实际位置是:
 
执行下面的脚本就一步一步即可:

#!/bin/sh

# Usage:
# test_certs {cert_file} {private_key_file}
# Example:
# test_certs aps_developer_indetity.cer aps_developer_identity.p12 mkdir -p priv/temp
openssl pkcs12 -in "$2" -out priv/temp/key-enc.pem
openssl rsa -in priv/temp/key-enc.pem -out priv/temp/key.pem
openssl x509 -inform der -in "$1" -out priv/temp/cert.pem
cat priv/temp/cert.pem priv/temp/key.pem > priv/cert.pem
rm -rf priv/temp
make test
下面是测试代码,注意send_badge/1方法就是我们需要的效果:
-module(t).
-compile(export_all).
-define(APNS_NAME,app_apns). -include("apns.hrl").
-include("localized.hrl"). conn_apns() ->
ssl:start(),
apns:start(),
apns:connect(
?APNS_NAME,
fun handle_apns_error/,
fun handle_apns_delete_subscription/
). send_message()->
apns:send_message(?APNS_NAME, "devicetoken31d1df3a324bb72c1ff2bcb3b87d33fd1a2b7578b359fb5494eff", "hello,这是一号话务员"). send_message(Msg) ->
apns:send_message(my_connection_name, #apns_msg{
alert = Msg ,
badge = ,
sound = "beep.wav" ,
expiry = ,
device_token = "devicetoken31d1df3a324bb72c1ff2bcb3b87d33fd1a2b7578b359fb5494eff"
}). send_badge(Number)->
apns:send_badge(qiaoqiao_apns,"devicetoken31d1df3a324bb72c1ff2bcb3b87d33fd1a2b7578b359fb5494eff", Number). handle_apns_error(MsgId, Status) ->
error_logger:error_msg("error: ~p - ~p~n", [MsgId, Status]). handle_apns_delete_subscription(Data) ->
error_logger:info_msg("delete subscription: ~p~n", [Data]).
APNS相关资料:
 
 
[0] iOSDeveloper Library: Apple Push Notification Service (APNS)
 
[1] Apple Push Notification Services in iOS 6 Tutorial
 
[2]  Apple Push Notification Services in iOS 6 Tutorial 中文
 http://www.raywenderlich.com/zh-hans/24732
 
[3] iOS 和 Android 的后台推送原理各是什么?有什么区别?
 
[4] 苹果产品是如何实现推送功能的呢?
 
[5] 为什么 Android 的后台推送不如 iOS 的推送使用广泛?
 
[6]  Is the device token as unique as the device ID?
 
[7]  If the user restores backup data to a new device or computer, or reinstalls the operating system, the device token changes. https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html
 
[8] Apple Push Notifications with Erlang
 
[9] Sending Apple Push Notifications with Erlang
 
最后小图一张:
 

[Erlang 0106] Erlang实现Apple Push Notifications消息推送的更多相关文章

  1. 使用Google Cloud Messaging (GCM),PHP 开发Android Push Notifications (安卓推送通知)

    什么是GCM? Google Cloud  Messaging (GCM) 是Google提供的一个服务,用来从服务端向安卓设备发送推送通知. GCM分为客户端和服务端开发. 这里我们只介绍服务端开发 ...

  2. (转)在SAE使用Apple Push Notification Service服务开发iOS应用, 实现消息推送

    在SAE使用Apple Push Notification Service服务开发iOS应用, 实现消息推送 From: http://saeapns.sinaapp.com/doc.html 1,在 ...

  3. Push:iOS基于APNS的消息推送

    1. Push的三个步骤,如下图所示: (1)Push服务应用程序把要发送的消息.目的iPhone的标识打包,发给APNS: (2)APNS在自身的已注册Push服务的iPhone列表中,查找有相应标 ...

  4. [置顶] 手把手教你iOS消息推送证书生成以及Push消息

    iOS推送消息是许多iOS应用都具备的功能,今天在给应用加推送功能,在生成证书的过程中,发生了各种令人蛋痛的事.下面就把步骤拿出来分享下: iOS消息推送的工作机制可以简单的用下图来概括: Provi ...

  5. 了解iOS消息推送一文就够:史上最全iOS Push技术详解

    本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表. 1.引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ.微信等IM界面处于前台时,聊天消息和指 ...

  6. 为友盟消息推送开发的PHP SDK(composer版):可以按省发Android push

    一直以来APP希望按省市县推送Android push,只能自己分析用户经纬度,打tag发送. 现在终于有服务商提供了. 友盟消息推送 可以“按省推送”,很方便. 我为友盟做了PHP SDK(comp ...

  7. 带你了解什么是Push消息推送

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 如果有看我最近文章的同学可能就知道我在公司负责的是一 ...

  8. APP消息推送机制的实现(PUSH)

    出于好奇,想了解一下消息推送机制,在网上搜索到了几篇文章,感觉还不错,粘贴下来,等真正用到的时候再仔细研究 以下两篇是关于ios的 1.http://blog.csdn.net/xyxjn/artic ...

  9. 采用MQTT协议实现android消息推送(2)MQTT服务端与客户端软件对比、android客户端示列表

    1.服务端软件对比 https://github.com/mqtt/mqtt.github.io/wiki/servers 名称(点名进官网) 特性 简介 收费 支持的客户端语言 IBM MQ 完整的 ...

随机推荐

  1. 关于MVC EF架构及Repository模式的一点心得

    一直都想写博客,可惜真的太懒了或者对自己的描述水平不太自信,所以...一直都是不想写的状态,关于领域驱动的东西看了不少,但是由于自己水平太差加上工作中实在用不到,所以一直处于搁置状态,最近心血来潮突然 ...

  2. js实现css3的过渡,需要注意的一点(浏览器优化)

    大部分浏览器对元素几何改变时候的重排做了优化.据说是这样子,一定时间内本应多次重排的改变,浏览器会hold住,仅一次重排.其中如果使用分离的一步处理过程,例如计时器,依然多次重排.例如,当我们应用tr ...

  3. 原创:微信小程序入口猜想?

    昨天看到一篇文章:是有一个人逆向了微信源码,从中发现了很多关于小程序的未公开内容,然后发布了出来,不过很快作者就删掉了文章,而我也没保留,只是隐约留下来一点点印象,就是作者推测了很多个入口:作者删掉的 ...

  4. 浅析.NET的反射特性

    在.net框架体系内,反射特性较多的应用到.反射的相关定义分为两种. 自然解释:射是一种自然现象,表现为受刺激物对刺激物的逆反应:这是反射的字面解释,我们看一下计算机编程中的反射: 编程解释:通过 S ...

  5. DotNet中几种常用的加密算法

    在.NET项目中,我们较多的使用到加密这个操作.因为在现代的项目中,对信息安全的要求越来越高,那么多信息的加密就变得至关重要.现在提供几种常用的加密/解密算法. 1.用于文本和Base64编码文本的互 ...

  6. 关于Javascript中通过实例对象修改原型对象属性值的问题

    Javascript中的数据值有两大类:基本类型的数据值和引用类型的数据值. 基本类型的数据值有5种:null.undefined.number.boolean和string. 引用类型的数据值往大的 ...

  7. Qt自适应大小显示图片,添加菜单

    由于后面的图像处理需要UI,OpenCV自带也不怎么会,MFC实在懒得学的.听同学说Qt不错,就用Qt做UI了. 本文主要介绍三个内容:在Qt Creator中使用OpenCV2.Qt中自适应显示图片 ...

  8. iOS滤镜实现之LOMO(美图秀秀经典LOMO)

    LOMO追求鲜艳色彩,随意.自由的态度,是一种经常使用的滤镜,今天介绍一下iOS 中LOMO滤镜的实现 首先它有3张输入图像 1.我们要处理的图像.即我们要应用LOMO滤镜的图像 2 3 在gpuim ...

  9. 这些Javascript知识点,面试和平时开发都需要

    No1.语法和类型 1.声明定义 变量类型:var,定义变量:let,定义块域(scope)本地变量:const,定义只读常量.    变量格式:以字母.下划线“_”或者$符号开头,大小写敏感.    ...

  10. AngularJS----服务,表单,模块

    AngularJS中的服务 服务是一个函数或对象,AngularJS中可以创建自己的服务或使用内建服务.$http是AngularJS中最常见的服务,服务向服务器发送请求,应用响应服务器传送过来的数据 ...