欢迎访问我的博客,http://www.paulwangblog.com
最近的一个项目在开发一个iphone客户端,客户提出要做一个程序即使在后台也可以弹出的消息提示,这是目前大量ios应用的方式,找了点资料研究了一下,现在总结出来
1.什么是Apns?
参考链接
2.Apns的原理及流程
参考链接
3.Apns的几个接口
push是指通过自己的服务器给用户手机的固定应用发信息
feedback是指定期从苹果那里取到一些不再能接收此应用信息的手机id,例如当用户卸载应用后,就不会再发送成功,所以这时候不要再给此用户发送信息了
4.PHP Demo
我采用了Google code中的一个项目,代码写的比较严谨,但是第一次用,有许多不明白的地方,所以研究后做下说明,告诉大家,如下:
项目地址:http://code.google.com/p/apns-php/
这个项目通过socket用ssl去连接苹果服务器的时候,没有传入密码(一般都有的),我做了一些修改,修改后可以成功的给申请过应用的手机下发信息
sample_push.php:下发测试代码,我修改的地方如下:
- $push = new ApnsPHP_Push(
- ApnsPHP_Abstract::ENVIRONMENT_SANDBOX,
- 'my.pem',
- 'abc@123'
- );
Abstract.php我做了修改,全部贴出来
- <?php
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- abstract class ApnsPHP_Abstract
- {
- const ENVIRONMENT_PRODUCTION = 0;
- const ENVIRONMENT_SANDBOX = 1;
-
- const DEVICE_BINARY_SIZE = 32;
-
- const CONNECT_RETRY_INTERVAL = 1000000;
- const SOCKET_SELECT_TIMEOUT = 1000000;
-
- protected $_aServiceURLs = array();
-
- protected $_nEnvironment;
-
- protected $_nConnectTimeout;
- protected $_nConnectRetryTimes = 3;
-
- protected $_sProviderCertificateFile;
- protected $_sProviderPass;
- protected $_sRootCertificationAuthorityFile;
-
- protected $_nConnectRetryInterval;
- protected $_nSocketSelectTimeout;
-
- protected $_logger;
-
- protected $_hSocket;
-
-
-
-
-
-
-
-
-
-
- public function __construct($nEnvironment, $sProviderCertificateFile, $sProviderPass)
- {
- if ($nEnvironment != self::ENVIRONMENT_PRODUCTION && $nEnvironment != self::ENVIRONMENT_SANDBOX) {
- throw new ApnsPHP_Exception(
- "Invalid environment '{$nEnvironment}'"
- );
- }
- $this->_nEnvironment = $nEnvironment;
-
- if (!is_readable($sProviderCertificateFile)) {
- throw new ApnsPHP_Exception(
- "Unable to read certificate file '{$sProviderCertificateFile}'"
- );
- }
- $this->_sProviderCertificateFile = $sProviderCertificateFile;
- $this->_sProviderPass = $sProviderPass;
-
- $this->_nConnectTimeout = ini_get("default_socket_timeout");
- $this->_nConnectRetryInterval = self::CONNECT_RETRY_INTERVAL;
- $this->_nSocketSelectTimeout = self::SOCKET_SELECT_TIMEOUT;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public function setLogger(ApnsPHP_Log_Interface $logger)
- {
- if (!is_object($logger)) {
- throw new ApnsPHP_Exception(
- "The logger should be an instance of 'ApnsPHP_Log_Interface'"
- );
- }
- if (!($logger instanceof ApnsPHP_Log_Interface)) {
- throw new ApnsPHP_Exception(
- "Unable to use an instance of '" . get_class($logger) . "' as logger: " .
- "a logger must implements ApnsPHP_Log_Interface."
- );
- }
- $this->_logger = $logger;
- }
-
-
-
-
-
-
- public function getLogger()
- {
- return $this->_logger;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public function setRootCertificationAuthority($sRootCertificationAuthorityFile)
- {
- if (!is_readable($sRootCertificationAuthorityFile)) {
- throw new ApnsPHP_Exception(
- "Unable to read Certificate Authority file '{$sRootCertificationAuthorityFile}'"
- );
- }
- $this->_sRootCertificationAuthorityFile = $sRootCertificationAuthorityFile;
- }
-
-
-
-
-
-
- public function getCertificateAuthority()
- {
- return $this->_sRootCertificationAuthorityFile;
- }
-
-
-
-
-
-
-
-
-
- public function setConnectTimeout($nTimeout)
- {
- $this->_nConnectTimeout = (int)$nTimeout;
- }
-
-
-
-
-
-
- public function getConnectTimeout()
- {
- return $this->_nConnectTimeout;
- }
-
-
-
-
-
-
-
-
-
- public function setConnectRetryTimes($nRetryTimes)
- {
- $this->_nConnectRetryTimes = (int)$nRetryTimes;
- }
-
-
-
-
-
-
- public function getConnectRetryTimes()
- {
- return $this->_nConnectRetryTimes;
- }
-
-
-
-
-
-
-
-
-
-
-
- public function setConnectRetryInterval($nRetryInterval)
- {
- $this->_nConnectRetryInterval = (int)$nRetryInterval;
- }
-
-
-
-
-
-
- public function getConnectRetryInterval()
- {
- return $this->_nConnectRetryInterval;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public function setSocketSelectTimeout($nSelectTimeout)
- {
- $this->_nSocketSelectTimeout = (int)$nSelectTimeout;
- }
-
-
-
-
-
-
- public function getSocketSelectTimeout()
- {
- return $this->_nSocketSelectTimeout;
- }
-
-
-
-
-
-
-
-
-
-
-
-
- public function connect()
- {
- $bConnected = false;
- $nRetry = 0;
- while (!$bConnected) {
- try {
- $bConnected = $this->_connect();
- } catch (ApnsPHP_Exception $e) {
- $this->_log('ERROR: ' . $e->getMessage());
- if ($nRetry >= $this->_nConnectRetryTimes) {
- throw $e;
- } else {
- $this->_log(
- "INFO: Retry to connect (" . ($nRetry+1) .
- "/{$this->_nConnectRetryTimes})..."
- );
- usleep($this->_nConnectRetryInterval);
- }
- }
- $nRetry++;
- }
- }
-
-
-
-
-
-
- public function disconnect()
- {
- if (is_resource($this->_hSocket)) {
- $this->_log('INFO: Disconnected.');
- return fclose($this->_hSocket);
- }
- return false;
- }
-
-
-
-
-
-
-
- protected function _connect()
- {
- $sURL = $this->_aServiceURLs[$this->_nEnvironment];
- unset($aURLs);
-
- $this->_log("INFO: Trying {$sURL}...");
-
-
-
-
- $streamContext = stream_context_create(array('ssl' => array(
-
-
- 'local_cert' => $this->_sProviderCertificateFile,
- 'passphrase'=> $this->_sProviderPass
- )));
-
- $this->_hSocket = @stream_socket_client($sURL, $nError, $sError,
- $this->_nConnectTimeout, STREAM_CLIENT_CONNECT, $streamContext);
-
- if (!$this->_hSocket) {
- throw new ApnsPHP_Exception(
- "Unable to connect to '{$sURL}': {$sError} ({$nError})"
- );
- }
-
- stream_set_blocking($this->_hSocket, 0);
- stream_set_write_buffer($this->_hSocket, 0);
-
- $this->_log("INFO: Connected to {$sURL}.");
-
- return true;
- }
-
-
-
-
-
-
- protected function _log($sMessage)
- {
- if (!isset($this->_logger)) {
- $this->_logger = new ApnsPHP_Log_Embedded();
- }
- $this->_logger->log($sMessage);
- }
- }
5.Pythoh Demo
http://code.google.com/p/apns-python-wrapper/
注意事项:
无论你是在sandbox,还是正式环境下,都是需要申请证书才能连接apns服务的,所以不要心存侥幸,申请的流程自己去搜索一下,值得说明的证书分.p12和.pem格式2种,.net用p12,而下面的php项目用的是pem,这个pem是用苹果下载的2个pem合并的,方法别人也介绍过了,用这个证书,加上密码(如果有密码的话),就可以通过ssl(https)去连接服务器了,这些都正确,你才会连接成功,那才能给手机发信息哦