APNS 推送
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
1.推送過(guò)程簡(jiǎn)介
? ? ?(1)App啟動(dòng)過(guò)程中,使用UIApplication::registerForRemoteNotificationTypes函數(shù)與蘋(píng)果的APNS服務(wù)器通信,發(fā)出注冊(cè)遠(yuǎn)程推送的申請(qǐng)。若注冊(cè)成功,回調(diào)函數(shù)application:(UIApplication?*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData?*)deviceToken 會(huì)被觸發(fā),App可以得到deviceToken,該token就是一個(gè)與設(shè)備相關(guān)的字符串.
? ? ?(2)App獲取到DeviceToken后,將DeviceToken發(fā)送給自己的服務(wù)端。
? ? ?(3)服務(wù)端拿到DeviceToken以后,使用證書(shū)文件,向蘋(píng)果的APNS服務(wù)器發(fā)起一個(gè)SSL連接。連接成功之后,發(fā)送一段JSON串,該JSON串包含推送消息的類(lèi)型及內(nèi)容。
? ? (4)蘋(píng)果的APNS服務(wù)器得到JSON串以后,向App發(fā)送通知消息,使得App的回調(diào)函數(shù)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary?*)userInfo被調(diào)用,App從userInfo中即可得到推送消息的內(nèi)容。
?
2.?用到的證書(shū)文件及生成過(guò)程
? ?(1)certSigningRequest文件,該文件在MAC系統(tǒng)中生成,用于在A(yíng)pple網(wǎng)站上申請(qǐng)推送證書(shū)文件。
? ? ? ? ?生成過(guò)程:
? ? ? ? ?打開(kāi)應(yīng)用程序中的“鑰匙串訪(fǎng)問(wèn)”軟件,從菜單中選擇 “鑰匙串訪(fǎng)問(wèn)”-》“證書(shū)助理”-》“從證書(shū)頒發(fā)機(jī)構(gòu)請(qǐng)求證書(shū)”,郵箱和名稱(chēng)隨便填寫(xiě),然后選擇保存到磁盤(pán),就可以在本地生成一個(gè)CertificateSigningRequest.certSigningRequest文件。
? ?(2)注冊(cè)一個(gè)支持push的app id,后面會(huì)用到。
? ? ? ? 生成過(guò)程:
? ? ? ?進(jìn)入developer.apple.com,選擇member center -?Certificates, Identifiers & Profiles ?- ?Identifiers- App Ids,然后選擇注冊(cè)app id,設(shè)置appid名稱(chēng),同時(shí),app id?suffix一欄必須選擇explicit app id,然后設(shè)置bundle id,最后勾選?App Services中的?Push Notifications,這樣就可以注冊(cè)一個(gè)支持push的aphid。
? ??
? (3) 推送證書(shū)cer文件,該文件在developer.apple.com中生成,用于生成服務(wù)端需要的文件。
? ? ? ? 生成過(guò)程:
? ? ? ? 進(jìn)入developer.apple.com,選擇member center -?Certificates, Identifiers & Profiles ?- ?Certificates,然后選擇創(chuàng)建certificate,類(lèi)型分為Development和Product。這里以Development為例,選擇Apple Push Notification service SSL (Sandbox) ,然后下一步,選擇之前生成的支持push的AppId,然后下一步,提交之前創(chuàng)建的CSR文件,再下一步就可以生成cer文件,然后保存到本地。
? (4)生成服務(wù)端使用的證書(shū)文件。如果是使用網(wǎng)上的mac 版PushMeBaby工具,在mac機(jī)器上進(jìn)行推送消息的發(fā)送,那么有上面的cer文件就夠了。如果是使用PHP、java/c#開(kāi)發(fā)自己的服務(wù)端,那么還需要將上面的cer文件做一個(gè)轉(zhuǎn)換,生成pem文件或者p12文件。
? ? ? ?生成php用的pem文件過(guò)程為:
? ? ? ? 首先雙擊前面保存的cer文件,此時(shí)會(huì)打開(kāi)“鑰匙串訪(fǎng)問(wèn)”軟件,里面會(huì)出現(xiàn)一個(gè)Apple Development ?IOS push services證書(shū),一個(gè)公用密鑰和一個(gè)專(zhuān)用秘鑰,秘鑰的名稱(chēng)與證書(shū)助理中填寫(xiě)的名稱(chēng)一致。
? ? ? 選中證書(shū),導(dǎo)出為?apns-dev-cert.p12 文件
? ? ? 選中專(zhuān)有秘鑰,導(dǎo)出為apns-dev-key.p12文件
? ? ??通過(guò)終端命令將這些文件轉(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
? ? ? 最后, 需要將兩個(gè)pem文件合并成一個(gè)apns-dev.pem文件,此文件在連接到APNS時(shí)需要使用:
? ? ? cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem
? ? ? ?生成java/c#用的p12文件過(guò)程為:
? ? ? ?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文件,該文件用于真機(jī)調(diào)試。
? ? ? ? ?生成過(guò)程:
? ? ? ? ?進(jìn)入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ù)端的開(kāi)發(fā)
? ? ?(1)如果只是希望在mac電腦上測(cè)試一下消息的推送,可以使用PushMeBaby工具,使用起來(lái)比較簡(jiǎn)單。該工具是開(kāi)源的,可以從https://github.com/stefanhafeneger/PushMeBaby 下載,代碼的執(zhí)行過(guò)程實(shí)際上就是設(shè)置一下SSL證書(shū),然后連接APNS,接著發(fā)送JSON數(shù)據(jù)。由于要處理SSL邏輯,因此代碼稍微多點(diǎn)。在使用工具時(shí),將工程資源中的cer文件替換成自己的cer文件,然后將代碼中的deviceToken替換成自己設(shè)備的deviceToken即可。
? ? ?(2)使用php開(kāi)發(fā)服務(wù)端
? ? ? ?由于php已經(jīng)內(nèi)置了ssl模塊,因此使用php連接APNS服務(wù)器來(lái)發(fā)送json的過(guò)程實(shí)際上是很簡(jiǎn)單的,代碼如下:
該文件可以放到服務(wù)器中通過(guò)瀏覽器來(lái)訪(fǎng)問(wèn),也可以通過(guò)命令行的方式來(lái)解釋執(zhí)行,代碼為:$ php -f Pusher.php
? ? ?
<?=?‘自己的deviceToken';?//沒(méi)有空格 $body?=?array("aps"?=>?array("alert"?=>?'message',"badge"?=>?2,"sound"=>''));??//推送方式,包含內(nèi)容和聲音$ctx?=?stream_context_create();//如果在Windows的服務(wù)器上,尋找pem路徑會(huì)有問(wèn)題,路徑修改成這樣的方法: //$pem?=?dirname(__FILE__)?.?'/'?.?'apns-dev.pem'; //linux?的服務(wù)器直接寫(xiě)pem的路徑即可 stream_context_set_option($ctx,"ssl","local_cert","apns-dev.pem"); $pass?=?"xxxxxx";stream_context_set_option($ctx,?'ssl',?'passphrase',?$pass);// //此處有兩個(gè)服務(wù)器需要選擇,如果是開(kāi)發(fā)測(cè)試用,選擇第二名sandbox的服務(wù)器并使用Dev的pem證書(shū),如果是正式發(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('?',?'' ?>
??? 4. 客戶(hù)端的開(kāi)發(fā)
? ? ?(1)下載前面建立的cer文件和provisioning文件,雙擊,導(dǎo)入到xcode中,在build setting中code signing一欄里選擇這兩個(gè)文件的名稱(chēng),這樣就可以將支持push的app部署到真機(jī)中。
? ? ?
? ? ?(2)處理推送消息
? ? ? ? ? ?客戶(hù)端對(duì)推送消息的處理分兩種情況:
? ? ? ? ? 一. 在A(yíng)pp沒(méi)有運(yùn)行的情況下,系統(tǒng)收到推送消息,用戶(hù)點(diǎn)擊推送消息,啟動(dòng)App。此時(shí),不會(huì)執(zhí)行前面提到的 ? ? ? ? ?didReceiveRemoteNotification函數(shù),而是在A(yíng)pp的applicationDidFinishLaunching函數(shù)中處理推送,通過(guò)以下代碼可以獲取推送消息中的數(shù)據(jù): NSDictionary *userInfo =[launchOptionsobjectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
? ? ? ? ? 二 . 當(dāng)APP處于前臺(tái)時(shí),系統(tǒng)收到推送消息,此時(shí)系統(tǒng)不會(huì)彈出消息提示,會(huì)直接觸發(fā)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo函數(shù),推送數(shù)據(jù)在userInfo字典中。
? ? ? ? ? ?當(dāng)App處于后臺(tái)時(shí),如果系統(tǒng)收到推送消息,當(dāng)用戶(hù)點(diǎn)擊推送消息時(shí),會(huì)執(zhí)行application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo函數(shù),
? ? ? ? ? 此時(shí)AppDelegate中函數(shù)執(zhí)行的順序?yàn)?#xff1a;
? ? ? ? ? applicationWillEnterForeground??
? ? ? ? ? application:didReceiveRemoteNotification
? ? ? ? ? applicationDidBecomeActive
?
轉(zhuǎn)載于:https://my.oschina.net/u/2483082/blog/524832
總結(jié)
- 上一篇: idea大小写转换
- 下一篇: 我用的/etc/vimrc