出家如初,成佛有余

iOS及Android消息推送方案安装使用入门

Posted in 移动互联网, 技术相关 by chuanliang on 2012/10/12

iOS消息推送直接使用苹果消息推送协议,服务器端采用easy apns:http://www.easyapns.com/

Android消息推送采用MQTT协议,服务器端采用mosquito+PhpMQTTClient

mosquito:http://mosquitto.org/

PhpMQTTClient   :https://github.com/tokudu/PhpMQTTClient

1     iOS消息推送

1.0 、消息推送证书生成

在apple官网分别生成消息推送的development和production证书,这里只使用development证书,假定为push.p12

1.1、生成easy apns所需要的pem格式的证书

openssl pkcs12 -clcerts -nokeys -out cert.pem -in push.p12

openssl pkcs12 -nocerts -out key.pem -in push.p12

openssl rsa -in key.pem -out key.unencrypted.pem

cat cert.pem key.unencrypted.pem > apns-dev-cert.pem

 

对production证书重复以上类似步骤,生成apns-cert.pem

1.2easy apns安装配置

由于easy apns使用了mysqli来连接mysql,因此记得在安装php时候在php.ini启用mysqli

1.2.1 easy apns下载

https://github.com/manifestinteractive/easyapns下载easy apns代码

unzip manifestinteractive-easyapns-6f5731a.zip

1.2.2easy apns数据库初始化

创建数据库apns

用manifestinteractive-easyapns-6f5731a/manifestinteractive-easyapns-6f5731a/src/sql/apns.sql建立所需要的数据库表

1.2.3easy apns php应用

将manifestinteractive-easyapns-6f5731a/manifestinteractive-easyapns-6f5731a/src/php下的代码拷贝到服务器对应的目录下,假设为/var/www/html/apns

将1.1生成的apns-dev-cert.pem 和apns-cert.pem 拷贝到/var/www/html/apns下

修改classes/class_APNS.php如下参数:

private $logPath = ‘/var/www/html/apns/apns.log’;

private $certificate = ‘/var/www/html/apns/apns-cert.pem’;

private $sandboxCertificate = ‘/var/www/html/apns/apns-dev-cert.pem’; // change this to your development certificate absolute path

将证书权限修改为644

修改apns.php如下参数

$db = new DbConnect(‘localhost’, ‘apnsuser’, ‘apnspassword’, ‘apnsdb’);

将localhost、apnsuser、apnspassword、apnsdb改成对应的参数

1.2.4crontab配置

* * * * * nice /usr/bin/php -f /var/www/html/apns/apns.php fetch > /var/www/html/apns/apns.log 2>&1 &

1.2.5、测试

在manifestinteractive-easyapns-6f5731a/manifestinteractive-easyapns-6f5731a/src/delegate/Delegate.m基础上,建立iPhone测试Demo程序

修改Delegate.m中的:

NSString *host = @”www.mywebsite.com“;  //修改为指向实际消息推送的Web服务器的地址和端口

NSString *urlString = [NSString stringWithFormat:@”/apns.php?task=%@&appname=%@&appversion=%@&deviceuid=%@&devicetoken=%@&devicename=%@&devicemodel=%@&deviceversion=%@&pushbadge=%@&pushalert=%@&pushsound=%@“, @”register”, appName,appVersion, deviceUuid, deviceToken, deviceName, deviceModel, deviceSystemVersion, pushBadge, pushAlert, pushSound];

将/apns.php? 修改为easy apns实际的url访问路径,此处为:/apns/apns.php

修改samples.php

$db = new DbConnect(‘localhost’, ‘apnsuser’, ‘apnspassword’, ‘apnsdb’);

将localhost、apnsuser、apnspassword、apnsdb改成对应的参数

在iPhone上运行Demo程序,查看服务器数据库apns_devices表,看Demo程序是否成功注册

如果在apns_devices表中已有iPhone客户端的设备信息,则修改对应的development字段为:sandbox

运行发送消息的例子:http://ip:port/apns/samples.php,应该就会有消息推送

备注:

a、如果要向所有已注册的设备推送消息,可以将samples.php中的例子修改为

$apns->newMessage(NULL);

$apns->addMessageAlert(‘所有设备推送测试消息’);

$apns->addMessageCustom(‘acme2’, array(‘bang’, ‘whiz’));

$apns->queueMessage();

b、如果要支持推送表情消息,可以参考:http://www.easyapns.com/category/just-for-fun

c、查看classes/class_APNS.php的_fetchMessages()可知,easy apns缺省每次只处理100条记录,为提高发送效率,可适当提高此参数

1.2.6、其他问题

a、消息大批量发送问题

目前由于APNS(Apple Push Notification Service)机制原因,目前easy apns的消息发送机制为:

对每一条发送的消息,为所有需要推送的设备都在数据库中apns_messages创建一条消息,然后通过轮训数据库表来一条一条向苹果消息推送服务器发送消息

在需要推送的设备较多的情况下,由于存在大量的网络链接,导致存在较长时间的延迟。

解决方案:

1、做批量消息推送时候,保持与苹果消息推送服务器的长链接

2、使用批量发送机制

具体可参考:http://bit.ly/QUNRJ6

You should also retain connections with APNs across multiple notifications. APNs may consider connections that are rapidly and repeatedly established and torn down as a denial-of-service attack. Upon error, APNs closes the connection on which the error occurred.

As a provider, you are responsible for the following aspects of push notifications:

You must compose the notification payload (see “The Notification Payload”).

You are responsible for supplying the badge number to be displayed on the application icon.

You should regularly connect with the feedback web server and fetch the current list of those devices that have repeatedly reported failed-delivery attempts. Then you should cease sending notifications to the devices associated with those applications. See “The Feedback Service” for more information.

b、数据库轮询效率问题

由于目前easy apns是采用数据库轮询的方式来进行消息推送,效率并不高,后期可以修改为Redis这样的NOSQL方案

1.3、参考文档:

http://1j2.com/tutorial-implementing-push-notifications-with-easy-apns/

2Android消息推送

MQTT服务器采用mosquito  http://mosquitto.org/

PHP管理包采用phpmqttclient:https://github.com/tokudu/PhpMQTTClient

2.1mosquito安装

cd /etc/yum.repos.d

wget http://download.opensuse.org/repositories/home:/oojah:/mqtt/CentOS_CentOS-5/home:oojah:mqtt.repo

yum update

yum install mosquitto

2.2mosquito命令行使用

mosquito安装主要包含三个部分:

mosquitto mosquitto服务器主程序,实现了MQTT协议

mosquitto_pub mosquitto发布消息的命令行程序

mosquitto_sub mosquitto订阅消息的命令行程序

启动mosquitto在前台运行

mosquitto

启动mosquitto在后台运行

mosquitto -d

启动订阅:

mosquitto_sub -t hello/world //订阅topic为hello/world的消息,使用默认地址和端口1883

发布消息

mosquitto_pub -t hello/world -m “hello,world” //发布topic 为hello/world的消息 “hello,world”

更多mosquitto命令可以参考

http://mosquitto.org/documentation/

2.3PhpMQTTClient安装

2.3.1、从https://github.com/tokudu/PhpMQTTClient下载

将tokudu-PhpMQTTClient-ba4e494/tokudu-PhpMQTTClient-ba4e494拷贝到服务器对应目录下

假设为/var/www/html/mqtt,可以通过http://host:port/mqtt访问phpmqttclient

2.3.2、将index.php$result = $conn->connect(SAM_MQTT, array(SAM_HOST => ‘127.0.0.1’, SAM_PORT => 1883));   修改为

$result = $conn->connect(SAM_MQTT, array(‘SAM_HOST’ => ‘127.0.0.1’, ‘SAM_PORT’ => 1883));

备注:如果phpmqttclient的http服务器与mosquitto没有安装在同一台服务器,注意将index.php中的127.0.0.1和send_mqtt.php修改成mosquitto的ip地址

2.3.3、将SAM/MQTT/sam_mqtt.phpSAM_PORTSAM_HOST也都加上

if ($options[‘SAM_PORT’] == ”) {

$this->port = 1883;

} else {

$this->port = $options[‘SAM_PORT’];

}

if ($options[‘SAM_HOST’] == ”) {

$this->host = ‘localhost’;

} else {

$this->host = $options[‘SAM_HOST’];

2.3.4、服务器测试,测试PhpMQTTClient安装成功

启动mosquitto在前台运行,以方便获取连接客户端的信息

mosquitto

在服务器另外一终端上启动订阅消息的进程,订阅所有tokudu开头topic

mosquitto_sub  –t  tokudu /+

注意,此处之所以要使用tokudu,可以看index.php的182行          var target = ‘tokudu/’ + $(‘#messageTarget’).val();

在mosquitto的终端获得mosquitto_sub客户端的id

1350006978: New client connected from 127.0.0.1 as mosqsub/8491-localhost..

访问http://host:port/mqtt ,push notification target字段填写8491-localhost,push notification text填写需要推送的测试消息

在在mosquitto的终端查看是否收到了推送的消息,如果收到,说明phpmqttclient已经安装配置成功

2.3.5android Demo程序安装

https://github.com/tokudu/AndroidPushNotificationsDemo 下载Android客户端例子,安装到Android,启动后获取客户端的Device Target

2.3.6、先客户端推送消息

访问http://host:port/mqtt ,push notification target字段填写Android客户端的Device Target,push notification text填写需要推送的测试消息

2.4、问题

1、 需要在客户端增加向服务器端上报Device Target的通信报文,服务器端获取客户端的设备信息后存入到数据库中。需要发送消息时候从设备信息表中获取Device Target,然后调用推送接口发送消息,可参考send_mqtt.php

2、 消息队列的持久化及轮询机制,初期可存放到数据库中(参考easy apns),后期放到NOSQL数据库中。需要程序轮询消息队列,获取mosquitto消息队列状态、对未成功发送的消息重试等

3、大批量消息推送:可能的瓶颈应该主要在mosquitto的处理性能 ,由于是使用C++写的,性能应该可以支撑需要,可以先通过调整mosquitto.conf参数来优化mosquitto的性能。

4、除了MQTT+Mosquitto外,Apache ActiveMQ/Apollo+MQTT也是值得考虑的方案,ActiveMQ 5.6开始也支持MQTT协议了

5、之所以选择MQTT而非XMPP协议,可以参考 http://slidesha.re/PrXJvb,值得注意的Facebook Messenger也采用了MQTT协议。有空再单独写一篇关于移动终端消息推送整体架构及选型的方案

2.5、参考文档

http://tokudu.com/2010/how-to-implement-push-notifications-for-android/

http://mqtt.org/wiki/

http://ceit.uq.edu.au/content/installing-mosquitto-under-centos

留下评论

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理