Ios开发之Apns功能介绍(应用程序通知)及PHP/Python代码

欢迎访问我的博客,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:下发测试代码,我修改的地方如下:

[php]  view plain copy
  1. $push = new ApnsPHP_Push(  
  2.     ApnsPHP_Abstract::ENVIRONMENT_SANDBOX,  
  3.     'my.pem',//我的证书  
  4.     'abc@123'//我修改的,增加了密码  
  5. );  

Abstract.php我做了修改,全部贴出来

[php]  view plain copy
  1. <?php  
  2. /** 
  3.  * @file 
  4.  * ApnsPHP_Abstract class definition. 
  5.  * 
  6.  * LICENSE 
  7.  * 
  8.  * This source file is subject to the new BSD license that is bundled 
  9.  * with this package in the file LICENSE.txt. 
  10.  * It is also available through the world-wide-web at this URL: 
  11.  * http://code.google.com/p/apns-php/wiki/License 
  12.  * If you did not receive a copy of the license and are unable to 
  13.  * obtain it through the world-wide-web, please send an email 
  14.  * to [email protected] so we can send you a copy immediately. 
  15.  * 
  16.  * @author (C) 2010 Aldo Armiento ([email protected]) 
  17.  * @version $Id: Abstract.php 102 2011-11-15 09:56:47Z aldo.armiento $ 
  18.  */  
  19.   
  20. /** 
  21.  * @mainpage 
  22.  * 
  23.  * @li ApnsPHP on Google Code: http://apns-php.googlecode.com/ 
  24.  */  
  25.   
  26. /** 
  27.  * @defgroup ApplePushNotificationService ApnsPHP 
  28.  */  
  29.   
  30. /** 
  31.  * Abstract class: this is the superclass for all Apple Push Notification Service 
  32.  * classes. 
  33.  * 
  34.  * This class is responsible for the connection to the Apple Push Notification Service 
  35.  * and Feedback. 
  36.  * 
  37.  * @ingroup ApplePushNotificationService 
  38.  * @see http://tinyurl.com/ApplePushNotificationService 
  39.  */  
  40. abstract class ApnsPHP_Abstract  
  41. {  
  42.     const ENVIRONMENT_PRODUCTION = 0; /**< @type integer Production environment. */  
  43.     const ENVIRONMENT_SANDBOX = 1; /**< @type integer Sandbox environment. */  
  44.   
  45.     const DEVICE_BINARY_SIZE = 32; /**< @type integer Device token length. */  
  46.   
  47.     const CONNECT_RETRY_INTERVAL = 1000000; /**< @type integer Default connect retry interval in micro seconds. */  
  48.     const SOCKET_SELECT_TIMEOUT = 1000000; /**< @type integer Default socket select timeout in micro seconds. */  
  49.   
  50.     protected $_aServiceURLs = array(); /**< @type array Container for service URLs environments. */  
  51.   
  52.     protected $_nEnvironment/**< @type integer Active environment. */  
  53.   
  54.     protected $_nConnectTimeout/**< @type integer Connect timeout in seconds. */  
  55.     protected $_nConnectRetryTimes = 3; /**< @type integer Connect retry times. */  
  56.   
  57.     protected $_sProviderCertificateFile/**< @type string Provider certificate file with key (Bundled PEM). */  
  58.     protected $_sProviderPass;  
  59.     protected $_sRootCertificationAuthorityFile/**< @type string Root certification authority file. */  
  60.   
  61.     protected $_nConnectRetryInterval/**< @type integer Connect retry interval in micro seconds. */  
  62.     protected $_nSocketSelectTimeout/**< @type integer Socket select timeout in micro seconds. */  
  63.   
  64.     protected $_logger/**< @type ApnsPHP_Log_Interface Logger. */  
  65.   
  66.     protected $_hSocket/**< @type resource SSL Socket. */  
  67.   
  68.     /** 
  69.      * Constructor. 
  70.      * 
  71.      * @param  $nEnvironment @type integer Environment. 
  72.      * @param  $sProviderCertificateFile @type string Provider certificate file 
  73.      *         with key (Bundled PEM). 
  74.      * @throws ApnsPHP_Exception if the environment is not 
  75.      *         sandbox or production or the provider certificate file is not readable. 
  76.      */  
  77.     public function __construct($nEnvironment$sProviderCertificateFile$sProviderPass)  
  78.     {  
  79.         if ($nEnvironment != self::ENVIRONMENT_PRODUCTION && $nEnvironment != self::ENVIRONMENT_SANDBOX) {  
  80.             throw new ApnsPHP_Exception(  
  81.                 "Invalid environment '{$nEnvironment}'"  
  82.             );  
  83.         }  
  84.         $this->_nEnvironment = $nEnvironment;  
  85.   
  86.         if (!is_readable($sProviderCertificateFile)) {  
  87.             throw new ApnsPHP_Exception(  
  88.                 "Unable to read certificate file '{$sProviderCertificateFile}'"  
  89.             );  
  90.         }  
  91.         $this->_sProviderCertificateFile = $sProviderCertificateFile;  
  92.         $this->_sProviderPass = $sProviderPass;  
  93.   
  94.         $this->_nConnectTimeout = ini_get("default_socket_timeout");  
  95.         $this->_nConnectRetryInterval = self::CONNECT_RETRY_INTERVAL;  
  96.         $this->_nSocketSelectTimeout = self::SOCKET_SELECT_TIMEOUT;  
  97.     }  
  98.   
  99.     /** 
  100.      * Set the Logger instance to use for logging purpose. 
  101.      * 
  102.      * The default logger is ApnsPHP_Log_Embedded, an instance 
  103.      * of ApnsPHP_Log_Interface that simply print to standard 
  104.      * output log messages. 
  105.      * 
  106.      * To set a custom logger you have to implement ApnsPHP_Log_Interface 
  107.      * and use setLogger, otherwise standard logger will be used. 
  108.      * 
  109.      * @see ApnsPHP_Log_Interface 
  110.      * @see ApnsPHP_Log_Embedded 
  111.      * 
  112.      * @param  $logger @type ApnsPHP_Log_Interface Logger instance. 
  113.      * @throws ApnsPHP_Exception if Logger is not an instance 
  114.      *         of ApnsPHP_Log_Interface. 
  115.      */  
  116.     public function setLogger(ApnsPHP_Log_Interface $logger)  
  117.     {  
  118.         if (!is_object($logger)) {  
  119.             throw new ApnsPHP_Exception(  
  120.                 "The logger should be an instance of 'ApnsPHP_Log_Interface'"  
  121.             );  
  122.         }  
  123.         if (!($logger instanceof ApnsPHP_Log_Interface)) {  
  124.             throw new ApnsPHP_Exception(  
  125.                 "Unable to use an instance of '" . get_class($logger) . "' as logger: " .  
  126.                 "a logger must implements ApnsPHP_Log_Interface."  
  127.             );  
  128.         }  
  129.         $this->_logger = $logger;  
  130.     }  
  131.   
  132.     /** 
  133.      * Get the Logger instance. 
  134.      * 
  135.      * @return @type ApnsPHP_Log_Interface Current Logger instance. 
  136.      */  
  137.     public function getLogger()  
  138.     {  
  139.         return $this->_logger;  
  140.     }  
  141.   
  142.     /** 
  143.      * Set the Root Certification Authority file. 
  144.      * 
  145.      * Setting the Root Certification Authority file automatically set peer verification 
  146.      * on connect. 
  147.      * 
  148.      * @see http://tinyurl.com/GeneralProviderRequirements 
  149.      * @see http://www.entrust.net/ 
  150.      * @see https://www.entrust.net/downloads/root_index.cfm 
  151.      * 
  152.      * @param  $sRootCertificationAuthorityFile @type string Root Certification 
  153.      *         Authority file. 
  154.      * @throws ApnsPHP_Exception if Root Certification Authority 
  155.      *         file is not readable. 
  156.      */  
  157.     public function setRootCertificationAuthority($sRootCertificationAuthorityFile)  
  158.     {  
  159.         if (!is_readable($sRootCertificationAuthorityFile)) {  
  160.             throw new ApnsPHP_Exception(  
  161.                 "Unable to read Certificate Authority file '{$sRootCertificationAuthorityFile}'"  
  162.             );  
  163.         }  
  164.         $this->_sRootCertificationAuthorityFile = $sRootCertificationAuthorityFile;  
  165.     }  
  166.   
  167.     /** 
  168.      * Get the Root Certification Authority file path. 
  169.      * 
  170.      * @return @type string Current Root Certification Authority file path. 
  171.      */  
  172.     public function getCertificateAuthority()  
  173.     {  
  174.         return $this->_sRootCertificationAuthorityFile;  
  175.     }  
  176.   
  177.     /** 
  178.      * Set the connection timeout. 
  179.      * 
  180.      * The default connection timeout is the PHP internal value "default_socket_timeout". 
  181.      * @see http://php.net/manual/en/filesystem.configuration.php 
  182.      * 
  183.      * @param  $nTimeout @type integer Connection timeout in seconds. 
  184.      */  
  185.     public function setConnectTimeout($nTimeout)  
  186.     {  
  187.         $this->_nConnectTimeout = (int)$nTimeout;  
  188.     }  
  189.   
  190.     /** 
  191.      * Get the connection timeout. 
  192.      * 
  193.      * @return @type integer Connection timeout in seconds. 
  194.      */  
  195.     public function getConnectTimeout()  
  196.     {  
  197.         return $this->_nConnectTimeout;  
  198.     }  
  199.   
  200.     /** 
  201.      * Set the connect retry times value. 
  202.      * 
  203.      * If the client is unable to connect to the server retries at least for this 
  204.      * value. The default connect retry times is 3. 
  205.      * 
  206.      * @param  $nRetryTimes @type integer Connect retry times. 
  207.      */  
  208.     public function setConnectRetryTimes($nRetryTimes)  
  209.     {  
  210.         $this->_nConnectRetryTimes = (int)$nRetryTimes;  
  211.     }  
  212.   
  213.     /** 
  214.      * Get the connect retry time value. 
  215.      * 
  216.      * @return @type integer Connect retry times. 
  217.      */  
  218.     public function getConnectRetryTimes()  
  219.     {  
  220.         return $this->_nConnectRetryTimes;  
  221.     }  
  222.   
  223.     /** 
  224.      * Set the connect retry interval. 
  225.      * 
  226.      * If the client is unable to connect to the server retries at least for ConnectRetryTimes 
  227.      * and waits for this value between each attempts. 
  228.      * 
  229.      * @see setConnectRetryTimes 
  230.      * 
  231.      * @param  $nRetryInterval @type integer Connect retry interval in micro seconds. 
  232.      */  
  233.     public function setConnectRetryInterval($nRetryInterval)  
  234.     {  
  235.         $this->_nConnectRetryInterval = (int)$nRetryInterval;  
  236.     }  
  237.   
  238.     /** 
  239.      * Get the connect retry interval. 
  240.      * 
  241.      * @return @type integer Connect retry interval in micro seconds. 
  242.      */  
  243.     public function getConnectRetryInterval()  
  244.     {  
  245.         return $this->_nConnectRetryInterval;  
  246.     }  
  247.   
  248.     /** 
  249.      * Set the TCP socket select timeout. 
  250.      * 
  251.      * After writing to socket waits for at least this value for read stream to 
  252.      * change status. 
  253.      * 
  254.      * In Apple Push Notification protocol there isn't a real-time 
  255.      * feedback about the correctness of notifications pushed to the server; so after 
  256.      * each write to server waits at least SocketSelectTimeout. If, during this 
  257.      * time, the read stream change its status and socket received an end-of-file 
  258.      * from the server the notification pushed to server was broken, the server 
  259.      * has closed the connection and the client needs to reconnect. 
  260.      * 
  261.      * @see http://php.net/stream_select 
  262.      * 
  263.      * @param  $nSelectTimeout @type integer Socket select timeout in micro seconds. 
  264.      */  
  265.     public function setSocketSelectTimeout($nSelectTimeout)  
  266.     {  
  267.         $this->_nSocketSelectTimeout = (int)$nSelectTimeout;  
  268.     }  
  269.   
  270.     /** 
  271.      * Get the TCP socket select timeout. 
  272.      * 
  273.      * @return @type integer Socket select timeout in micro seconds. 
  274.      */  
  275.     public function getSocketSelectTimeout()  
  276.     {  
  277.         return $this->_nSocketSelectTimeout;  
  278.     }  
  279.   
  280.     /** 
  281.      * Connects to Apple Push Notification service server. 
  282.      * 
  283.      * Retries ConnectRetryTimes if unable to connect and waits setConnectRetryInterval 
  284.      * between each attempts. 
  285.      * 
  286.      * @see setConnectRetryTimes 
  287.      * @see setConnectRetryInterval 
  288.      * @throws ApnsPHP_Exception if is unable to connect after 
  289.      *         ConnectRetryTimes. 
  290.      */  
  291.     public function connect()  
  292.     {  
  293.         $bConnected = false;  
  294.         $nRetry = 0;  
  295.         while (!$bConnected) {  
  296.             try {  
  297.                 $bConnected = $this->_connect();  
  298.             } catch (ApnsPHP_Exception $e) {  
  299.                 $this->_log('ERROR: ' . $e->getMessage());  
  300.                 if ($nRetry >= $this->_nConnectRetryTimes) {  
  301.                     throw $e;  
  302.                 } else {  
  303.                     $this->_log(  
  304.                         "INFO: Retry to connect (" . ($nRetry+1) .  
  305.                         "/{$this->_nConnectRetryTimes})..."  
  306.                     );  
  307.                     usleep($this->_nConnectRetryInterval);  
  308.                 }  
  309.             }  
  310.             $nRetry++;  
  311.         }  
  312.     }  
  313.   
  314.     /** 
  315.      * Disconnects from Apple Push Notifications service server. 
  316.      * 
  317.      * @return @type boolean True if successful disconnected. 
  318.      */  
  319.     public function disconnect()  
  320.     {  
  321.         if (is_resource($this->_hSocket)) {  
  322.             $this->_log('INFO: Disconnected.');  
  323.             return fclose($this->_hSocket);  
  324.         }  
  325.         return false;  
  326.     }  
  327.   
  328.     /** 
  329.      * Connects to Apple Push Notification service server. 
  330.      * 
  331.      * @throws ApnsPHP_Exception if is unable to connect. 
  332.      * @return @type boolean True if successful connected. 
  333.      */  
  334.     protected function _connect()  
  335.     {  
  336.         $sURL = $this->_aServiceURLs[$this->_nEnvironment];  
  337.         unset($aURLs);  
  338.   
  339.         $this->_log("INFO: Trying {$sURL}...");  
  340.   
  341.         /** 
  342.          * @see http://php.net/manual/en/context.ssl.php 
  343.          */  
  344.         $streamContext = stream_context_create(array('ssl' => array(  
  345.             //'verify_peer' => isset($this->_sRootCertificationAuthorityFile),  
  346.             //'cafile' => $this->_sRootCertificationAuthorityFile,  
  347.             'local_cert' => $this->_sProviderCertificateFile,  
  348.             'passphrase'=> $this->_sProviderPass//modify by paul  
  349.         )));  
  350.   
  351.         $this->_hSocket = @stream_socket_client($sURL$nError$sError,  
  352.             $this->_nConnectTimeout, STREAM_CLIENT_CONNECT, $streamContext);  
  353.   
  354.         if (!$this->_hSocket) {  
  355.             throw new ApnsPHP_Exception(  
  356.                 "Unable to connect to '{$sURL}': {$sError} ({$nError})"  
  357.             );  
  358.         }  
  359.   
  360.         stream_set_blocking($this->_hSocket, 0);  
  361.         stream_set_write_buffer($this->_hSocket, 0);  
  362.   
  363.         $this->_log("INFO: Connected to {$sURL}.");  
  364.   
  365.         return true;  
  366.     }  
  367.   
  368.     /** 
  369.      * Logs a message through the Logger. 
  370.      * 
  371.      * @param  $sMessage @type string The message. 
  372.      */  
  373.     protected function _log($sMessage)  
  374.     {  
  375.         if (!isset($this->_logger)) {  
  376.             $this->_logger = new ApnsPHP_Log_Embedded();  
  377.         }  
  378.         $this->_logger->log($sMessage);  
  379.     }  
  380. }  


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)去连接服务器了,这些都正确,你才会连接成功,那才能给手机发信息哦

你可能感兴趣的:(Ios开发之Apns功能介绍(应用程序通知)及PHP/Python代码)