在ios中,通知有兩種(提醒轟炸的來源):php
第一種是本地通知(UILocalNotification),這一種不須要申請推送證書,也不須要向程序註冊,直接使用,這一種不是本文討論的範圍。linux
第二種是APNS遠程推送——遠程通知(UIRemoteNotification),這個不只須要向程序註冊,也須要在開發者帳號裏申請推送證書,下面來介紹一下如何註冊和申請證書。ios
先看下面一幅圖(圖片來源於無線互聯):
程序員
能夠看出,遠程推送的過程分爲6步,下面爲你們簡單講解一下:json
第一步是在程序上註冊遠程通知,這是通知的前提(程序員的工做),註冊好後,當用戶下載完咱們的應用並打開時,app會彈出一個alertView,問是否容許該應用像你發送通知,以下圖:服務器
當用戶選擇「好」以後,ios 這個操做系統將會告訴APNS這個服務器,這樣一來,當程序運行時,apns就會給程序發送那一臺設備的 device token(惟一),這時候要作的操做就是獲取這個token值(appDelegate的代理方法),並將這個token值發送到公司的服務器上去,讓他存儲下來。若是用戶選擇「不容許」,ios 這個操做系統將不會告訴apns這個服務器,那麼到這一步也就完結了。app
咱們的服務器拿到token值後也不是隨意就能向設備發送推送的,還須要一個證實身份的文件——推送證書,有了這個推送證書後,當有事情發生時,服務器即可以主動向用戶發送遠程推送了
socket
下面來說解一下這個過程post
在 didFinishLaunchingWithOptions 裏寫上 :測試
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound]; //後面的具體操做省略,程序員們可自由發揮 }
這樣寫就是會提醒,在程序上顯示通知數,推送的過程當中有鈴聲。
經過:
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
代理方法來獲取 device token,在這裏,通常進行的是post請求,將deviceToken值發給服務器
注意:咱們拿到的deviceToken 是帶有空格的,交給服務器時,咱們要將空格去掉(這也能夠交給服務器來作)
當收到遠程通知時,將調用以下代理方法:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{ //這裏書寫的代碼應該可讓程序進入到相關的頁面 }
選擇 :
——>
——>
點擊「鑰匙串訪問」
而後選擇「從證書頒發機構請求證書,如圖:
看到以下界面,郵箱填一個你本身的:
這邊名字隨便起一個
而後點擊繼續在桌面上就生成了一個證書了(申請一個就足夠了):
打開99美圓開發者帳號,進入到申請證書的頁面:
點擊「證書」:
選擇App IDs
找到你想發送遠程推送的那一個App ID,點擊它:
點擊"edit」 進行編輯,看到以下界面:
將Push Notifications 的 「勾」 勾上,選擇下面的 「Create Certification」 ,將剛剛申請的本地證書上傳上去:
點擊Continue :
最後將其下載下來,這裏只示範開發證書,不示範發佈證書的申請了,兩個證書都申請好了以後,再次點擊「edit」能夠看到以下界面:
到這裏,申請證書的工做就算完成了。
下面以開發描述文件爲例,發佈描述文件步驟相同
如圖,選擇申請開發描述文件:
這裏要選擇咱們用於推送的app 的app id
選擇」continue「 選擇證書
將設備所有選上
最後給描述文件起一個名字,並下載下來
點擊生成後,下載雙擊安裝就完成了。
下面只製做push開發證書,push 發佈證書的製做過程是同樣的,不一樣之處,下文會說明。
雙擊點擊剛剛安裝的下載的證書,這樣證書就進去到鑰匙串裏面去了,在鑰匙串的中找到那一個證書,將其導出爲.p12文件,如圖:
最好創建一個文件夾將全部的證書放在同一個地方,由於最後生成的證書也是在那個位置,給p12取一個名字,存到指定文件夾中:
點擊「存儲」以後要輸入一個密碼,這個密碼隨便輸一個,可是要記住,由於在接下來的步驟中要用得上
在桌面上創建了一個叫「通知」的文件夾,裏面放着全部的證書,如圖:
這樣p12就準備好了
打開終端應用程序,訪問到你證書存放的那個目錄下(如訪問到桌面「通知」文件夾,在終端輸入:
cd /Users/aec/Desktop/通知 ):
輸入後敲回車
進到文件夾目錄後,輸入如下命令將證書轉換成.pem文件:
openssl x509 -in 證書名字.cer -inform der -out push_developer_cer.pem
如圖:
能夠看到文件夾裏多了一個.pem文件:
在終端輸入:
openssl pkcs12 -nocerts -out pushKey.pem -in p12名字.p12
如圖:
敲入回車後,會讓你輸入p12的密碼,這個密碼你輸出來數看不見的,可是你確實輸了,輸完後在敲回車
接下來會讓你輸入兩次新生成的.pem文件的密碼,這個密碼也是看不見的(這個密碼之後要給服務器使用,要牢記)如圖:
能夠看到,文件夾又生成了一個新的文件:pushKey.pem
將上述新產生的文件合併,在終端輸入命令後敲回車:
cat 下載證書生成的.pem p12生成的.pem > 最終證書的名字.pem
如圖:
能夠看到,文件夾又生成了一個新的文件:final_Push_developer.pem(這個密碼要記住是pushKey.pem生成時要輸入的密碼,密碼須要給到服務器)
在終端輸入(開發用的驗證):
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert 下載證書生成的.pem -key p12生成的.pem
若是是發佈證書的驗證,輸入:
openssl s_client -connect gateway.push.apple.com:2195 -cert 下載證書生成的.pem -key p12生成的.pem
以後會讓你輸入密碼,輸入密碼後,會有大量openssl消息,當你任意輸入幾個字符時,服務器會提示斷開
如圖:
以上省略若干行後出現下圖:
這時候你就能夠把final_Push_developer.pem 和相應的密碼 交給服務器端了,告訴他們這個證書是沒有問題的
如下php代碼能夠直接交給服務器,或者讓他們本身寫均可以
<?php $deviceToken= 'da6d8206503c8e62e68b5df1b36c3b58ced1588c6dabe0fc9e6828961aeb36d9'; //沒有空格 $body = array("aps" => array("alert" => '推送的內容',"badge" => 1,"sound"=>'default')); //推送方式,包含內容和聲音 $ctx = stream_context_create(); //若是在Windows的服務器上,尋找pem路徑會有問題,路徑修改爲這樣的方法: //$pem = dirname(__FILE__) . '/' . 'apns-dev.pem'; //linux 的服務器直接寫pem的路徑便可 stream_context_set_option($ctx,"ssl","local_cert","26ck.pem"); $pass = "123123"; 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); //這邊能夠弄一個循環實現多個deviceToken 值,這裏暫用一個token值得方法 $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); ?>