苹果消息推送服务教程:第一部分(共2部分)(蔷薇科苹果属植物)
這篇文章還可以在這里找到英語
Learn how to add Push Notifications into your iPhone app!
這是iOS教程團隊的Matthijs Hollemans編寫的一篇教程, Matthijs Hollemans是一個經驗豐富的iOS開發者和設計師。
 在iOS系統中,在后臺運行的程序能夠進行的操作是非常有限的。這種限制是為了節省手機電池。
 但是,如果你需要在用戶沒有使用你的程序的情況下給他們推送消息該怎么辦呢?
打個比方,用戶收到了一個來自推特的信息,他喜歡的球隊在比賽中取勝,或者他的晚飯準備好了。因為現在用戶并沒有在使用我們的程序,程序本身無法聽取這些事件。
幸運的是,蘋果系統對此已有了解決辦法。你并不需要讓程序不停地聽取事件或者在后臺跑運算。你只需要編寫一個服務器組件來完成這個任務。
在一個特定的事件發生時,那個服務器的組件就可以給我們的程序發一個推送信息!推送信息可以做如下三件事:
- 顯示一條信息
- 播放一小段提示音樂
- 在程序的小圖標邊上放置一個數量標志
你可以隨意組合這些選項;比如你可以播放提示音并放置數量標志,而不顯示任何信息。
在這個有兩部分的教程中,你會用蘋果推送服務器(APNS)來完成一個有消息推送功能的簡單的程序。
在第一部分,你會學習如何接收推送的信息。
這篇教程針對的是中級或者高級的iOS開發者。如果你對iOS還處于入門階段,你應該先看看這個網站上一些初級教程. 并且,我也建議你可以先看看下面這兩篇教程(或者有類似的經驗):
- 如何為iOS程序寫簡單的PHP/MySQL網絡服務
- 如何在iOS程序中使用網絡服務
那就讓我們開始吧!
文章概略
為你的app加入信息推送是需要付出很多努力的。這個任務有很多個部分。下面是一個概要:
- 程序啟用消息推送功能。用戶必須確認他希望接受這些推送信息。
- 那個程序接收一個“設備標記碼”。你可以把這個設備標記碼理解為推送信息的地址。
- 那個程序將這個設備標記碼發送到服務器。
- 每當任何關于你的程序的事件發生時,那個服務器會將信息發送到蘋果的推送信息服務(APNS)。
- APNS 將這個信息再推送到用戶的設備上
用戶的設備收到這個信息時,會有提示窗口,播放提示音或者更新app的數量標志。用戶可以在提示窗口中直接開啟這個app。我們的app從這里接過推送信息的內容并能自定義處理這個信息的邏輯。
有人會問,iOS4中已經有了本地提示以及多重任務執行,那推送信息提示還有用嗎?答案:“當然啦”!
本地提示僅能用于定時的事件。無限制的后臺運算也僅限用于網絡通話,導航和背景音樂類的app。如果在程序已經進入后臺運行還想給用戶信息提示,那我們仍然需要使用推送信息提示。
在這個教程中,我會詳細解釋推送信息提示是怎么實現的,以及如何在你的app中使用它。需要學的東西很多,讓我們現在開始吧!
推送信息提示準備工作
在你的app中加入推送信息提示,你需要:
一臺 iPhone 或者 iPad。你需要真實的設備因為推送信息提示在模擬器中不能用。
你必須是注冊的iOS開發者。每個要加入推送信息的app的需要一個新的App ID,provisioning profile 和SSL證書。你可以在iOS Provisioning Portal來完成這些所需操作。
如果你想跟著這個教程中的例子,那你就需要創建新的provisioning profile和SSL 證書;你不能用我的。因為獲取正確的證書很重要,我會一步步解釋如何獲取這個證書。
一個連接到網上的服務器。推送信息是由這個服務器發送出來的。開發期間你可以用你的蘋果電腦作為服務器(我們在這個教程中就會這樣做),但是在app上線后,你至少需要一個VPS(虛擬私人服務器)。
一個簡單的共享的服務器賬號是不夠的。你需要能夠在服務器上跑后臺線程,安裝SSL證書以及對外在特定端口建立TLS鏈接。
大多數共享服務器的提供者是不會讓你這么做的。所以,我強烈建議你用Linode類型的服務器.
解析消息推送服務/h2>
你的服務器負責創建被推送的消息,所以我們應該來了解一下這個服務器是怎么做到的。
一個推送消息會包含設備標記碼,信息負載和一些其他的字節。那個信息負載就是我們要發到設備上的推送消息。
你的服務器提供的這個信息負載應該是JSON字典的格式。一個簡單的推送信息負載應該是這樣的:
{
	"aps":
	{
		"alert": "Hello, world!",
		"sound": "default"
	}
}
如果你不了解JSON,你只需要知道用“{}”符號分割出來的一個代碼塊代表了一個鍵與值對應的字典(和NSDictionary相似)。
我們的信息就是這樣的一個字典。這個字典里至少要有一個物件,“aps”。在這里,“aps”本身又是一個字典。“aps”包含了“alert”和“sound”兩個鍵。當設備收到這個消息時,程序應該顯示一個彈出消息:“Hello,world!”并且發出標準的提示音。
你還可以在“aps”字典中加入其他物件來設置那個消息。比如:
{
	"aps":
	{
		"alert":
		{
			"action-loc-key": "Open",
			"body": "Hello, world!"
		},
		"badge": 2
	}
}
注意“alert”本身也變成了一個字典。彈出信息欄的查看按鈕的標簽會變換成“action-lock-key”的值。“badge”鍵所對應的數字值會成為程序圖標的數量標記。這個消息不會發出提示音。
這個JSON格式的信息負載還有很多可以設置的選項。你可以改變提示音的聲音,提供翻譯過的標簽,你也可以加入自定義的鍵值對。如果有興趣深入了解,你可以看看蘋果公司提供的本地和推送信息編程指南.
推送信息應該很簡潔;那個信息負載不應該超過256個字節。這樣一般有足夠的空間傳送一個SMS信息或者一個推特消息。正確的服務器不會浪費寶貴的負載空間了傳送換行符和空格,所以你的服務其應該發送這樣的信息:
{"aps":{"alert":"Hello, world!","sound":"default"}}
這個對于人來說比較難讀懂,但是卻更節省空間。蘋果APNS不會接受超過256個字節的推送消息。
推送消息的易錯點
推送消息不可靠!
太不可靠了!就算在APNS服務器接收了信息的情況下,推送消息也不一定會成功地傳到用戶設備上。
你的服務器在發射推送消息到APNS后,沒有任何辦法可以獲取消息的狀態。消息實際被推送的時間也不一定,可能幾秒鐘,也可能要半個小時。
并且,用戶的iPhone并不是隨時都能接收推送信息。他們可能在一個無法接收蘋果推送服務的無線網絡中,原因可能是相應的網絡端口被封閉了;或者用戶的手機關機了。
蘋果推送服務會在手機重新上線后試著重試沒有傳遞的信息,但是這是有時限的。時限一過,我們就永遠失去那個信息提示了!
 <img alt="蘋果消息推送服務教程:第一部分(共2部分)" src="http://cdn1.raywenderlich.com/wp-content/uploads/2011/05/RageFace-250x197.jpg" title="在看到蘋果推送服務的賬單后
<img onload="Wpfcll.r(this,true);" src="https://javaforall.cn/wp-content/plugins/wp-fastest-cache-premium/pro/images/blank.gif" class="j-lazy" alt="蘋果消息推送服務教程:第一部分(共2部分)" data-wpfc-original-src="http://javaforall.cn/wp-content/uploads/2020/11/2020110816061913.jpg" data-original="http://cdn1.raywenderlich.com/wp-content/uploads/2011/05/RageFace-250x197.jpg" title="在看到蘋果推送服務的賬單后
” alt=”在看到蘋果推送服務的賬單后”> 
在看到蘋果推送服務的賬單后
好貴啊!如果有很多用戶,或者所推送的信息需要從其他地方不斷獲取,那這個服務的費用可能會很高。
 打個比方,如果你控制了RSS源。因為你會清楚知道什么時候會有新的RSS,你可以輕松直接地在適當的時候給用戶推送信息。
 但是,如果你的程序允許用戶輸入自定義的RSS網址怎么辦?在這種情況下你需要有自己的一套方案來探測是否有心的RSS信息。
事實上,你的服務器需要不停地訪問這些地址來探測新的RSS信息。如果你有很多用戶,那你就需要不斷增加新的服務器來探測和發送信息。這很快就會變得非常昂貴。
理論問題討論完了,那我們就開始實踐吧。 但是在做有趣的事情–編程,之前, 我們還需要在iOS開發者門戶網站上完成一些無聊的設置。
Provisioning Profiles以及各類證書
蘋果推送服務需要一個證書!
為了使你的程序能使用推送服務,我們需要建立一個特別用來進行這個服務的provisioning profile。另外,你的服務器還需要通過SSL證書來和蘋果的推送服務器建立聯系。
provisioning profile和SSL證書是一一對應的,并且只有在有一個有效的App ID的情況下才能用。這是為了保證你的服務器只能將推送信息發到這一個特定的程序中,而不能發到其他任何程序。
值得注意的是,一個程序在開發時和發布時需要用不同的provisioning profile。同時也有兩種服務器證書:
- 開發時. 如果你的程序是在Debug模式下運行,并且使用的是開發階段的provisioning profile(Code Signing Identity屬性的值是”iPhone Developer”),那你的服務器必須使用開發階段的證書。
- 生產時. 程序如果已經在蘋果商店上發布(Code Signing Identity屬性的值是”iPhone Distribution”),那服務器必須使用生產階段的證書。如果這兩個被弄混了,推送的提示信息就無法到達你的程序。
在這個叫教程里,我們將只會使用開發時的profile和證書。
生成Certificate Signing Request(證書申請)
還記得你如何在iOS開發者網站上注冊iOS開發計劃并獲取開發證書的嗎?我們下面要做的和那個類似。但我還是建議你一步一步跟著我來完成這個操作。因為大多數問題都出在證書上。
電子證書都是基于公共和私有密鑰加密的。你并不需要知道這個加密的過程,但你需要知道那個證書必須和一個私有密鑰一起用才會有效。
那個證書是這組密鑰的公共部分。所以把這部分隨便給別人是沒有問題的,在你用SSL來通訊時就需要這么做。但是那個私有密鑰卻需要保密。這個秘密不能讓任何別人知道。如果你沒有這個密鑰,那證書就失效了。
在你申請一個電子證書時,你需要提交一份Certificate Signing Request(證書申請),縮寫為CSR。在你生成CSR時,會生成一個新的私有密鑰并被放到你電腦的keychain中。然后你把這個CSR發到一個證書的認證網站(在我們的情況下,這個網站就是蘋果的開發者門戶網站)。這個網站會用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(保存到硬盤)邊上打鉤。將它保存為”PushChat.certSigningRequest”。
如果你現在來到Keychain Access的Keys部分,你應該看到一個新的,你剛剛生成的私有密鑰。右鍵點擊并將它匯出。
將匯出文件命名為“PushChatKey.p12”然后輸入一個加密碼。
為了方便,我的加密碼就是“pushchat”。但為了更好地保護這個p12文件,你應該選擇一些更難猜到的加密碼。私有密鑰必須是秘密的,不是嗎?但是你一定要記得住這個加密碼,否則私有密鑰還是不能用。
創建App ID和獲取SSL證書
登陸iOS置備門戶網站.
首先,我們需要創建一個新的App ID。每一個用推送信息服務的app都需要一個特有的ID,因為只有這樣,被推送的信息提示才能被發送到正確的程序上。(在這里,你不能使用通配符ID。)
在邊上的目錄欄中選擇“App IDs”,然后點擊“New App ID”按鈕。
我填寫內容如下:
- Description: PushChat
- Bundle Seed ID: Generate New
- Bundle Identifier: com.hollance.PushChat
你最好是選擇一個你自己的Bundle Identifier,而不是用我的,例如“com.你的網站.PushChat”。你之后在Xcode中還要使用這個Bundle Identifier。
很快,我們會生成一個SSL證書。你的服務器就是用這個證書來和蘋果的推送服務器建立安全連接。這個證書和你的App ID綁定在一起,這樣你的服務器就只能給這一個app發送推送信息提示了。
在你創建好App ID后,你應該看到類似如下的列表:
在“Apple Push Notification service”(蘋果推送信息服務)一欄里,有兩個橘黃色的標志分別寫著“Configurable for Development”(開發設置)和“Configurable for Production”(發布生產設置)。這意味著我們的App ID已經可以用來進行推送了,只是還需要我們做相應的設置。點擊那個寫著“Configure”的鏈接來打開設置App ID的界面。
在“Enable for Apple Push Notification service”(啟用蘋果推送服務)旁打鉤然后點擊對應“Development Push SSL Certificate”的Configure按鈕。蘋果推送服務SSL證書助手界面就出現了:
它首先要你生成一個證書簽署請求。我們已經完成這一步了。點擊Continue。在下一步你需要上傳已經生成的證書簽署請求(CSR)。選擇那個CSR文件,然后點擊Generate。
生成SSL證書需要幾分鐘時間,完成后點擊Continue。
點擊“Download”來下載證書 – 名字應該叫 “aps_developer_identity.cer”. 點擊“Done”來關閉助手界面并回到設置App ID的界面。
如你所見,我們現在有一個有效的證書了,可以開始給App推送證書了。如果需要,你可以在剛才的地方重新下載證書。開發證書的有效期是3個月。
當你的App準備可以正式使用時,重復上述步驟來獲取生產時用的證書。步驟是一樣的。
注意:生產時用的證書有效期是1年。但你需要提前更新它以確保你的App的推送服務不會中斷。
創建PEM文件
現在我們總共有三個文件:
- CSR
- 私有密鑰(PushChatKey.p12)
- SSL證書(aps_developer_identity.cer)
將這三個文件好好保存起來。你可以選擇不再用那個CSR文件了。但是在你更新證書時,你可以使用同一個CSR或者獲取一個新的。如果你獲取新的CSR,你同時會生成一個新的私有密鑰。如果使用同一個CSR,那就只有SSL證書需要改變了。
我們需要將證書和私有密鑰轉換成另外一個更方便的格式。我們在服務器的推送部分會用PHP來寫,所以我們現在可以把證書和私有密鑰合并成一個PEM格式的文件。
PEM文件是怎么運作的并不重要(說實話我也不知道),但是這樣我們能更容易地在PHP里使用這個證書。如果你準備用其他語言來寫這個服務器部分,那下面的步驟可能會不配套。
我們將使用命令行OpengSSL的工具來完成這項任務。打開一個Terminal并輸入以下指令。
“cd”到你下載證書,密鑰文件的文件夾,對于我是桌面文件夾:
$ cd /Users/matthijs/Desktop
將那個.cer文件轉換成.pem文件:
$ openssl x509 -in aps_developer_identity.cer -inform der 
    -out PushChatCert.pem
將那個密鑰.p12文件轉換成.pem文件:
$ openssl pkcs12 -nocerts -out PushChatKey.pem -in PushChatKey.p12 Enter Import Password: <輸入你導出密鑰時用的那個密碼> MAC verified OK Enter PEM pass phrase: <輸入一個新的密碼> Verifying - Enter PEM pass phrase: <重復密碼>
你首先需要輸入.p12文件的密碼,這樣openssl才能讀取這個文件。然后你需要你個新的密碼來對pem文件進行加密。在這個教程中我用的還是“pushchat”。但你自己應該選擇一個更加保險的密碼。
注意:如果你不輸入PEM的密碼,openssl不會給你任何的錯誤信息。但是生成的.pem文件里就不會有那個密鑰。
最后,將那個證書和密鑰合并為一個文件:
$ cat PushChatCert.pem PushChatKey.pem > ck.pem
我們應該測試一下這個證書是否能用。執行如下指令:
$ telnet gateway.sandbox.push.apple.com 2195 Trying 17.172.232.226... Connected to gateway.sandbox.push-apple.com.akadns.net. Escape character is '^]'.
我們試著與APNS服務器建立一個一般的,沒有加密的連接。如果你看到類似上面的回復,那說明你的Mac能連上APNS。按Ctrl+C切斷連接。如果你得到一個錯誤信息,那你應該確保你的防火墻允許對外2195端口的連接。
讓我們再次試著連接。這次,我們會使用那個SSL證書和密鑰來建立一個加密連接:
$ openssl s_client -connect gateway.sandbox.push.apple.com:2195 
    -cert PushChatCert.pem -key PushChatKey.pem
Enter pass phrase for PushChatKey.pem: 
你應該看到一大竄回復內容。那是openssl的運行信息。
如果連接成功建立,你應該可以鍵入幾個字符,然后當你點回車時,服務器就會和你斷開連接。如果建立連接過程出現問題,openssl會給出錯誤信息,但你可能需要在那一大竄信息中找出錯誤信息。
值得注意的是,APNS其實有兩個不同的服務器:那個沙盒服務器使用來測試的。還有一個正式的服務器是在你的程序投入生產后使用的。我們上面用的是測試用的服務器。因為我們的證書是開發時才能用的。
生成Provisioning Profile
 我們還需要用Provisioning門戶網頁來生成一個新的Provisioning Profile。在左邊的目錄欄中點擊“Provisioning”,選擇“Development”來生成一個新的profile。
 
填寫表格如下:
- Profile Name: PushChat Development
- Certificates: 在你的證書旁打鉤
- App ID: PushChat
- Devices: 選擇你的設備
我們需要一個新的profile因為每個有推送信息的app都需要和它App ID相對應的一個profile。
點擊Submit,你的profile就會被生成。那個profile的狀態一開始會是“Pending”。刷新頁面直到它的狀態變成“Active”,這時你就可以下載那個文件了(給它取名為PushChat_Development.mobileprovision)。
雙擊那個文件或者將這個文件拖到Xcode的圖標上,這樣就能將這個profile添加到Xcode中了。
在你將程序投入生產時,你需要重復上述步驟來生成Ad Hoc或者distribution profile。
一個非常基礎的APP
到現在為止我們做的準備工作都比較枯燥,但卻是必要的。我們詳細的學習了生成各種證書的過程因為我們不會經常坐這件事,但是推送信息沒有這些就無法運作。
通過連接到沙盒服務器,我們確認了證書是可用的。現在我們要測試一下我們是否確實可以推送提示信息!
啟動Xcode并建立一個新的項目。 選擇View-based Application作為這個項目的模版然后點擊進入下一步。
我是這樣填寫各個空格的:
- Product Name: PushChat
- Company Identifier: com.hollance
- Device Family: iPhone
那個Product Name(產品名字)和Company Identifier(公司代碼)合在一起就是Bundle ID。我的是“com.hollance.PushChat”。 你應該選擇和你在蘋果的Provisioning Portal上注冊的App ID相對應的產品名字和公司代碼(com.yourname.PushChat)。
完成創建項目并打開PushChatAppDelegate.m文件。將didFinishLaunchingWithOptions改為如下:
|  | 
我們調用registerForRemoteNotificationTypes方法來告訴OS我們的程序想接收推送信息。
編譯并運行你的程序。你應該在真正的蘋果設備上運行因為模擬器不支持推送信息提示。Xcode應該會自動選擇那個新的provisioning profile。如果你得到一個關于“code sign”的錯誤,那你需要確保已經選擇了正確的profile。 你可以在“build settings”中的“Code Sign”設置部分對其修改。
當啟動你的程序時,系統應該會彈出一個選擇菜單來詢問用戶是否允許當前程序推送提示信息。
你的程序只會向用戶詢問一次然后記住用戶的選擇。用戶只有選擇“OK”之后你的程序才能接收推送提示信息。用戶也可以在iPhone系統設置菜單中更改推送信息的設置。
你app的名稱會出現在手機的提示設置界面里。用戶可以在這里設置是否允許你的app推送信息提示,顯示數量圖標以及發出提示音。
你的app也可以通過如下的代碼來探測用戶啟用了哪一種提示方式:
|  | 
要讓我們的app開始接收推送提示,我們還需要將下面的代碼加入PushChatAppDelegate.m文件中:
|  | 
當你的app注冊遠程推送提示時,它會獲取一個設備代碼(device toke)。這是一個32字節的獨特數字來辨別用戶的設備。你可以把這個代碼看做是用戶設備的地址。APNS用這個地址來推送信息提示。
在你用來測試的蘋果設備上運行你的app。你應該在Xcode的控制臺窗口中看到:
My token is: <740f4707 bebcf74f 9b7c25d4 8e335894 5f6aa01d a5ddb387 462c7eaf 61bb78ad>
那個代碼是一個NSDatat對象,擁有某種二進制數據結構。我們不應該對它進行任何修改。我們只用知道它有32個字節,可以用64個十六進制的字符表示。我們會直接用這種表示方式(去掉那括弧和中間的空格)。
如果你在模擬器里運行你的程序,didFailToRegisterForRemoteNotificationsWithError:方法應該會被調用因為模擬器不支持推送信息提示。
我們的app就暫時寫完了。但要真的開始推送信息,我們還需要完成最后的一步!
推送第一個信息提示
我曾說過,你需要有一個服務器來把信息推送到你的app上。但為了測試,我們還不需要一個服務器。你可以用下面這個簡單的PHP腳本來和APNS建立連接并將信息推送到指定的設備上。你可以直接在你的Mac上運行這個腳本。
下載這個叫“SimplePush”代碼包并解壓縮. 你需要對simplepush.php文件進行如下修改.
|  | 
你應該把設備代碼從app里拷貝粘貼到$deviceToken變量。請確保你去掉空格和括弧。把$passphrase的值設為你密鑰的密碼, $message的值設為你要推送的信息字符串。
把你的ck.pem文件拷貝到SimplePush文件夾中。記住,ck.pem包含你的證書和密鑰。
打開終端并打入:
$ php simplepush.php
如果一切順利,那個腳本應該回應:
Connected to APNS Message successfully delivered
然后幾秒之后,你應該收到app的第一個推送信息提示:
注意,如果你的app是開著的,你就看不到推送的信息。這是因為我們還沒有寫代碼在app里接收推送的信息。你應該關掉app然后重試。
如果simplepush.php腳本因錯誤退出,那你因該確保你的PEM文件是正確生成的,并且確保你可以連接到蘋果的沙盒服務器(請看上面的詳細步驟)。
我們并不用急著知道這個腳本到底做了什么,因為這是這個教程的下一部分的內容。在下一部分,我們將學習如何編寫一個真正的推送服務器。
下一步做什么?
到現在為止,你的app已經可以接收推送信息了,你也成功地用PHP代碼推送了第一個信息!
下一步是看看這個教程的第2部分。我們會學習編寫一個簡單的短信app叫做PushChat,并運用推送的方式來傳遞信息。我們還會學習如何完成一個完整的服務器API,在后臺不斷地推送提示信息!
from:http://www.raywenderlich.com/zh-hans/24732/
總結
以上是生活随笔為你收集整理的苹果消息推送服务教程:第一部分(共2部分)(蔷薇科苹果属植物)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Linux中comm命令怎么用
- 下一篇: 怎么将xdf文件转换为word文档
