1.推送過程簡介
(1)App啟動過程中胶坠,使用UIApplication::registerForRemoteNotificationTypes函數(shù)與蘋果的APNS服務(wù)器通信君账,發(fā)出注冊遠程推送的申請。若注冊成功沈善,回調(diào)函數(shù)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 會被觸發(fā)乡数,App可以得到deviceToken椭蹄,該token就是一個與設(shè)備相關(guān)的字符串.
(2)App獲取到DeviceToken后,將DeviceToken發(fā)送給自己的服務(wù)端净赴。
(3)服務(wù)端拿到DeviceToken以后绳矩,使用證書文件,向蘋果的APNS服務(wù)器發(fā)起一個SSL連接玖翅。連接成功之后翼馆,發(fā)送一段JSON串,該JSON串包含推送消息的類型及內(nèi)容烧栋。
(4)蘋果的APNS服務(wù)器得到JSON串以后写妥,向App發(fā)送通知消息,使得App的回調(diào)函數(shù)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo被調(diào)用审姓,App從userInfo中即可得到推送消息的內(nèi)容。
2. 用到的證書文件及生成過程
(1)certSigningRequest文件祝峻,該文件在MAC系統(tǒng)中生成魔吐,用于在Apple網(wǎng)站上申請推送證書文件。
生成過程:
打開應用程序中的“鑰匙串訪問”軟件莱找,從菜單中選擇 “鑰匙串訪問”-》“證書助理”-》“從證書頒發(fā)機構(gòu)請求證書”酬姆,郵箱和名稱隨便填寫,然后選擇保存到磁盤奥溺,就可以在本地生成一個CertificateSigningRequest.certSigningRequest文件辞色。
(2)注冊一個支持push的app id,后面會用到浮定。
生成過程:
進入developer.apple.com相满,選擇member center - Certificates, Identifiers & Profiles? -? Identifiers- App Ids,然后選擇注冊app id桦卒,設(shè)置appid名稱立美,同時,app id suffix一欄必須選擇explicit app id方灾,然后設(shè)置bundle id建蹄,最后勾選 App Services中的 Push Notifications,這樣就可以注冊一個支持push的aphid紫岩。
(3) 推送證書cer文件宪赶,該文件在developer.apple.com中生成亦歉,用于生成服務(wù)端需要的文件。
生成過程:
進入developer.apple.com劲腿,選擇member center - Certificates, Identifiers & Profiles? -? Certificates,然后選擇創(chuàng)建certificate蔫巩,類型分為Development和Product谆棱。這里以Development為例快压,選擇Apple Push Notification service SSL (Sandbox) ,然后下一步垃瞧,選擇之前生成的支持push的AppId蔫劣,然后下一步,提交之前創(chuàng)建的CSR文件个从,再下一步就可以生成cer文件脉幢,然后保存到本地。
(4)生成服務(wù)端使用的證書文件嗦锐。如果是使用網(wǎng)上的mac 版PushMeBaby工具嫌松,在mac機器上進行推送消息的發(fā)送,那么有上面的cer文件就夠了奕污。如果是使用PHP萎羔、java/c#開發(fā)自己的服務(wù)端,那么還需要將上面的cer文件做一個轉(zhuǎn)換碳默,生成pem文件或者p12文件贾陷。
生成php用的pem文件過程為:
首先雙擊前面保存的cer文件,此時會打開“鑰匙串訪問”軟件嘱根,里面會出現(xiàn)一個Apple Development? IOS push services證書髓废,一個公用密鑰和一個專用秘鑰,秘鑰的名稱與證書助理中填寫的名稱一致该抒。
選中證書慌洪,導出為 apns-dev-cert.p12 文件
選中專有秘鑰,導出為apns-dev-key.p12文件
通過終端命令將這些文件轉(zhuǎn)換為PEM格式:
openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12
最后凑保, 需要將兩個pem文件合并成一個apns-dev.pem文件冈爹,此文件在連接到APNS時需要使用:
cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem
生成java/c#用的p12文件過程為:
openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12
openssl pkcs12 -export -in apns-dev-cert.pem -inkey apns-dev-key.pem -certfile CertificateSigningRequest.certSigningRequest -name "push" -out push.p12
(5)生成XCODE使用的provisioning文件,該文件用于真機調(diào)試。
生成過程:
進入developer.apple.com愉适,選擇member center - Certificates, Identifiers & Profiles? -? Provisioning Profiles犯助,然后選擇創(chuàng)建Provisioning? file,接著選擇iOS App Development 维咸,下一步選擇AppId剂买,選中之前建立的支持push的appid,接著下一步選擇支持push的certificate癌蓖,下一步勾選需要支持的device id瞬哼,最后一步設(shè)置provisioning文件的文件名,這樣provisioning文件就生成了租副。
3. 服務(wù)端的開發(fā)
(1)如果只是希望在mac電腦上測試一下消息的推送坐慰,可以使用PushMeBaby工具,使用起來比較簡單用僧。該工具是開源的结胀,可以從https://github.com/stefanhafeneger/PushMeBaby 下載赞咙,代碼的執(zhí)行過程實際上就是設(shè)置一下SSL證書,然后連接APNS糟港,接著發(fā)送JSON數(shù)據(jù)攀操。由于要處理SSL邏輯,因此代碼稍微多點秸抚。在使用工具時速和,將工程資源中的cer文件替換成自己的cer文件,然后將代碼中的deviceToken替換成自己設(shè)備的deviceToken即可剥汤。
(2)使用php開發(fā)服務(wù)端
由于php已經(jīng)內(nèi)置了ssl模塊颠放,因此使用php連接APNS服務(wù)器來發(fā)送json的過程實際上是很簡單的,代碼如下:
該文件可以放到服務(wù)器中通過瀏覽器來訪問吭敢,也可以通過命令行的方式來解釋執(zhí)行碰凶,代碼為:$ php -f Pusher.php
復制代碼
array("alert" => 'message',"badge" => 2,"sound"=>'default'));? //推送方式,包含內(nèi)容和聲音$$ctx = stream_context_create();
//如果在Windows的服務(wù)器上省有,尋找pem路徑會有問題痒留,路徑修改成這樣的方法:
//$pem = dirname(__FILE__) . '/' . 'apns-dev.pem';
//linux 的服務(wù)器直接寫pem的路徑即可
stream_context_set_option($ctx,"ssl","local_cert","apns-dev.pem");
$pass = "xxxxxx";stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);//
//此處有兩個服務(wù)器需要選擇,如果是開發(fā)測試用蠢沿,選擇第二名sandbox的服務(wù)器并使用Dev的pem證書,如果是正式發(fā)布匾效,使用Product的pem并選用正式的服務(wù)器
$fp = stream_socket_client("ssl://gateway.push.apple.com:2195", $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
$fp = stream_socket_client("ssl://gateway.sandbox.push.apple.com:2195", $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
if (!$fp)
{echo "Failed to connect $err $errstrn";return;}
print "Connection OK\n";
$payload = json_encode($body);$msg = chr(0) . pack("n",32) . pack("H*", str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;
echo "sending message :" . $payload ."\n";
fwrite($fp, $msg);? fclose($fp);
?>
復制代碼
4. 客戶端的開發(fā)
(1)下載前面建立的cer文件和provisioning文件舷蟀,雙擊,導入到xcode中面哼,在build setting中code signing一欄里選擇這兩個文件的名稱野宜,這樣就可以將支持push的app部署到真機中。
(2)處理推送消息
客戶端對推送消息的處理分兩種情況:
一. 在App沒有運行的情況下魔策,系統(tǒng)收到推送消息匈子,用戶點擊推送消息,啟動App闯袒。此時虎敦,不會執(zhí)行前面提到的? ? ? ? ? didReceiveRemoteNotification函數(shù),而是在App的applicationDidFinishLaunching函數(shù)中處理推送政敢,通過以下代碼可以獲取推送消息中的數(shù)據(jù): NSDictionary *userInfo =[launchOptionsobjectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
二 . 當APP處于前臺時其徙,系統(tǒng)收到推送消息,此時系統(tǒng)不會彈出消息提示喷户,會直接觸發(fā)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo函數(shù)唾那,推送數(shù)據(jù)在userInfo字典中。
當App處于后臺時褪尝,如果系統(tǒng)收到推送消息闹获,當用戶點擊推送消息時期犬,會執(zhí)行application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo函數(shù),
此時AppDelegate中函數(shù)執(zhí)行的順序為:
applicationWillEnterForeground
application:didReceiveRemoteNotification
applicationDidBecomeActiveI