googleAPNS:https://code.google.com/p/apns-php/wiki/CertificateCreation
推送證書建立:
1,登陸官網:iPhone Developer Program Portal
2,選擇APP IDs。 (or click here)
3,建立一個app id,注意不要選擇Explicit,不要選擇Wildcard。
4,繼續向下進行。直至完成建立。--->建立PUSH SSL CER(Apple Documentation: Creating the SSL Certificate and Keys)
5,生成SSL證書後,輕按兩下加入Keychain中(建立成功的話,證書下方會有私鑰)。
6,在keychain中,右擊證書,導出證書為**.p12(不要注入密碼)。
7,開啟終端,更改目錄到p12檔案所在處,用指令将PKCS12證書更改為PEM格式檔案,指令:
-
openssl pkcs12 -in **.p12 -out **.pem -nodes -clcerts
8,在背景ApnsPHP中應用PEM檔案。
APP中APNS的實作:ObjectiveC page
推送通知至某裝置,DeviceToken是依據DeviceID和APPlicationID,經由apple生成。故是唯一的(per device and per application)。
code demo: http://code.google.com/p/apns-php/source/browse/trunk/Objective-C%20Demo
----------------------------------------------------------------------------------------------------
簡述:
想讓應用程式的推送功能正常工作,你需要相當多的努力,這個過程非常繁瑣。以下是這個過程的概述圖:

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版本的即可。
1,生成證書簽名請求(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”。
2,建立 App ID
每個使用 APNs 的 iOS 應用必須有一個唯一的 App ID。在本步驟中,你将學到如何建立推送通知中要用到的App ID。
1. 登入iPhoneDeveloper Program:http://developer.apple.com/iphone/。點選頁面右邊的“ iPhone Developer Program Portal ”(圖4):
2. 首先看到的是歡迎頁面(圖5):
3. 點選左邊的“App ID”,然後點選右邊的“New App ID”按鈕(圖6):
4. 在 Description 欄輸入“PushAppID”,在“Bundle Seed ID”欄中選擇“Generate New”。在“Bundle Identifier”欄,輸入“net.learn2develop.MyPushApp”,然後點選“Submit”(圖7):
5. 現在你應該能看到所建立的 App ID 了(圖8):
配置 App
一旦建立了 App ID,你還要為推送通知對 App ID 進行一些配置。
1. 點選App ID 右邊的 Configure 連結,會看到如下選項(圖9):
勾選“Enable for Apple Push Notificationservice”,點選“Development Push SSL Certificate”右邊的“Configure”按鈕。
2. 接下來你會看到“Apple Push Notification service SSL Certificate Assistant”頁面。點選Continue(圖10):
3. 點選Choose File 按鈕,選擇前面儲存的證書請求檔案存放位址。點選 Generate(圖11):
4. 你的SSL 證書會被生成。點選 Continue(圖12):
5. 點選Download Now 按鈕,下載下傳 SSL 證書。點選 Done(圖13):
6. 下載下傳的 SSL 證書檔案名為 aps.developer.identity.cer。輕按兩下,将證書安裝到鑰匙串中(圖14)。這個證書會在你的程式中用到,它允許程式接收 APNs 發送來的推送通知。
3,建立 Provisioning Profile
接下來,需要建立 provisioning profile 以便允許應用程式安裝到真實裝置上。
1. 回到iPhone Development Program Portal,點選 Provisioning 欄,點選 New Profile 按鈕(圖15):
2. Profile Name 欄輸入 MyDevicesProfile,在 App ID 欄選擇 PushAppID。在Devices 欄,勾選所有你想激活的裝置(在 iPhone Developer Program Portal 的 Devices 頁中注冊的所有裝置)。點選 Submit(圖16)。
3. provisioning profile 會等待稽核。幾秒鐘後,它會顯示在頁面上。點選Download 按鈕下載下傳該 provisioning profile(圖17):
4. 下載下傳下來的provisioning profile 名為 MydevicesProfile.mobileprovision。
4,激活裝置:建立 provision profile 後,你可以将它安裝到真實裝置中。
--------------------------------------------------
你的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
幾秒鐘内,你應該會收到你的第一個推送通知:
注意, 當應用程式是開着的你不會看到任何東西。消息傳過來了,但是我們在app中沒有做任何處理消息的方法。
關閉應用程式,然後再試一次。
如果顯示一些錯誤資訊,simplepush.php腳本退出,檢查你是否正确制作PEM檔案,
并且你能正确的連接配接到沙盒伺服器 (見上文)。
現在,腳本究竟做了什麼并不重要。在這個系列的第二部分,我們會建立一個真正的推送伺服器,到那時候我們會就此做更多的說明。
接下來?
此時,你已經成功建立了一個app來接收推送通知,并且通過自定義的PHP代碼發送了第一條推送通知。
----------------------
建立 Push Notification Provider
Push Notification Provider 是一個應用程式,用于通過 APNs 發送推送通知給 iPhone 應用。
通過 APNs 發送推送通知有幾個步驟:
1. 使用前面建立的 SSL 證書與 APNs 通訊;
2. 構造所要發送的消息載體;
3. 發送載體到APNs;
APNs 是一個基于流的 TCP socket,你的 provider 以 SSL 協定與其通訊。推送通知(包括載體)是以二進制流的方式發送的。和APNs 建立連接配接後,你可以維持該連接配接并在連接配接中斷之前發送多個通知。
技巧: 應避免每發送一次推送通知就建立、關閉一次連接配接。頻繁的建立、關閉連接配接可能會被 APNs 認為是 DOS 攻擊,進而拒絕發送 provider 的推送通知發送請求。
一個推送通知消息的格式如圖24 所示:
更多細節,請參考 Apple Push Notification Service Programming Guide。
載體(payload)是 JSON 字元串(最長 256 位元組),封裝了你發送給 iOS 應用的資訊。這是一個 payload 的例子:
{
"aps": {
"alert" : "Yougot a new message!" ,
"badge" : 5,
"sound" : "beep.wav"},
"acme1" : "bar",
"acme2" : 42
}
寫provider之前,我們需要生成php Push Notification sender需要的證書檔案:
1)在Keychain Access.app裡標明這個新證書(Apple Development Push Services*),導出到桌面,儲存為Certificates.p12.
2)然後運作如下指令:
見第一部分。
下面是一個簡單的push notification proivder寫法:
view plain
- <span style="font-size:16px;"><?php
- $deviceToken = '38c866dd bb323b39 ffa73487 5e157ee5 a85e0b7ce90d56e9 fe145bcc 6c2c594b'; // masked for security reason
- // Passphrase for the private key (ck.pem file)
- // $pass = '';
- // Get the parameters from http get or from command line
- $message = $_GET['message'] or $message = $argv[1] or $message = 'Message received from javacom';
- $badge = (int)$_GET['badge'] or $badge = (int)$argv[2];
- $sound = $_GET['sound'] or $sound = $argv[3];
- // Construct the notification payload
- $body = array();
- $body['aps'] = array('alert' => $message);
- if ($badge)
- $body['aps']['badge'] = $badge;
- if ($sound)
- $body['aps']['sound'] = $sound;
- $ctx = stream_context_create();
- stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
- // assume the private key passphase was removed.
- // stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);
- $fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
- if (!$fp) {
- print "Failed to connect $err $errstrn";
- return;
- }
- else {
- print "Connection OKn";
- }
- $payload = json_encode($body);
- $msg = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;
- print "sending message :" . $payload . "n";
- fwrite($fp, $msg);
- fclose($fp);
- ?></span>
運作結果:Connection OKnsending message :{"aps":{"alert":"Message received from javacom"}}n
效果圖在下面。
為了省去自己編寫 push notification provider 的麻煩,你也可以使用 Stefan Hafeneger 寫的一個 Mac OS X 應用程式:PushMeBaby,下載下傳位址
1. 在Xcode 中打開 PushMeBaby。
2. 右擊 Resouces 檔案夾,選擇 Add Existing Files…,選擇前面所下載下傳到的aps.developer.identity.cer 檔案(圖25)。
3. 在 ApplicationDelegate.m 檔案中,修改如下代碼(加粗部分):
- (id)init {
self = [super init];
if(self != nil) {
self.deviceToken = @"38c866dd bb323b39 ffa73487 5e157ee5 a85e0b7ce90d56e9 fe145bcc 6c2c594b";
self.payload = @"{"aps":{"alert":"Yougot a new message!","badge":5,"sound":"beep.wav"},"acme1":"bar","acme2":42}";
self.certificate = [[NSBundle mainBundle]
pathForResource:@"aps_developer_identity" ofType:@"cer"];
}
return self;
}
4. 按下 ⌘+R,運作程式。将會問你是否允許使用證書,點選Always Allow(總是允許)(圖26):
在 iPhone/iPod,确認 ApplePushNotification 程式未運作。點選 Push 按鈕,會向裝置發送一條推送通知。伺服器實際上發送了下列消息給APN 伺服器:
{
"aps": {
"alert" : "Yougot a new message!" ,
"badge" : 5,
"sound" : "beep.wav"},
"acme1" : "bar",
"acme2" : 42
}
5. 如果消息推送成功,将會在 iPhone/iPod 上出現下圖(圖27):
6. 如果現在按下 ⌘+R 調試 ApplePushNotification 程式,然後從 PushMeBaby 中發送一條消息,控制台會顯示如下輸出:
2009-11-24 21:11:49.182 ApplePushNotification[1461:207]key: acme1, value: bar
2009-11-24 21:11:49.187 ApplePushNotification[1461:207]key: aps, value: {
alert = "You got a new message!";
badge = 5;
sound = "beep.wav";
}
2009-11-24 21:11:49.191 ApplePushNotification[1461:207]key: acme2, value: 42
幾個注意的問題:
1.如果申請ssl 證書時不是用的新的apple id,而是原來已經存在的,那麼設定好之後要把對應的provisioning profile
也更新一下, 然後去下載下傳新的profile替換掉老的,不然運作會有錯。
2.如果你用的是企業版的開發者證書,别人可能沒有權限去申請這個ssl 證書,當你替他申請好證書後,應該把證書和證書對
的私鑰一起發給他,這樣他在本地安裝私鑰時才會有對應的密鑰。
3.當push notification到達時,程式狀态不同,效果也是不一樣的,一般來說程式可以分為下面三種狀态:
1)程式不在運作(背景和前台都不在運作)
這時候如果push notification到了,會彈出一個alertview,當你點選action按鈕時,會啟動程式,并執行程式delegate.m檔案裡的
view plain
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
方法,是以你可以在這裡做一些處理:
view plain
- //看是否有push notification到達,并做相應處理,這個方法和local notification相同,但注意key要對應就行
- UILocalNotification * remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
- if (remoteNotification) {
- //彈出一個alertview,顯示相應資訊
- UIAlertView * al = [[UIAlertView alloc]initWithTitle:@"receive remote notification!" message:@"hello" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
- [al show];
- [al release];
- }
2)程式在運作(不論是在前台還是背景)
當push notification到達時,如果程式在前台運作并不會彈出alertview,而是直接執行下面方法:
view plain
- - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
- UIAlertView * al = [[UIAlertView alloc]initWithTitle:@"receive remote notification!" message:@"hey" delegate:self cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
- [al show];
- [al release];
- }
在這個方法裡你可以擷取到userInfo字典來進行相應處理。
如果程式是在背景運作,則會彈出一個alertview,當你點選action按鈕,也會執行上面一樣的方法。
是以如果你想要程式在push notification到達時,針對前台和背景運作做區分處理,你可以在上面方法裡先做一個狀态的
判斷:
view plain
- //可以根據application狀态來判斷,程式目前是在前台還是背景
- UIApplicationState state = [application applicationState];
- if (state == UIApplicationStateInactive) {
- // Application was in the background when notification
- // was delivered.
- }