標籤:
iOS 推送基礎知識
Apple 使用公用密鑰數位憑證對來自 iOS 應用程式的推送請求進行身分識別驗證,所以您首先需要建立身分識別驗證密鑰,並向 Apple 註冊它們。我將在下一節中花相當長的篇幅來直接介紹這一點。
接下來,需要確定安裝該應用程式並選擇接收該應用程式的推播通知的每台裝置。工作順序如下:
- iOS 應用程式中的一個警告對話方塊會請求使用者的許可,以接收推播通知。
- 如果使用者授予許可權,iOS 應用程式會聯絡 Apple Push Notification 服務 (APNs) 獲得一個 ID 字串,以惟一地標識在此裝置上安裝的這個應用程式。(您可以將 ID 看作類似於傳統訊息情境中的收件者電話號碼)。
- iOS 應用程式將 ID 上傳到您的伺服器應用程式。
- 當伺服器應用程式需要發送推送訊息時,它對 Apple 的推送伺服器進行身分識別驗證,然後使用從步驟 2 和 3 中獲得的 ID 指定訊息的收件者。
- 如果收件者裝置線上,它接收並處理訊息。如果裝置離線,那麼訊息將會排隊,然後當裝置下一次線上時交付。
APNs 也使您的伺服器應用程式可以定期驗證您所儲存的應用程式識別碼 列表。這使您有機會刪除那些在後來刪除應用程式或修改其推送選擇狀態的使用者和 ID。
這聽起來好像要涉及很多工作,的確是這樣的。這就是為什麼會存在像 Urban Airship 的服務,收費代理訊息(見側欄)。
在說明如何註冊應用程式之後,我將進入開發 iOS 推播通知應用程式的細節,並利用開源 Java 庫及其伺服器組件的協助。
您自己伺服器的一個替代方案:Urban Airship
Urban Airship 是一種服務,讓您無需運行自己的伺服器就可以推送訊息(參見 參考資料)。將私密金鑰上傳到 Urban Airship 並使用其基於 Web 的訊息控制台,以向使用者推送訊息。Urban Airship 提供了一個 iOS SDK,使您的應用程式可以很容易地將每個已安裝的裝置註冊到其伺服器,那麼這些裝置就會出現在訊息控制台。雖然 Urban Airship 可以簡化您的工作,但是成本昂貴,並且您還需要瞭解基本的推播通知概念。
APNs 也使您的伺服器應用程式可以定期驗證您所儲存的應用程式識別碼 列表。這使您有機會刪除那些在後來刪除應用程式或修改其推送選擇狀態的使用者和 ID。
這聽起來好像要涉及很多工作,的確是這樣的。這就是為什麼會存在像 Urban Airship 的服務,收費代理訊息(見側欄)。
在說明如何註冊應用程式之後,我將進入開發 iOS 推播通知應用程式的細節,並利用開源 Java 庫及其伺服器組件的協助。
註冊應用程式
要註冊您的應用程式使用推播通知,您首先需要建立一對私人/公用密鑰,對 APNs 伺服器的 API 呼叫進行身分識別驗證。在 Mac 上,您可以通過使用 KeyChain Access 應用程式完成該操作。選擇 KeyChain Access > Certificate Assistant > Request a Certificate from a Certificate Authority,以建立一個認證簽章要求檔案。該請求檔案包含產生的公用金鑰組,而相應的私密金鑰則儲存在 KeyChain Access 中。請務必在對話方塊中選擇 Saved to disk 選項, 1 所示:
圖 1. 在 Mac 上從 KeyChain Access 程式產生一個金鑰組和簽章要求
接下來,登入到 Apple 的應用程式配置門戶(參見 參考資料),並上傳您的簽章要求檔案,它將被關聯到相應的配置概要檔案。大多數應用程式都有一個供測試人員使用的開發配置概要檔案,以及一個用於 App Store 的生產概要檔案,所以您將最有可能產生和上傳兩個簽章要求。在您上傳簽章要求後,該門戶產生一個數位憑證,供您下載。該認證包含公開金鑰,現在 APNs 識別為與您應用程式關聯。圖 2 顯示了一個樣本:
圖 2. 來自 Apple 的數位憑證
下載數位憑證,並雙擊要下載的檔案。現在,KeyChain Access 自動匯入數位憑證,並將它與您在建立簽章要求時產生的私密金鑰關聯起來。圖 3 顯示了在 KeyChain Access 中的公開金鑰和私密金鑰對:
圖 3. 在 KeyChain Access 中的公開金鑰和私密金鑰對
現在,將金鑰組匯出為一個檔案,所使用的格式稱為 Personal Information Exchange (p12)。當您建立 p12 檔案時,KeyChain Access 要求您指定一個密碼來保護私密金鑰。如果您想使用一個空密碼,也沒有問題。
從這時起,所有對 APNs 推送伺服器的 API 請求都必須由 p12 檔案中??的私密金鑰進行加密,然後由該 p12 檔案中的公開金鑰進行數位簽章,以驗證 API 呼叫是真的由您產生的。稍後在本文中描述如何與 APNs 伺服器互動時,我將示範如何使用密鑰。(如果您使用 Urban Airship,它會要求您將 p12 檔案以及任何密碼上傳到其伺服器,以便它能夠以您的名義發送推送訊息。)
現在,您已經有了推送認證,您必須重新下載並重新安裝您的應用程式配置概要檔案,因為概要檔案現在已被更新為可以支援應用程式的推播通知。
請求和儲存裝置令牌
您的 iOS 應用程式需要請求使用者許可,在它所安裝的裝置上接收推播通知。通常情況下,您可以通過一個簡單的 API 呼叫在應用程式代理程式中實現這一點,如清單 1 所示:
清單 1. 請求使用者許可
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
如果使用者授予許可,應用程式會自動聯絡 APNs 伺服器擷取裝置令牌。令牌使 APNs 可以將該特定裝置上所安裝的這個特定應用程式識別為一個訊息目的地。這個過程是自動的,並且在後台執行。您不需要為它編寫任何代碼。
在 APNs 伺服器響應後,應用程式代理程式中的 didRegisterForRemoteNotificationsWithDeviceToken 方法被調用,並將裝置令牌作為一個調用參數傳遞進來。您必須儲存裝置令牌並將它上傳到自己的推播通知伺服器,如清單 2 所示:
清單 2. 接收一個 ID 並將它上傳到伺服器
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken { NSString *tokenStr = [deviceToken description]; NSString *pushToken = [[[[tokenStr stringByReplacingOccurrencesOfString:@"<" withString:@""] stringByReplacingOccurrencesOfString:@">" withString:@""] stringByReplacingOccurrencesOfString:@" " withString:@""] retain]; // Save the token to server NSString *urlStr = [NSString stringWithFormat:@"https://%@/push_token", RINGFULDOMAIN]; NSURL *url = [NSURL URLWithString:urlStr]; NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url]; [req setHTTPMethod:@"POST"]; [req setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-type"]; NSMutableData *postBody = [NSMutableData data]; [postBody appendData:[[NSString stringWithFormat:@"username=%@", username] dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[[NSString stringWithFormat:@"&token=%@", pushToken] dataUsingEncoding:NSUTF8StringEncoding]]; [req setHTTPBody:postBody]; [[NSURLConnection alloc] initWithRequest:req delegate:nil];}
在理想情況下,您將令牌與一些標記使用者的資訊(如在您的系統中的個人使用者名稱)相關聯,使您的伺服器知道稍後要將訊息發送給誰。(您可以將它想像為類似於將電話號碼與個人姓名相關聯。)如果您沒有將令牌與自己的使用者標識資訊關聯,您仍然可以將訊息發送到這些裝置,但您不能為每個使用者自訂訊息,因為您所擁有的是一個目標裝置的字母令牌字串。
伺服器應該將令牌及其相關的標識資訊儲存在資料庫中。在大多數應用程式中,它被儲存在使用者設定檔資料庫中。
發送一個推送訊息
要發送一個推送訊息,您的伺服器:
- 尋找即將發送訊息的目標應用程式 ID 列表
- 根據收件者的使用者設定檔為每個收件者個人化訊息
- 聯絡 APNs Message Service器
APNs 伺服器的 Web 服務 API 很複雜。對 Java 開發人員來說幸運的是,開源 JavaPNS 庫可以使其使用變得更簡單。JavaPNS 和下載和文檔連結參見 參考資料。
清單 3 中的代碼顯示了如何使用 JavaPNS 庫向裝置發送類似於簡訊的訊息:
清單 3. 發送一個推送訊息
String[] devices = {"token1", "token2};List<PushedNotification> notifications = Push.alert("Hello World!", "keypair.p12", "password", false, devices);
JavaPNS 庫的主介面方法是在 Push 類中的靜態方法。APNs 允許您在訊息中嵌入各種內容。請參閱 iOS 推送訊息指南,擷取所支援的負載類型的完整清單(參見 參考資料)。Push 類為每種類型的訊息提供方便的方法,並且它將訊息的轉換為 APNs 伺服器接受的 JavaScript Object Notation (JSON) 格式。在 清單 3 中,keypair.p12 是從 KeyChain Access 匯出的 p12 檔案,password 是 p12 檔案的密碼。devices 陣列是從 iOS 應用程式接收的裝置令牌列表。所有這些裝置都將收到這個推送訊息。在參數中的 false 值指定該訊息應發送到 APNs 程式開發伺服器(沙箱),而不是其生產伺服器。(回憶一下,您通常為沙箱建立一個 p12 金鑰組,為生產伺服器建立一個不同的金鑰組。)
方法調用返回的值是一個 PushedNotification 對象的列表,您可以用它來確定推送交付的狀態,如清單 4 所示:
清單 4. 檢查推送交付的狀態
for (PushedNotification notification : notifications) { if (notification.isSuccessful()) { /* Apple accepted the notification and should deliver it */ } else { String invalidToken = notification.getDevice().getToken(); /* Add code here to remove invalidToken from your database */ }}
如果通知對象告訴您,有某個裝置令牌不再處於啟用狀態,例如,如果使用者從裝置中刪除了該應用程式,或在應用程式設定中禁用了通知,您應該從資料庫中刪除該令牌,以便您不會再向它發送訊息。
保持最新的活動裝置令牌列表的另一種方式,是讓您的伺服器應用程式定期檢查 APNs 伺服器。清單 5 顯示了如何查詢 APNs 反饋服務,使用 JavaPNS 從 APNs 沙箱接收一個無效裝置令牌的列表:
清單 5. 檢查以更新活動的裝置令牌
List<Device> inactiveDevices = Push.feedback("keypair.p12", "password", false);/* remove inactive devices from your own list of devices */
不要將資源浪費在將訊息發送到已刪除您的應用程式的裝置,或選擇不接收通知的裝置,這一點很重要。
其他考慮事項
推播通知不能在 iOS 模擬器上進行測試;您必須將應用程式部署到實際裝置上對其進行測試。因為用於對訊息進行身分識別驗證的數位憑證被捆綁到應用程式的配置概要檔案,您需要使用在開發或臨時分發應用程式中的開發認證進行測試。在應用程式通過審批並在 App Store 中提供後,您必須切換到生產認證。
此外,重要的是要理解,為大資料庫中的使用者定製和發送推送訊息是一項資源密集型工作。例如,每 5 秒遍曆一次一個百萬使用者級的資料庫,以確定 10 個當時需要收到訊息的使用者,這成本非常高。伺服器端的基礎架構需要精心的設計和規劃,以支援對大量使用者的頻繁推播通知。相反,一次向一百萬個使用者發送推送訊息會產生大量的流量,因此通過使用一個線程池可以更好地處理這一情境,而不是阻止一個單獨線程。JavaPNS 庫提供一個簡單的 API,它使用線程池,可以同時將訊息推送給大量裝置。
結束語
推送技術讓您的伺服器應用程式繞過電信電訊廠商,並直接通過 Internet 向 iOS 裝置的應用程式發送訊息。雖然實現推播通知並非小事(用戶端 SSL 憑證對 Apple 伺服器的身分識別驗證需求很複雜),但是來自 Urban Airship 和 JavaPNS 等第三方的協助可以使發送通知更加容易。SMS 和 MMS 有自己的位置,並且仍然比推送技術更可靠,但您可以通過實現推送訊息使您的 iOS 應用程式更加豐富,提供更多的功能。
iOS遠程訊息推送