推送 方法2

手把手教你配置蘋果APNS推送服務php


 

1. 什麼是推送通知

 

消息通知分本地通知和遠程推送通知,是沒有運行在前臺的應用程序可讓它們的用戶得到相關消息通知的方式。消息通知多是一條消息,即將發生的日曆 事件,或遠程服務器的新數據。當被操做系統顯示時,本地通知和推送通知看起來同樣。它們能夠顯示一個警告信息或在應用程序的圖標上面顯示一個徽標。它們也 能夠在警告窗或徽標顯示時播放一段聲音。推送通知是在 iOS 3.0 和 Mac OS X v7.0 以後引入的。本地通知是在 iOS 4.0 以後引入的。它們都不支持 Mac OS X,當用戶被通知相應的應用程序有消息,事件,或其餘數據時,他們能夠啓動該應用程序並查看詳情。他們也能夠選擇忽略通知,此時應用程序沒有被激活。html

本地通知和推送通知爲不一樣的需求而設計的。本地通知是本地 iPhone、iPad、或iPod touch 上面的應用發起的。相反推送通知(又稱遠程通知)是從其餘設備上面到達的。它來自一個遠程設備——應用程序的提供者——並在有新的消息須要查看或新的數據 須要下載的時候被推送到本地設備上面的應用,常見的本地通知像iphone的日曆,微信或者qq這些都是本地推送,好比還安裝了優酷,qq視頻這些軟件, 容許推送後,天天會給你發些新的視頻消息,這些就是遠程推送。java

 

2. 什麼是APNS?

 

蘋果推送通知服務(APNs)是推送通知的網關,iPhone ipad 對於應用程序在後臺運行有諸多限制,考慮到手機電池電量,應用不容許在後臺進行過多的操做。所以,當用戶切換到其餘程序後,原先的程序沒法保持運行狀態。 對於那些須要保持持續鏈接狀態的應用程序(好比社區網絡應用),將不能收到實時的信息。推送是解決輪詢所形成的流量消耗和電量消耗的一個比較好的解決方案mysql

爲解決這一限制,蘋果推出了APNs(蘋果推送通知服務 Apple Push Notification services)。APNs 容許設備與蘋果的推送通知服務器保持常鏈接狀態。當你想發送一個推送通知給某個用戶的iPhone上的應用程序時,你可使用 APNs 發送一個推送消息給目標設備上已安裝的某個應用程序。ios

蘋果的推送服務APNs基本原理簡單來講就是蘋果利用本身專門的推送服務器(APNs)接收來自咱們本身應用服務器的須要被推送的信息,而後推送到 指定的iOS設備上,而後由設備通知到咱們的應用程序,設備以通知或者聲音的形式通知用戶有新的消息。推送的前提是裝有咱們應用的設備須要向APNs服務 器註冊,註冊成功後APNs服務器會返給咱們一個device_token,拿到這個token後咱們將這個token發給咱們本身的應用服務器,當有需 要被推送的消息時,咱們的應用服務器會將消息按指定的格式打包,而後結合設備的device_token一併發給APNs服務器,因爲咱們的應用和 APNs維持一個基於TCP的長鏈接,APNs將新消息推送到咱們設備上,而後在屏幕上顯示出新消息來。git

順便說下安卓的推送,Android消息推送採用MQTT協議,服務器端採用mosquito+PhpMQTTClient,有興趣的同窗能夠看看github

mosquito:http://mosquitto.org/web

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

 

3. 推送流程

 

3.1 獲取設備device_token階段

整個過程基本就這樣,下面咱們看一下設備註冊APNs的流程圖:數據庫

上圖完成了以下步驟:

1.Device鏈接APNs服務器並攜帶設備序列號

2.鏈接成功,APNs通過打包和處理產生device_token並返回給註冊的Device

3.Device攜帶獲取的device_token向咱們本身的應用服務器註冊

4.完成須要被推送的Device在APNs服務器和咱們本身的應用服務器註冊

執行順序以下所示:

這裏要提到的一點是,咱們的設備和APNS服務器之間的通信是基於SSL協議的TCP流通信,兩者之間維持一個長鏈接,當從APNS服務器註冊成功 後,必定要將device_token發送給咱們的應用服務器,由於在推送過程當中,首相是由咱們的應用服務器(上圖中Provider)將須要推送的消息 結合device_token按指定格式(後面會提到)打包而後發送給APNS服務器,而後由APNS服務器推送給咱們的設備。

3.2 消息推送過程

好了,註冊設備的過程完成了,接下來就是如何推送了:

推送的過程通過以下步驟:

1.首先,安裝了具備推送功能的應用,咱們的設備在有網絡的狀況下會鏈接蘋果推送服務器,鏈接過程當中,APNS會驗證device_token,鏈接成功後維持一個長鏈接;

2.Provider(咱們本身的服務器)收到須要被推送的消息並結合被推送設備的device_token一塊兒打包發送給APNS服務器;

3.APNS服務器將推送信息推送給指定device_token的設備;

4.設備收到推送消息後通知咱們的應用程序並顯示和提示用戶(聲音、彈出框)

3.3 完整流程介紹

比較直觀的流程參照下圖:

 

 

  1. 應用啓用推送通知功能,須要用戶確認;
  2. 應用收到設備識別ID(device token),至關於接收推送通知的地址;
  3. 應用將設備識別ID發送到你開發的服務器;
  4. 當有推送通知的須要時,你就能夠經過你開發的服務組件發送信息到蘋果的服務器上;
  5. 蘋果推送通知服務將信息推送到用戶的設備上。

上圖顯示了咱們的應用服務器將消息推送到咱們的App的完整路徑,其實真正完成推送的是APNS服務器,咱們本身的應用服務器只是將須要推送的消息告訴蘋果服務器,至於如何維護消息隊列或如何保證消息能被推送到指定的設備上,這些都由蘋果APNS給咱們作完了

4. Push機制類型

 

四種:徽章、提示框、聲音和橫幅,具體表現形式以下圖

Push機制的4個組件

Provider

APNS

iPhone設備

Client App

其中APNS(Apple Push Notification Service)是由蘋果提供的消息推送服務中心,全部的消息都經由這裏轉發給相應的設備

 

 

5. 正式開工

5.1 準備工做

你得有臺ios設備,iphone,ipad

 5.1.2 爲推送通知獲取受權

爲了給提供者這邊開發和配置推送通知,你必須從開發者中心(即蘋果官網 DevCenter)取得 SSL 受權證書。每一個受權證書限制必須對應一個單獨的應用,由應用的Bundle ID 標識。並且該受權證書也被限制用於如下兩個環境之一,沙箱環境(用於開發和測試)和生產環境。這些環境都擁有它本身的 IP 地址,並且須要它們本身的受權證書。你必須同時得到這些環境的的配置文件(即 Provisioning profiles)。

5.1.3 提供者和APNs之間經過二進制接口通訊

二進制接口是異步的,並且它使用 TCP 方式經過 sock 鏈接把二進制內容的推送通知發送給 APNs。沙箱和生產環境都有本身獨立的接口,每一個都有它本身的地址和端口。對於每一個接口,你須要使用 TLS(或 SSL)和已經拿到的 SSL 受權證書來創建一條到 APNs 的安全通訊通道。提供者把推送通知打包並經過該通道發送給 APNs。APNs 包含了一個反饋服務,它負責維護每一個應用的傳遞通知失敗的設備列表(即APNs 當前沒法把推送通知傳遞到這些設備上面的對應的應用)。提供者應該週期性的鏈接到反饋服務來查看推送失敗的設備以便它能夠把以前失敗的通知重複發送過
去。

開發狀態服務器地址 gateway.sandbox.push.apple.com 2195

產品狀態服務器地址 gateway.push.apple.com 2195

Development和Production兩個版本對應的apns device token是不一樣的,前者是develop的mobileprovision下獲取的。後者是production的mobileprovision獲取的。
Development和Production兩個版本能夠共用一個App ID(不推薦。共用時每次調試前都要刪除設備上的app,從新打包生成。並且公用appid會常常抓狂,早上行,下午就不行了。因此不推薦),可是不能共 用一個mobileprovision,因此要單獨生成Distribution的證書供production版本使用。
注:Distribution的版本是沒法在設備上debug調試的!
Development和Production兩個版本的code sign是不一樣的,前者是iPhone Developer,後者是iPhone Distribution。注意不能搞錯。

不管是Development Push SSLCertificate仍是Production Push SSL Certificate 都有過時時間的。Development Push SSL Certificate有效期大概四個月左右,而ProductionPush SSL Certificate的有效期是一年。須要注意在過時以前生成新的證書,以避免影響使用。

 

5.2 證書生成

 

5.2.1 過程簡介

先概述下大體過程,而後下面會截圖給出詳細的步驟

在Mac上生成 Apple推送通知SSL許可證:
 1. 登陸到 apple Developer Connection Portal 並點擊 App IDs
 2. 建立一個不使用通配符的 App ID 。通配符 ID 不能用於推送通知服務。例如,咱們的iPhone程序ID像這樣:54im.com.PushChat
 3. 點擊App ID旁的「Configure」,而後按下按鈕生產 推送通知許可證。根據「嚮導」指導的步驟生成一個簽名並上傳,最後下載生成的許可證。
 4. 經過雙擊.cer文件將你的 aps_developer_identity.cer 引入Keychain中。
 5. 在Mac上啓動 Keychain助手,而後在login keychain中選擇 Certificates分類。你將看到一個可擴展選項「Apple Development Push Servicescom.54im.PushChat」
 6. 擴展此選項而後右擊「Apple Development Push Services」 > Export 「Apple Development Push Services:com.54im.PushChat」。保存爲 PushChat_cert.p12 文件。
 7. 擴展「Apple Development Push Services」 對「Private Key」作一樣操做,保存爲 PushChat_key.p12 文件。
 8. 須要經過終端命令將這些文件轉換爲PEM格式:
openssl pkcs12 -clcerts -nokeys -out cert.pem -in PushChat_cert.p12
 9. 轉換獲得key的pem:
openssl pkcs12 -nocerts -out key.pem -in PushChat_key.p12
 10. 若是你想要移除密碼,要麼在導出/轉換時不要設定或者執行:
openssl rsa -in key.pem -out key.unencrypted.pem
 11. 最後,你須要將鍵和許可文件合成爲apns-dev.pem文件,此文件在鏈接到APNS時須要使用:
cat apns-dev-cert.pem key.unencrypted.pem > ck.pem

5.2.2 配置詳解

 1. 建立APPID

首先登錄咱們的Apple Developer後臺爲將要使用推送服務的App新建一個App ID,以下圖,點擊新建後輸入基本信息

 

我把要改的地方截圖下來了,高手勿笑哦,屌絲第一次用mac,也是第一次進蘋果開發者後臺。

APPID建立好後,咱們點編輯剛剛生成好的APPID,生成下development證書,生產狀況下用 Production證書

 

 

建立正式過程當中,要求上傳一張Certificate Signing Request 證書請求籤名文件

 

2. 生成證書請求文件

這個請求文件在本身的mac上生成

輸入證書信息

 

3. 生成PUSH證書

還記得剛剛蘋果開發者那裏要上傳的證書不,將生成好的這個.certSigningRequest證書上傳上去,

下載aps_development.cer這個證書到mac上,若是是發佈版的推送證書,就爲aps_production.cer。而後雙擊該 證書,將推送證書安裝到咱們的Mac機器上,安裝成功後會看到以下界面(若是是發佈版,則證書的Development部分顯示的是 Production)

 

須要爲certificate和它之下的private key各自export出一個.p12文件。(會出現設置密碼過程)

4. 導出公鑰

導出私鑰

 

5. key轉換

須要將上面的2個.p12文件轉成.pem格式:

openssl pkcs12 -clcerts -nokeys -out cert.pem -in Push_Chat_cert.p12
openssl pkcs12 -nocerts -out key.pem -in Push_Chat_cert_key.p12

若是須要對key不進行加密
openssl rsa -in key.pem -out key.unencrypted.pem

而後就能夠 合併兩個.pem文件, 這個ck.pem就是服務端須要的證書了
cat cert.pem key.unencrypted.pem > apns-dev.pem

建立 Provisioning Profile

 

5.3 建立 provisioning profile

 

接下來,須要建立 provisioning profile 以便容許應用程序安裝到真實設備上。

 

將該prifiles文件下載下來,名字是PushChat.mobileprovision,其實不用下載,xcode裏面會根據你的項目id自動去拉對於的這個文件。

在製做測試demo前咱們先了解下開源的一個應用 easyapns,或者你也能夠寫demo,主要就是收集DeviceToken

啥是Easy APNS

Easy APNS 是一個用來管理蘋果推送通知的PHP腳本。若是你對蘋果推送通知後端部分比較感興趣,而恰巧你有熟悉PHP,那麼Easy APNS是你工具箱中必須的工 具。Easy APNS徹底開源,而且設置很是簡單。經過使用免費的、開源的PHP腳本,Easy APNS爲開發者提供了一種很直觀的能夠用來控制整個 推送通知後端部分的方式。

項目官網:http://www.easyapns.com/

github地址:https://github.com/manifestinteractive/easyapns

github裏面有這幾個目錄

delegate 將這裏面代碼添加到新建項目的 AppDelegate.m中

php 將文件放在一個能夠訪問的web目錄下(要有php+mysql環境)

sql 將該目錄sql導入到數據庫

 

6. 客戶端製做

開始製做咱們的客戶端

在代碼中加入如下代碼

而且修改裏面的push服務器地址

如今能夠把項目編譯到iphone或者ipad上面了,注意項目 General中team配置。


而後插上本身的iphone或者ipad,就能夠點build按鈕了,這時屏幕上會彈出一個警告框,是否容許消息推送,相似於

用戶同於消息推送後,也能夠自行再關閉掉,也能夠自行調整通知方式

7. php服務器端配置

 

數據庫導入

create database pushchat DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

mysql -h 127.0.0.1 -uroot -p –databse pushchat<apns.sql

修改apns.php 和samples.php配置文件

$db = new DbConnect(‘localhost’, ‘root’, ’54im.com’, ‘pushchat’);

而後單獨修改class目錄下class_APNS.php的證書和日誌路徑

private $DEVELOPMENT = ‘sandbox’

private $logPath = ‘/usr/local/apns/apns.log

private $sandboxCertificate = ‘/usr/local/apns/ck.pem

固然你的證書也必須放到這個目錄下(就是以前合併的那個證書)

在手機上打開咱們安裝的那個PushChat應用,而後數據庫中就有手機發送過來的

8. 測試

 

消息發送測試,在服務器上執行samples.php 就能夠

php -f samples.php

備註:

服務器端,若是是php的,那必須使用.pem的證書,若是是java的,那必須使用.p12的證書。(極可能還須要雙擊證書進行安裝!)
服務器端發出的json包是有大小限制的,最大256字節,包括自定義字典集。
aps中的alert字符串裏是能夠添加」\n」作換行的。
json包中除了alert,badge,sound以外,仍是是能夠自定值的。

額外的自定義值:
$payload[‘aps’] = array(‘alert’ => ‘This is the alert text’, ‘badge’ => 1, ‘sound’ => ‘default’);
$payload[‘server’] = array(‘serverId’ => $serverId, ‘name’ => $name);
$output = json_encode($payload);
當用戶按下「View」後,自定義server值將被傳遞到設備中的程序。JSON 值以下:
{
「aps」 :
{ 「alert」 :
{
「action-loc-key」 : 「顯示」 ,
「body」 : 「This is the alert text」
},
「badge」 : 1,
「sound」 : 「default」 },
「server」 : { 「serverId」 : 1, 「name」 : 「Server name」)
}
256字節的限制適用於整個payload,包括自定義字典集。

 

IOS7以前,蘋果對於一個設備上的多個APP,生成相同的DeviceToken。
IOS7以及以後,蘋果對於一個設備上的多個APP,生成不一樣的DeviceToken。
這種新改變致使APNS上建立了一張新老token的映射表,若是你一直用老的token,那沒問題,可是,一旦服務器使用新的DeviceToken,映射表中的記錄就會被刪除,這意味着,老的DeviceToken就不能用了,必然發送失敗。
待驗證:IOS5和IOS6,APP永遠能夠獲取DeviceToken,除此以外的系統,若是用戶拒絕了,或者關閉了推送,那麼沒法獲取DeviceToken,走失敗回調。

 

 

8. 附錄:

8.1 JSON示例

如下通知負載的示例舉例說明了表 3-1 所列舉的屬性。名爲」acme」的屬性是一個
自定義負載數據的例子。該示例包含了可讀性的空白符和換行符。爲了提升性能,提
供者應該忽略空白符和換行符。
示例 1:如下負載包含哦一個簡單的 aps 字典,採用默認的警告按鈕的提示信息(關
閉按鈕和查看按鈕)。它使用字符串而不是字典做爲 alert 的值。該負載一樣包含了一
個自定義的屬性數組。
{
「aps」 : { 「alert」 : 「Message received from Bob」 },
「acme2″ : [ 「bang」, 「whiz」 ]
}
示例 2:該示例的負載包含了一個 aps 的字典,指定設備顯示一個警告消息並在左
邊包含一個關閉按鈕和右邊顯示一個本地化的」action」按鈕。在該例中,」PLAY」被做
爲鍵使用來從Localizable.strings文件裏面當前偏好語言的字典裏面獲取對應的「Play」
的字符串。aps 字典一樣要求應用程序的圖標顯示數字 5。
{
「aps」 : {
「alert」 : {
「body」 : 「Bob wants to play poker」,
「action-loc-key」 : 「PLAY」
},
「badge」 : 5,
},
「acme1″ : 「bar」,
「acme2″ : [ 「bang」, 「whiz」 ]
}
2012-01-28 |© 2012 YouMi Mobile Co. Ltd. All Rights Reserved.                   
Local and Push Notification Programming Guide
示例 3:該示例的負載指定設備應用顯示一個警告信息幷包含關閉按鈕和查看按
鈕。同時它要求應用程序的圖標顯示數字 9,並在通知顯示的時候播放主目錄廈門的
bingbong.aiff 音頻文件。
{
「aps」 : {
「alert」 : 「You got your emails.」,
「badge」 : 9,
「sound」 : 「bingbong.aiff」
},
「acme1″ : 「bar」,
「acme2″ : 42
}
示例 4:該示例的負載主要關注的是使用 alert 字典裏面的 loc-key 和 loc-args 子屬
性來從應用程序的主目錄下面獲取一個本地化的字符串並根據 loc-args 選擇合適的子
變量位於正確的位置。它一樣指定了一個自定義聲音文件 chime,幷包含了一個自定
義屬性。
{
「aps」 : {
「alert」 : { 「loc-key」 : 「GAME_PLAY_REQUEST_FORMAT」, 「loc-args」 : [ 「Jenna」,
「Frank」] },
「sound」 : 「chime」,
},
「acme」 : 「foo」
}
示例 5:下面的示例顯示了一個空的 aps 字典,由於 badge 屬性被隱藏了,因此當
前應用程序圖標的任何數字都會被移除。而自定義屬性 acme2 是一個包含兩個整形的
數組。
{
「aps」 : {
},
「acme2″ : [ 5, 8 ]
}

記住,爲了更好的性能,你應該在把字符串添加到通知裏面以前儘量的去除空
白字符和換行字符

 

8.2 檢驗證書是否正確的方法:

$ telnet gateway.sandbox.push.apple.com 2195

Trying 17.172.232.226…

Connected to gateway.sandbox.push-apple.com.akadns.net.

Escape character is ‘^]’.

它將嘗試發送一個規則的,不加密的鏈接到APNS服務。若是你看到上面的反饋,那說明你的MAC可以到達APNS。按下Ctrl+C 關閉鏈接。若是獲得一個錯誤信息,那麼你須要確保你的防火牆容許2195端口。

而後再次鏈接,此次用咱們的SSL證書和私鑰來設置一個安全的鏈接:

$ openssl s_client -connect gateway.sandbox.push.apple.com:2195

-cert PushChatCert.pem -key PushChatKey.pem

Enter pass phrase for PushChatKey.pem:

你會看到一個完整的輸出,讓你明白OpenSSL在後臺作什麼。若是鏈接是成功的,你能夠鍵入一些字符。當你按下回車後,服務就會斷開鏈接。若是在創建鏈接時有問題,OpenSSL將會給你一個錯誤消息,可是你不得不向上翻輸出LOG,來找到它。

固然上面要測試prodution版本是否正確的話,把gateway.sandbox.push.apple.com換成gateway.push.apple.com就好。

 

8.3 Push故障排除

 

8.4 APNS信息包結構體

上圖顯示的這個消息體就是咱們的服務器(Provider)發送給APNS服務器的消息結構,APNS驗證這個結構正確並提取其中的信息後,再將消 息推送到指定的設備。這個結構體包括五個部分,第一個部分是命令標示符,第二個部分是咱們的device_token的長度,第三部分是咱們的 device_token字符串,第四部分是推送消息體(Payload)的長度,最後一部分也就是真正的消息內容了,裏面包含了推送消息的基本信息,比 如消息內容,應用Icon右上角顯示多少數字以及推送消息到達時所播放的聲音等。接下來咱們拆解看一下Payload(消息體)的結構:

{
「aps」 : {
「alert」 : 「You got your emails.」,
「badge」 : 1,
「sound」 : 「default」
},
}

這其實就是個JSON結構體,alert標籤的內容就是會顯示在用戶手機上的推送信息,badge顯示的數量(注意是整型)是會在應用Icon右上 角顯示的數量,提示有多少條未讀消息等,sound就是當推送信息送達是手機播放的聲音,傳defalut就標明使用系統默認聲音,若是傳好比 「beep.wav」就會播放在咱們應用工程目錄下名稱爲beep.wav的音頻文件,好比當手機鎖屏時QQ在後臺收到新消息時的滴滴聲。

 

有這麼一種狀況,當咱們將應用從設備卸載後,推送的消息改如何處理呢。咱們知道,當咱們將應用從設備卸載後,咱們是收不到Provider給咱們推 送的消息的,可是,如何讓APNS和Provider都知道不去向這臺卸載了應用的設備推送消息呢?針對這個問題,蘋果也已經幫咱們解決了,那就是 Feedback service。他是APNS的一部分,APNS會持續的更新Feedback service的列表,當咱們的Provider將信息發給APNS推送到咱們的設備時,若是這時設備沒法將消息推送到指定的應用,就會向APNS服務器 報告一個反饋信息,而這個信息就記錄在feedback service中。按照這種方式,Provider應該定時的去檢測Feedback service的列表,而後刪除在本身數據庫中記錄的存在於反饋列表中的device_token,從而再也不向這些設備發送推送信息。鏈接 Feedback service的過程一樣使用Socket的方式,鏈接上後,直接接收由APNS傳輸給咱們的反饋列表,傳輸完成後斷開鏈接,而後咱們根據這個最新的反饋 列表在更新咱們本身的數據庫,刪除那些再也不須要推送信息的設備的device_token。從Feedback service讀取的數據結構以下:

結構中包含三個部分,第一部分是一個時間戳,記錄的是設備失效後的時間信息,第二個部分是device_token的長度,第三部分就是失效的 device_token,咱們所要獲取的就是第三部分,跟咱們的數據庫進行對比後,刪除對應的device_token,下次再也不向這些設備發送推送信 息

8.5 消息大批量發送問題

a.消息大批量發送問題

目前因爲APNS(Apple Push Notification Service)機制緣由,目前easy apns的消息發送機製爲:

對每一條發送的消息,爲全部須要推送的設備都在數據庫中apns_messages建立一條消息,而後經過輪訓數據庫表來一條一條向蘋果消息推送服務器發送消息

在須要推送的設備較多的狀況下,因爲存在大量的網絡連接,致使存在較長時間的延遲。

解決方案:

一、作批量消息推送時候,保持與蘋果消息推送服務器的長連接

二、使用批量發送機制

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

 

8.6 參考鏈接

http://blog.sina.com.cn/s/blog_6f9a9718010128hi.html

http://blog.csdn.net/ryantang03/article/details/8482259

http://www.cnblogs.com/gpwzw/archive/2012/03/31/Apple_Push_Notification_Services_Tutorial_Part_1-2.html

http://www.devdiv.com/iOS_iPhone-_ios_push_-thread-130543-1-1.html

http://blog.sina.com.cn/s/blog_7cac85620100vv2b.html

http://www.cocoachina.com/bbs/read.php?tid=98797

相關文章
相關標籤/搜索