學習怎樣爲你的iphone程序添加推送通知 php
這是由iOS教程組成員Matthijs Hollemans撰寫的一篇有關推送通知的教程,Matthijs Hollemans是一位有着豐富經驗的iOS開發者和設計者。 node
在iOS系統裏,應用程序在後臺運行的時候有不少事情都作不了(譯者注:因爲沙盒限制)。應用程序只容許在這個「沙盒」內作一些操做,這樣能夠減緩電池的消耗,延長電池的使用時間。 mysql
可是,假如用戶如今沒有在用你的程序,而你的程序剛好發生了一些有趣的事情,而你也想讓用戶知道,這時你該怎麼作? ios
例如,用戶收到了一條tweet的新消息,他們喜歡的隊伍贏得了比賽,或者晚飯已經準備好了。由於應用如今沒有在運行,程序就接收不到這些新消息。 web
幸運的是,蘋果公司爲這種狀況提供了一個解決辦法。你能夠寫一個服務器端的組件來解決這樣的問題,而不是讓應用不斷的在後臺運做,檢查事件的發生。當一些有趣的事件發生的時候,服務器端的組件能夠發送一個推送通知! sql
下面是推送通知能夠作的三件事: 編程
·顯示一條短信息 xcode
·播放一個簡短的提示聲音 安全
·在程序的圖標上設置推送消息數量 服務器
你能夠根據須要,隨意組合以上三項功能;例如,你能夠播放簡短的提示聲音和設置應用圖標上推送消息的未讀數量,但不顯示消息。
在這兩部分的系列教程裏,你將經過建立一個簡單使用APNS(蘋果的推送通知)的app,來實現推送通知。
首先,在第一部分教程裏面,你將學習怎麼設置應用程序,來接受推送通知和一條測試消息。
這篇教程是爲中高級iOS開發者寫的。若是你只是一個iOS開發的初學者,應該先學習這個網站的其餘教程。因此,對於初學者,強力推薦先學習下面的兩篇教程:
閒話少說,讓咱們把完成它!
簡要概述
想讓應用程序的推送功能正常工做,你須要至關多的努力,這個過程很是繁瑣。如下是這個過程的概述圖:
1.應用程序須要激活推送通知功能。在使用以前,用戶須要確認他是否願意接受這些推送功能。
2.應用程序接到一個「device token」。你能夠認爲「device token」是推送通知發送信息的目的地址。
3.應用程序會將「device token」發送給你的服務器
4.當你的應用程序發生了有趣的事情,你的服務器向 「蘋果推送通知的服務器(Apple Push Notification Service,縮寫,APSN)」發送通知。
5.APSN再向用戶的設備(例如,iPhone,iPad等)發送通知。
當用戶的設備接受到推送通知,將會顯示提醒框,播放提示聲音,更新圖標的未讀信息數目。用戶能夠經過點擊提醒框來加載應用程序,蘋果公司給推送通知加入了可選內容,你能夠根據需求來操做推送通知。
當iOS4實現了本地通知和多任務,蘋果的推送通知是否還有使用價值?固然有!
本地通知被定時事件調度限制,而且只有VOIP、導航、後臺音頻播放這些應用在後臺沒有被限制。若是當應用程序處於關閉狀態時,你想將外部事件的發生通知給你的應用程序用戶,仍然須要推送通知。
在這篇教程中,我將解釋推送通知系統實現的細節以及如何在應用中創建推送。這裏有不少要解釋的,這須要(您)花點兒時間去明白。
你須要爲推送作些什麼
在你的應用中添加推送通知,你須要:
一臺iPhone或者iPad 推送通知不能在模擬器上實現,因此你須要在設備上測試。
一個iOS開發者證書 你須要一個新的AppID和每一個應用程序使用的推送證書,推送服務器須要的「SSL 」證書,你可在iOS開發網站上作這些。
若是你想跟隨這篇教程的例子學習,你將須要建立你本身的推送證書和SSL證書,你不可使用個人這些證書。由於得到正確的證書是很重要的,我將詳細解釋如何獲得一個推送證書。
一個聯網的服務器 推送通知一般是由服務器來發送的。對於開發,你可使用一個Mac來代替服務器(咱們將在教程中這樣作),可是發佈的產品,你至少須要相似VPS( Virtual Private Server )的服務器。
一個廉價的共享虛擬主機帳戶不能知足發佈產品的須要。你須要在服務器的後臺啓動一個進程,安裝一個SSL證書,而且可以在某個端口中可以外聯TLS。
大部分的共享虛擬主機並不讓你實現這些功能,即便若是申請的這些需求經過了。不管怎麼樣,我真的建議你使用一個VPS主機,像Linode。
解析一個推送通知
你的服務器負責建立一個推送通知消息,因此瞭解一個推送通知消息的構成是有必要的。
一個推送通知是一個短信息,由「device token」,「payload–負載內容」,和其餘的一些字節組成。「payload–負載內容」是咱們感興趣的部分,由於它包含着咱們實際想發送出去的數據。
你的服務器必須提供「payload–負載內容」,它是以JSON的字典的數據格式來組織數據的。下面是一個很簡單的推送消息payload:
{ "aps": { "alert": "Hello, world!", "sound": "default" } }
對於不瞭解JSON的人,一個block的劃分由一對花括號「{}」包裹,其中包含一個由「鍵/值 (key/value)」對組成的「字典」,(就像NSDictionary)。
「payload–負載內容」就是一個「字典」,包含了至少一個「aps」項,「aps」自己也是一個「字典」。在咱們的例子中,「aps」包含「alert」和「sound」字段。當這個推送通知被接收後,它將顯示一個包含「Hello, world!」內容的提醒框,而且播放標準的提示音。
你能夠向「aps」添加另外的選項,來配置通知,例如
{ "aps": { "alert": { "action-loc-key": "Open", "body": "Hello, world!" }, "badge": 2 } }
如今「alert」是一個字典。」action-loc-key」 對應的value替代了「View」按鈕上的文本內容,」badge」字段包含的數字將被顯示在應用圖標上,這個通知不會播放提示音。
有不少途徑去設置JSON的「payload–負載」內容,你能夠改變播放聲音,你能夠提供本地化的文本,而且添加本身的字段。更多信息,請詳見官方Local and Push Notification Programming Guide。
推送通知的目標就是精短;「payload–負載內容」的大小不能超過256個字節。這樣留給你的空間和一條短消息或者一個tweet消息的大小同樣。一個小型的推送服務不會在換行符和空格上浪費空間,這樣一條推送就像下面所顯示的:
{「aps」:{「alert」:」Hello, world!」,」sound」:」default」}}
上面這條消息可讀性比較低,可是它節省了足夠的字節,因此犧牲可讀性是值得的。若是一個推送通知的payload超過了256個字節,那麼這個推送就不會被「APNS」接受。
關於推送通知常見的錯誤
推送通知是不可靠的
推送通知是不可靠的!即便APNS(Apple Push Notification Service蘋果推送通知服務)服務器接受了推送通知,仍然沒法保證該通知最終會被送達。
就你的服務器而言,推送通知會被髮出而且遺忘掉;當你將通知發送到APNS後,沒有辦法查出它所處的狀態。通知送達的時間也從幾秒到半小時不等。
一樣,用戶的iPhone不是全部時間均可以收到推送通知。好比,由於指定的端口被封,手機處於一個不容許和APNS鏈接的WIFI網絡。或者手機已經關機了。
APNS將會在手機鏈接到可用網絡後下發從該機器收到的最後一條通知,可是隻會嘗試有限的時間。一旦發送超時,此條通知就會永遠丟失!
After looking at the APNS Server Bill
推送通知會使開銷很大!若是你掌控了須要推送的內容,在你的應用中加入推送功能至關容易和廉價,可是當你有好多用戶和數據須要輪詢的時候,這個功能就會使得服務器開銷龐大(譯者注:不必定指價格,包括是資源消耗)。
好比,你打算在本身的RSS訂閱更新的時候通知用戶,這樣作沒問題。由於你控制着RSS訂閱,而且知道它什麼時候發生變化——當你更新網站內容時——因而你的服務器能夠在合適的時候發出通知。
可是若是你的應用是一款RSS閱讀器,容許用戶添加自定義的連接呢?這種狀況下,你須要構建一些機制去檢測那些訂閱的更新。
實際上,這意味着你的服務器爲了檢查那些訂閱的變化,須要不停的輪詢它們。若是你擁有不少用戶,你可能不得不安裝一堆新服務器去處理這些工做和知足帶寬需求。對於這類應用,推送會變得異常昂貴,可能不值得去作。
好了,理論上足夠了。下面到時間來學習如何使用推送了。在咱們投入到美好的事物——編程!以前——有一些無聊的搭建環境的工做須要在iOS Provisioning Portal上完成,因此讓咱們儘快完成它。
Provisioning Profiles和證書,天哪!
APNS須要一個證書
在你的應用中使用推送通知,須要用一個配置過推送功能的provisioning profile來簽名。此外,你服務器全部與APNS的通信都須要進行SSL證書籤名。
Provisioning profile和SSL證書緊密聯繫在一塊兒,而且只對一個App ID有效。這個保護措施能夠保證只有你的服務器能夠發推送通知到你的應用,其它服務器不能夠。
正如你所知道的,應用程序在開發和發佈階段使用不一樣的provisioning profiles。一樣,推送服務器的證書也有兩種:
· Development. 若是你的應用程序運行在debug模式,而且使用的是Development provisioning profile (Code Signing Identity 是 「iPhone Developer」)簽名的,你的服務器必須使用Development證書。
· Production. 使用Ad Hoc方式發佈的,或發佈在App Store(Code Signing Identify 是 「iPhone Distribution」)上的應用程序,必須和使用Production證書籤名的服務器通信。若是這裏面有不匹配,推送通知將沒法送達你的應用。
在這篇教程裏,咱們不須要爲分發profiles和證書煩惱,只須要使用Development版本的便可。
生成證書籤名請求(Certificate Signing Request, CSR)
還記得你在註冊成爲iOS開發者以後,如何去iOS Provisioning Portal生成一個開發證書嗎?若是記得,下面的步驟應該會比較熟悉。不過,我仍然建議你準確地按照步驟來作。由於大多數在實現推送通知過程當中遇到的問題,都是因爲證書問題引發的。
數字證書基於公鑰-私鑰加密方法。你不須要知道任何關於證書的加密方法,可是你要知道證書一直會與一個私鑰搭配使用。
證書是密鑰對的非祕密的部分。將它發送給其它人是安全的,好比經過SSL通信的過程當中就會包含證書。然而,對於私鑰,固然是私有的。它是祕密的。你的私鑰只對你有用,對其餘人沒用。要重視的是:若是你沒有私鑰的話,就沒法使用證書。
每當申請一個數字證書的時候,你須要提供一個證書籤名請求,簡稱CSR。當你建立了CSR後,會生成一個新的私鑰保存到keychain應用程序中。而後你將CSR發送到一個證書頒發機構(目前狀況下就是iOS Developer Portal),它會根據CSR中的信息生成SSL證書。
打開Mac中的Keychain Access程序(在Applications/Utilities下),選擇菜單中的Request a Certificate from a Certificate Authority…
若是菜單中沒有「Request a Certificate from a Certificate Authority with key」選項,就先去下載安裝WWDR Intermediate Certificate。而且確認Keychain Access窗口裏沒有私鑰被選中。
如今,你應該會看到下面的窗口:
在裏面輸入你的郵件地址,聽有人推薦說最好使用和註冊IOS開發者證號一樣的郵件地址,但看起來任何郵件地址均可以。在Common Name中輸入「PushChat」。你能夠輸入任何字符串,但最好是有意義的。這會使你之後容易查找這個私鑰。
選擇Saved to disk選項,點擊Continue。將文件保存爲「PushChat.certSigningRequest」。
若是你切換到Keychain Access軟件的Keys標籤,你將會看到一個新的私鑰出如今你的鑰匙串裏。右鍵點擊它,選擇Export。
將私鑰保存爲「PushChatKey.p12」,輸入一個密碼短語。
爲了教程的方便,我用了密碼短語「pushchat」來保護這個p12文件,可是你應該選擇一些更不容易被猜出的。記住,私鑰是要保密的。另外,必定要選擇你能記住的密碼短語,不然之後就沒法使用這個密鑰了。
一個很是簡單的程序
目前尚未激動人心的地方,可是前面的那些準備工做是必須的。我將會詳細介紹如何生成證書,由於它不是你天天都要作的,可是沒有證書推送就不能工做。
由於能夠鏈接到沙盒服務器,因此證實咱們的證書是有效的。讓咱們來測試一下,是否是真的能推送一些消息!
點擊Xcode而後選擇File,建立一個新的Project。選擇View-based Application模板,而後下一步
· Product Name項目名:PushChat
· Company Identifier公司ID: com.hollance
· Device Family設備: iPhone
Bundle ID由項目名稱和公司ID組成。個人項目ID叫「com.hollance.PushChat」
你應該讓你的Product Name和Company Identifier 與你早先用App ID在Provisioning Portal 註冊的相一致(com.yourname.PushChat).
完成後打開PushChatAppDelegate.m,將didFinishLaunchingWithOptions 方法改爲下面的樣子:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; //讓設備知道咱們想要收到推送通知 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; return YES; }
調用registerForRemoteNotificationTypes 告訴OS 這個App想要接收推送消息。
編譯運行。你須要在真機上運行這個程序,由於模擬器不支持推送通知。
Xcode應該會自動選擇新的provisioning profile。若是你獲得一個簽名錯誤,那麼請確認在Code Signing build settings中選擇了正確的profile。
當應用程序啓動了推送通知,它會顯示一個消息通知用戶,它想推送通知。
這個app推送請求只出現一次。若是用戶選「肯定」,那麼咱們的推送通知就全設置好了。
然而,若是他們選擇「不容許」,那麼咱們的應用程序將不會接收到推送通知。用戶能夠在手機設置裏改變他們的決定。
你能夠在setting -> Notifications裏面找到你的應用程序,用戶能夠在這裏啓用或禁用
應用程序的通知,包括標記、聲音和警報。
你的app能夠查看哪些推送類型被啓用,用如下代碼來查看
UIRemoteNotificationType enabledTypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
爲了能收到推送消息,咱們還要在app中添加一些內容。將下列代碼添加到PushChatAppDelegate.m中:
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken { NSLog(@」My token is: %@」, deviceToken); } - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error { NSLog(@"Failed to get token, error: %@", error); }
當你的應用程序註冊遠程通知時,它將會嘗試得到一個「設備標記(device token)」。
這是一個32字節數字,標識你的設備的惟一性。 能夠把device token理解爲推送消息的接收地址。
再次運行程序,你應該能在Xcode的控制檯窗口看到下面這個:
My token is:
<740f4707 bebcf74f 9b7c25d4 8e335894 5f6aa01d a5ddb387 462c7eaf 61bb78ad>
這個標識是一個封裝的二進制數據結構,裝入一個NSData對象裏。蘋果不但願你看見它的內部信息,就咱們而言知道它是32字節長就夠了。
正如你上面所看到的,標識也可用64位十六進制字符表示,咱們將用這種格式使用設備標識,固然還要去掉分隔符和空格。
若是你在模擬器上運行這個程序,因爲你的模擬器不支持推送通知,didFailToRegisterForRemoteNotificationsWithError方法將被調用。
這個應用就是這樣。還有一件事要作,以後咱們立刻就能夠看到一些推送通知,當即行動!
我以前已經提到了幾回,你須要建立一個服務器,它將推送通知給你的app。
第一次測試程序,咱們不會去創建一個服務器。相反,我會給大家一個很是簡單的PHP腳本,
,來創建一個鏈接到APNS併發送一個推送通知到您所指定的設備。你能夠直接在mac電腦上運行這個腳本
下載這些SimplePush代碼並解壓縮,你須要在simplepush.php作些改變。
//把你的設備標識寫在這裏(沒有空格): $deviceToken = '0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78'; //密碼放在這裏 $passphrase = 'pushchat'; // 把你的推送消息放在這裏: $message = 'My first push notification!';
你須要從app中拷貝device token到$deviceToken變量。肯定刪掉了空格以及分隔符。它應該是64位的十六進制字符。把你私鑰密碼短語放到$passphrase變量,以及你想發送的信息放到$message中。
拷貝你的ck.pem 文件到SimplePush目錄,記住,這個ck.pem文件同時包含你的證書和私鑰。
而後打開一個終端並鍵入:
若是一切順利,腳本應該會顯示:
Connected to APNS
Message successfully delivered
注意, 當應用程序是開着的你不會看到任何東西。消息傳過來了,可是咱們在app中沒有作任何處理消息的方法。
若是顯示一些錯誤信息,simplepush.php腳本退出,檢查你是否正確製做PEM文件,
如今,腳本究竟作了什麼並不重要。在這個系列的第二部分,咱們會創建一個真正的推送服務器,到那時候咱們會就此作更多的說明。
此時,你已經成功創建了一個app來接收推送通知,而且經過自定義的PHP代碼發送了第一條推送通知。
稍後請看教程系列的Part2。