1.推送過程簡介php
(1)App啓動過程當中,使用UIApplication::registerForRemoteNotificationTypes函數與蘋果的APNS服務器通訊,發出註冊遠程推送的申請。若註冊成功,回調函數application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 會被觸發,App能夠獲得deviceToken,該token就是一個與設備相關的字符串.
(2)App獲取到DeviceToken後,將DeviceToken發送給本身的服務端。
(3)服務端拿到DeviceToken之後,使用證書文件,向蘋果的APNS服務器發起一個SSL鏈接。鏈接成功以後,發送一段JSON串,該JSON串包含推送消息的類型及內容。
(4)蘋果的APNS服務器獲得JSON串之後,向App發送通知消息,使得App的回調函數application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo被調用,App從userInfo中便可獲得推送消息的內容。java
2. 用到的證書文件及生成過程linux
(1)certSigningRequest文件,該文件在MAC系統中生成,用於在Apple網站上申請推送證書文件。
生成過程:
打開應用程序中的「鑰匙串訪問」軟件,從菜單中選擇 「鑰匙串訪問」-》「證書助理」-》「從證書頒發機構請求證書」,郵箱和名稱隨便填寫,而後選擇保存到磁盤,就能夠在本地生成一個CertificateSigningRequest.certSigningRequest文件。git
(2)註冊一個支持push的app id,後面會用到。
生成過程:
進入developer.apple.com,選擇member center - Certificates, Identifiers & Profiles - Identifiers- App Ids,而後選擇註冊app id,設置appid名稱,同時,app id suffix一欄必須選擇explicit app id,而後設置bundle id,最後勾選 App Services中的 Push Notifications,這樣就能夠註冊一個支持push的aphid。github
(3) 推送證書cer文件,該文件在developer.apple.com中生成,用於生成服務端須要的文件。
生成過程:
進入developer.apple.com,選擇member center - Certificates, Identifiers & Profiles - Certificates,而後選擇建立certificate,類型分爲Development和Product。這裏以Development爲例,選擇Apple Push Notification service SSL (Sandbox) ,而後下一步,選擇以前生成的支持push的AppId,而後下一步,提交以前建立的CSR文件,再下一步就能夠生成cer文件,而後保存到本地。json
(4)生成服務端使用的證書文件。若是是使用網上的mac 版PushMeBaby工具,在mac機器上進行推送消息的發送,那麼有上面的cer文件就夠了。若是是使用PHP、java/c#開發本身的服務端,那麼還須要將上面的cer文件作一個轉換,生成pem文件或者p12文件。c#
生成php用的pem文件過程爲:
首先雙擊前面保存的cer文件,此時會打開「鑰匙串訪問」軟件,裏面會出現一個Apple Development IOS push services證書,一個公用密鑰和一個專用祕鑰,祕鑰的名稱與證書助理中填寫的名稱一致。
選中證書,導出爲 apns-dev-cert.p12 文件
選中專有祕鑰,導出爲apns-dev-key.p12文件
經過終端命令將這些文件轉換爲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文件過程爲:xcode
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文件,該文件用於真機調試。
生成過程:
進入developer.apple.com,選擇member center - Certificates, Identifiers & Profiles - Provisioning Profiles,而後選擇建立Provisioning file,接着選擇iOS App Development ,下一步選擇AppId,選中以前創建的支持push的appid,接着下一步選擇支持push的certificate,下一步勾選須要支持的device id,最後一步設置provisioning文件的文件名,這樣provisioning文件就生成了。
服務器
3. 服務端的開發
(1)若是隻是但願在mac電腦上測試一下消息的推送,可使用PushMeBaby工具,使用起來比較簡單。該工具是開源的,能夠從https://github.com/stefanhafeneger/PushMeBaby 下載,代碼的執行過程實際上就是設置一下SSL證書,而後鏈接APNS,接着發送JSON數據。因爲要處理SSL邏輯,所以代碼稍微多點。在使用工具時,將工程資源中的cer文件替換成本身的cer文件,而後將代碼中的deviceToken替換成本身設備的deviceToken便可。
(2)使用php開發服務端
因爲php已經內置了ssl模塊,所以使用php鏈接APNS服務器來發送json的過程其實是很簡單的,代碼以下:
該文件能夠放到服務器中經過瀏覽器來訪問,也能夠經過命令行的方式來解釋執行,代碼爲:$ php -f Pusher.php
<?php $deviceToken= ‘本身的deviceToken'; //沒有空格
$body = array("aps" => array("alert" => 'message',"badge" => 2,"sound"=>'default')); //推送方式,包含內容和聲音$$ctx = stream_context_create();
//若是在Windows的服務器上,尋找pem路徑會有問題,路徑修改爲這樣的方法:
//$pem = dirname(__FILE__) . '/' . 'apns-dev.pem';
//linux 的服務器直接寫pem的路徑便可
stream_context_set_option($ctx,"ssl","local_cert","apns-dev.pem");
$pass = "xxxxxx";stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);//
//此處有兩個服務器須要選擇,若是是開發測試用,選擇第二名sandbox的服務器並使用Dev的pem證書,若是是正式發佈,使用Product的pem並選用正式的服務器
$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. 客戶端的開發
(1)下載前面創建的cer文件和provisioning文件,雙擊,導入到xcode中,在build setting中code signing一欄裏選擇這兩個文件的名稱,這樣就能夠將支持push的app部署到真機中。
(2)處理推送消息
客戶端對推送消息的處理分兩種狀況:
一. 在App沒有運行的狀況下,系統收到推送消息,用戶點擊推送消息,啓動App。此時,不會執行前面提到的 didReceiveRemoteNotification函數,而是在App的applicationDidFinishLaunching函數中處理推送,經過如下代碼能夠獲取推送消息中的數據: NSDictionary *userInfo =[launchOptionsobjectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
二 . 當APP處於前臺時,系統收到推送消息,此時系統不會彈出消息提示,會直接觸發application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo函數,推送數據在userInfo字典中。
當App處於後臺時,若是系統收到推送消息,當用戶點擊推送消息時,會執行application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo函數, 此時AppDelegate中函數執行的順序爲: applicationWillEnterForeground application:didReceiveRemoteNotification applicationDidBecomeActive