天天看點

iOS用戶端的APNS服務簡介與實作

apns --apple push notification service

apns 蘋果推送伺服器

device 安裝帶有推送服務程式的iphone手機

provider 程式伺服器,把需要推送的資訊發給 apns

devicetoken 在device第一次連接配接apns時,由apns生成的經過加密的連接配接認證資訊。在以後的連接配接中,無論時provider到apns還是apns到device 都需要 devicetoken作為認證。

payload 需要推送的消息的主體内容。alert-alert消息的消息體,按鍵标題等badge-顯示在程式icon右上角的數字,sound-聲音提示檔案的檔案名,該聲音資源檔案要在程式包中。

整體流程大體分為五個步驟:

1: device --> 連接配接--> apns 擷取 devicetoken

2: device-->連接配接-->provider提供devicetoken

iOS用戶端的APNS服務簡介與實作

3: provider偵測需要push的消息生成notification資訊

iOS用戶端的APNS服務簡介與實作

4: provider偵把要push的消息推送到apns

5: apns把該消息推送到手機

iOS用戶端的APNS服務簡介與實作

介紹完apns的概況,下面再了解一下具體的實作方法:

注:先申請apns的證書,再進行以下操作。

1. 将app注冊notification裡面, 并從apns上擷取測試機的devicetoken.

- (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions {

   [[uiapplication sharedapplication] registerforremotenotificationtypes:(uiremotenotificationtypebadge | uiremotenotificationtypesound)];

       // other codes here.

   return yes;

}

- (void)application:(uiapplication *)application didregisterforremotenotificationswithdevicetoken:(nsdata *)devicetoken {

   nslog(@”devicetoken: %@”, devicetoken);

- (void)application:(uiapplication *)application didfailtoregisterforremotenotificationswitherror:(nserror *)error {

   nslog(@”error in registration. error: %@”, error);

- (void)application:(uiapplication *)application didreceiveremotenotification:(nsdictionary *)userinfo

{

   nslog(@” 收到推送消息 : %@”,[[userinfo objectforkey:@"aps"] objectforkey:@”alert”]);

   if ([[userinfo objectforkey:@"aps"] objectforkey:@”alert”]!=null) {

       uialertview* alert = [[uialertview alloc] initwithtitle:@”推送通知”

                                                       message:[[userinfo objectforkey:@"aps"] objectforkey:@”alert”]

                                                      delegate:self

                                             cancelbuttontitle:@” 關閉”

                                             otherbuttontitles:@” 更新狀态”,nil];

       [alert show];

       [alert release];

   }

啟動程式,将app注冊到通知項後,在console裡面找到列印的devicetoken:

devicetoken: <6974ac11 870e09fa 00e2238e 8cfafc7d 2052e342 182f5b57 fabca445 42b72e1b>

2. 生成app在服務端需要的許可證

1)進入provisioning portal, 下載下傳certificates在development下的證書。

2) 找到需要測試的app id,然後enable它在development下的apple push notification service: development push ssl certificate。需要輸入1)中的簽名證書才可以生成一個aps_developer_identity.cer.

3) 輕按兩下aps_developer_identity.cer,會打開系統的key chain. 在my certificates下找到apple development push services。需要為certificate和它之下的private key各自export出一個.p12檔案。(會出現設定密碼過程)

4)需要将上面的2個.p12檔案轉成.pem格式:

openssl pkcs12 -clcerts -nokeys -out cert.pem -in cert.p12

openssl pkcs12 -nocerts -out key.pem -in key.p12

5)如果需要對 key不進行加密:

openssl rsa -in key.pem -out key.unencrypted.pem

6)然後就可以 合并兩個.pem檔案, 這個ck.pem就是服務端需要的證書了。

cat cert.pem key.unencrypted.pem > ck.pem

3. 服務端push通知到anps. 在cocoachina找到了兩種方法:

1)php驅動。需要将ck.pem和php腳本放到server 上。全部的php代碼是:

<?php

$devicetoken = ’6974ac11 870e09fa 00e2238e 8cfafc7d 2052e342 182f5b57 fabca445 42b72e1b’;

$pass = ’123456′;   // passphrase for the private key (ck.pem file)

// get the parameters from http get or from command line

$message = $_get['message'] or $message = $argv[1] or $message = ‘a test message from worldcup’;

$badge = (int)$_get['badge'] or $badge = (int)$argv[2];

$sound = $_get['sound'] or $sound = $argv[3];

// construct the notification payload

$body = array();

$body['aps'] = array(‘alert’ => $message);

if ($badge)

 $body['aps']['badge'] = $badge;

if ($sound)

 $body['aps']['sound'] = $sound;

/* end of configurable items */

$ctx = stream_context_create();

stream_context_set_option($ctx, ‘ssl’, ‘local_cert’, ‘ck.pem’);

// assume the private key passphase was removed.

stream_context_set_option($ctx, ‘ssl’, ‘passphrase’, $pass);

// connect to apns

$fp = stream_socket_client(‘ssl://gateway.sandbox.push.apple.com:2195′, $err, $errstr, 60, stream_client_connect, $ctx);

if (!$fp) {

   print “failed to connect $err $errstr\n”;

   return;

else {

  print “connection ok\n<br/>”;

// send message

$payload = json_encode($body);

$msg = chr(0) . pack(“n”,32) . pack(‘h*’, str_replace(‘ ‘, ”, $devicetoken)) . pack(“n”,strlen($payload)) . $payload;

print “sending message :” . $payload . “\n”;

fwrite($fp, $msg);

fclose($fp);

?>

請 求一次 http://127.0.0.1/apns /apns.php?message=a%20test%20message%20from%20localhost&badge=2& sound=received5.caf就 會向apns進行一次推送。我的請求結果如下:

connection ok

                2. sending message :{“aps”:{“alert”:”a test message from localhost”,”badge”:2,”sound”:”received5.caf”}}