Apple推送通知服務教程 PART-1

轉自:Apple推送通知服務教程 PART-1

clip_image001

學習怎樣爲你的iphone程序添加推送通知

這是由iOS教程組成員Matthijs Hollemans撰寫的一篇有關推送通知的教程,Matthijs Hollemans是一位有着豐富經驗的iOS開發者和設計者。

在iOS系統裏,應用程序在後臺運行的時候有很多事情都做不了(譯者注:由於沙盒限制)。應用程序只允許在這個“沙盒”內做一些操作,這樣可以減緩電池的消耗,延長電池的使用時間。

但是,假如用戶現在沒有在用你的程序,而你的程序恰好發生了一些有趣的事情,而你也想讓用戶知道,這時你該怎麼做?

例如,用戶收到了一條tweet的新消息,他們喜歡的隊伍贏得了比賽,或者晚飯已經準備好了。因爲應用現在沒有在運行,程序就接收不到這些新消息。

幸運的是,蘋果公司爲這種情況提供了一個解決辦法。你可以寫一個服務器端的組件來解決這樣的問題,而不是讓應用不斷的在後臺運作,檢查事件的發生。當一些有趣的事件發生的時候,服務器端的組件可以發送一個推送通知!

下面是推送通知可以做的三件事:

·顯示一條短信息

·播放一個簡短的提示聲音

·在程序的圖標上設置推送消息數量

你可以根據需要,隨意組合以上三項功能;例如,你可以播放簡短的提示聲音和設置應用圖標上推送消息的未讀數量,但不顯示消息。

在這兩部分的系列教程裏,你將通過創建一個簡單使用APNS(蘋果的推送通知)的app,來實現推送通知。

首先,在第一部分教程裏面,你將學習怎麼設置應用程序,來接受推送通知和一條測試消息。

這篇教程是爲中高級iOS開發者寫的。如果你只是一個iOS開發的初學者,應該先學習這個網站的其他教程。所以,對於初學者,強力推薦先學習下面的兩篇教程:

·如何爲iOS應用編寫一個簡單PHP/MySQL服務程序

·如何在ios應用裏面使用web service

閒話少說,讓我們把完成它!

簡要概述

想讓應用程序的推送功能正常工作,你需要相當多的努力,這個過程非常繁瑣。以下是這個過程的概述圖:

clip_image002

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”接受。

關於推送通知常見的錯誤

clip_image003

推送通知是不可靠的

推送通知是不可靠的!即使APNS(Apple Push Notification Service蘋果推送通知服務)服務器接受了推送通知,仍然無法保證該通知最終會被送達。

就你的服務器而言,推送通知會被髮出並且遺忘掉;當你將通知發送到APNS後,沒有辦法查出它所處的狀態。通知送達的時間也從幾秒到半小時不等。

同樣,用戶的iPhone不是所有時間都可以收到推送通知。比如,因爲指定的端口被封,手機處於一個不允許和APNS連接的WIFI網絡。或者手機已經關機了。

APNS將會在手機連接到可用網絡後下發從該機器收到的最後一條通知,但是隻會嘗試有限的時間。一旦發送超時,此條通知就會永遠丟失!

clip_image004

After looking at the APNS Server Bill

推送通知會使開銷很大!如果你掌控了需要推送的內容,在你的應用中加入推送功能相當容易和廉價,但是當你有好多用戶和數據需要輪詢的時候,這個功能就會使得服務器開銷龐大(譯者注:不一定指價格,包括是資源消耗)。

比如,你打算在自己的RSS訂閱更新的時候通知用戶,這樣做沒問題。因爲你控制着RSS訂閱,並且知道它何時發生變化——當你更新網站內容時——於是你的服務器可以在合適的時候發出通知。

但是如果你的應用是一款RSS閱讀器,允許用戶添加自定義的鏈接呢?這種情況下,你需要構建一些機制去檢測那些訂閱的更新。

實際上,這意味着你的服務器爲了檢查那些訂閱的變化,需要不停的輪詢它們。如果你擁有很多用戶,你可能不得不安裝一堆新服務器去處理這些工作和滿足帶寬需求。對於這類應用,推送會變得異常昂貴,可能不值得去做。

好了,理論上足夠了。下面到時間來學習如何使用推送了。在我們投入到美好的事物——編程!之前——有一些無聊的搭建環境的工作需要在iOS Provisioning Portal上完成,所以讓我們儘快完成它。

Provisioning Profiles和證書,天哪!

clip_image005

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…

clip_image006

如果菜單中沒有“Request a Certificate from a Certificate Authority with key”選項,就先去下載安裝WWDR Intermediate Certificate。並且確認Keychain Access窗口裏沒有私鑰被選中。

現在,你應該會看到下面的窗口:

clip_image007

在裏面輸入你的郵件地址,聽有人推薦說最好使用和註冊IOS開發者證號同樣的郵件地址,但看起來任何郵件地址都可以。在Common Name中輸入“PushChat”。你可以輸入任何字符串,但最好是有意義的。這會使你以後容易查找這個私鑰。

選擇Saved to disk選項,點擊Continue。將文件保存爲“PushChat.certSigningRequest”。

如果你切換到Keychain Access軟件的Keys標籤,你將會看到一個新的私鑰出現在你的鑰匙串裏。右鍵點擊它,選擇Export。

clip_image008

將私鑰保存爲“PushChatKey.p12”,輸入一個密碼短語。

爲了教程的方便,我用了密碼短語“pushchat”來保護這個p12文件,但是你應該選擇一些更不容易被猜出的。記住,私鑰是要保密的。另外,一定要選擇你能記住的密碼短語,否則以後就無法使用這個密鑰了。


一個非常簡單的程序

目前還沒有激動人心的地方,但是前面的那些準備工作是必須的。我將會詳細介紹如何生成證書,因爲它不是你每天都要做的,但是沒有證書推送就不能工作。

因爲可以連接到沙盒服務器,所以證明我們的證書是有效的。讓我們來測試一下,是不是真的能推送一些消息!

點擊Xcode然後選擇File,創建一個新的Project。選擇View-based Application模板,然後下一步

clip_image009

在文本框填入下列值:

· 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

當應用程序啓動了推送通知,它會顯示一個消息通知用戶,它想推送通知。

clip_image010

這個app推送請求只出現一次。如果用戶選“確定”,那麼我們的推送通知就全設置好了。

然而,如果他們選擇“不允許”,那麼我們的應用程序將不會接收到推送通知。用戶可以在手機設置裏改變他們的決定。

clip_image011

你可以在setting -> Notifications裏面找到你的應用程序,用戶可以在這裏啓用或禁用

應用程序的通知,包括標記、聲音和警報。

clip_image012

你的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文件同時包含你的證書和私鑰。

然後打開一個終端並鍵入:

$ php simplepush.php

如果一切順利,腳本應該會顯示:

Connected to APNS

Message successfully delivered

幾秒鐘內,你應該會收到你的第一個推送通知:

clip_image013

注意, 當應用程序是開着的你不會看到任何東西。消息傳過來了,但是我們在app中沒有做任何處理消息的方法。

關閉應用程序,然後再試一次。

如果顯示一些錯誤信息,simplepush.php腳本退出,檢查你是否正確製作PEM文件,

並且你能正確的連接到沙盒服務器 (見上文)。

現在,腳本究竟做了什麼並不重要。在這個系列的第二部分,我們會建立一個真正的推送服務器,到那時候我們會就此做更多的說明。

接下來?

此時,你已經成功建立了一個app來接收推送通知,並且通過自定義的PHP代碼發送了第一條推送通知

稍後請看教程系列的Part2


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章