發(fā)表日期:2016-07 文章編輯:小燈 瀏覽次數(shù):3879
一.關(guān)于推送通知
推送通知,也被叫做遠程通知,是在iOS
3.0以后被引入的功能。是當程序沒有啟動或不在前臺運行時,告訴用戶有新消息的一種途徑,是從外部服務器發(fā)送到應用程序上的。一般說來,當要顯示消息或
下載數(shù)據(jù)的時候,通知是由遠程服務器(程序的提供者)發(fā)送,然后通過蘋果的推送通知服務(Apple Push Notification
Service,簡稱apns)推送到設備的程序上。
推
送的新消息可能是一條信息、一項即將到期的日程或是一份遠程服務器上的新數(shù)據(jù)。在系統(tǒng)上展現(xiàn)的時候,可以顯示警告信息或在程序icon上顯示數(shù)字,同時,
也可以播放警告音。一旦用戶注意到程序有新的信息、時間或是數(shù)據(jù),他們可以運行程序并訪問新的內(nèi)容。也可以選擇忽略通知,這時程序?qū)⒉粫患せ睢?/p>
iPhone, iPad和iPod touch上同一時刻只有一個app在前臺運行。大多數(shù)程序在后臺運行的時候,可以對某些用戶感興趣的內(nèi)容做出回應(定時、或數(shù)據(jù)等)。推送通知能讓程序在這些事件發(fā)生的時候通知用戶。
作
為提供者為程序開發(fā)和部署推送通知,必須通過iOS Developer Program
Portal獲得SSL證書。每個證書限用于一個程序,使用程序的bundle
ID作為標識。證書有兩種用途的:一種是針對sandbox(用于開發(fā)和測試),另外一種針對發(fā)布產(chǎn)品。這兩種運行環(huán)境擁有為各自指定的IP地址并且需要
不同的證書。還必須為兩種不同的環(huán)境獲取各自的provisioning profiles。
APNS提供了兩項基本的服務:消息推送和反饋服務。
消
息推送:使用流式TCP套接字將推送通知作為二進制數(shù)據(jù)發(fā)送給APNs。消息推送有分別針對開發(fā)和測試用的sandbox、發(fā)布產(chǎn)品的兩個接口,每個都有
各自的地址和端口。不管用哪個接口,都需要通過TLS或SSL,使用SSL證書來建立一個安全的信道。提供者編制通知信息,然后通過這個信道將其發(fā)送給
APNs。 注:sandbox:?? gateway.sandbox.push.apple.com:219
產(chǎn)品接口:gateway.push.apple.com:2195
反
饋服務:可以得到針對某個程序的發(fā)送失敗記錄。提供者應該使用反饋服務周期性檢查哪些設備一直收不到通知,不需要重復發(fā)送通知到這些設備,降低推送服務器
的負擔。 注:sandbox:feedback.push.apple.com:2196
產(chǎn)品接口:feedback.sandbox.push.apple.com:2196
二.Apple Push Notification的工作機制
自己的客戶端發(fā)送消息到自己應用軟件的apns,apns發(fā)送消息到你的手機。這個是根據(jù)令牌識別的。手機在發(fā)送消息到你的應用軟件。
首先是應用程序注冊消息推送。
IOS跟APNS Server要deviceToken。應用程序接受deviceToken。
應用程序?qū)eviceToken發(fā)送給PUSH服務端程序(Provider)。
服務端程序向APNS服務發(fā)送消息。
APNS服務將消息發(fā)送給iPhone應用程序。
1. Provider是指某個iPhone軟件的Push服務器,是我們將要開發(fā)的服務器。
2. APNS 是Apple Push Notification Service(Apple Push服務器)的縮寫,是蘋果的服務器。
上圖可以分為三個階段:
第一階段:推送服務器(provider)把要發(fā)送的消息、目的iPhone的標識打包,發(fā)給APNS;
第二階段:APNS在自身的已注冊Push服務的iPhone列表中,查找有相應標識的iPhone,并把消息發(fā)到iPhone;
第三階段:iPhone把發(fā)來的消息傳遞給相應的應用程序,并且按照設定彈出Push通知。
三 推送之前的配置
在任何iOS應用開發(fā)里面,開發(fā)人員總是在團隊里面扮演某一角色:團隊經(jīng)理,團隊管理員,和團隊成員。iPhone開發(fā)證書和配置文件由不同角色完成。通常團隊經(jīng)理是團隊里面唯一可以創(chuàng)建Development SSL證書(沙箱環(huán)境)和Distribution SSL證書(產(chǎn)品環(huán)境)的人。而團隊經(jīng)理和團隊管理員都可以創(chuàng)建Development和Distribution的配置文件。團隊成員只能下載并安裝證書和配置文件(!這里要區(qū)別好證書和配置文件的概念:證書,即Certificates,它主要是使用Access Key Chain來生成的一個簽名密鑰。而配置文件,即Provisioning profiles,它主要是根據(jù)不同的App來生成的針對性的代碼簽名文件。二者區(qū)別是一般一個開發(fā)者賬戶只能有一個Certificates(而Development一個,Distribtuion一個),但是可以有多個Provisioning profiles文件,且這些Provisioning profiles通常創(chuàng)建的時候都使用同一個Certrificates)。以下部分詳細介紹該過程。
注意:iOS Provisioning Portal給所有iOS開發(fā)者。
創(chuàng)建SSL證書和密鑰
在iOS Dev Center的iOS Provisioning Portal里面,團隊經(jīng)理選中相應APNs的AppID。他需要完成以下步驟來創(chuàng)建SSL證書:
1.
點擊窗口左邊側(cè)邊欄的App IDs。
將會跳轉(zhuǎn)到一個顯示當前合法應用IDs的頁面。每個應用的ID前面包含了它的Bundle ID,而在Bundle ID之前包含了蘋果生成的十位字符串。團隊管理員必須輸入Bundle ID。對于每個證書,它必須匹配某一特定的Bundle ID,你不能使用“wildcart”的應用ID。即要使用推送通知的應用的Bundle ID不能使用“*”來創(chuàng)建。
2.
找到需要創(chuàng)建SSL證書的應用ID(和Development Provisioning Profile相關(guān)),并單擊Configure按鈕。
你必須確保該App ID下面的蘋果推送通知服務欄下面顯示“可用”狀態(tài)才能為該應用配置APNs證書。
3.
在App ID配置頁面,檢查已經(jīng)勾選了“Enable for Apple Push Notification service”復選框,并點擊下面的“Configure”按鈕。
單擊該按鈕將會啟動APNs助理,它會通過一系列步驟來引導完成操作。
4.
第一步要求你啟動Keychain Access應用并生成一個Certificate Signing Request(CSR)文件。
下面的介紹來自證書助理。當你完成生成CSR后,點擊Keychain Access上面Continue來返回到APNs Assistant。
當你創(chuàng)建一個CSR時,Keychain Access生成一個私有和公有的加密密鑰對。而私有的密鑰會默認被放入你的Login keychain里面。而公有的密鑰包含CSR會發(fā)送到配置服務器。當配置服務器把證書發(fā)回給你的時候,證書里面的其中一個條目將是公有密鑰。
5.
在Submit Certificate Signing Request面板上,單擊Choose File。導航到你之前創(chuàng)建的CSR文件的地方并選中它。
6.
單擊Generate按鈕。
在顯示Generate Your Certificate面板的同時,Assistant會配置并生成你的客戶端SSL證書。如果生成成功,它將會顯示信息“Your APNs Certificate has been generated.”。單擊Continue來進入下一步操作。
7.
在下一個面板,單擊Download Now按鈕來下載證書文件到本地文件夾。找到文件下載的地方并雙擊證書文件(該證書文件包含一個.cer的擴展名)來把它安裝到你的keychain里面。當完成后,單擊APNs Assistant上面的Done按鈕。
雙擊加載啟動Keychain Access。確保你已經(jīng)把剛才的證書安裝到了你用于開發(fā)的電腦的login keychain里面。在Keychain Access里面,確保你的證書使用的ID匹配你應用的Bundle ID。APNs的SSL證書應該安裝到你的通知服務上面。
當你返回到iOS Dev Center Portal的Configure App ID頁面完成這些步驟后,你的證書應該會變成綠色,并且顯示“Enabled”。
為了給產(chǎn)品環(huán)境創(chuàng)建一個證書,重復上述步驟,但記住選中產(chǎn)品證書的應用ID。
團隊經(jīng)理或團隊管理器接下來必須創(chuàng)建在服務器用于遠程通知開發(fā)的配置證書(Development 或 Distribution)。配置文件就是一個集合,它囊括了和應用相關(guān)的開發(fā)者和開發(fā)團隊驗證過的設備并使用這些設備來測試應用程序。配置文件包含了證書、設備標示符、應用的Bundle ID、和所有權(quán)利,包括。所有團隊程序需要在運行并測試他們應用代碼的設備上面安裝該配置文件。
注意:關(guān)于創(chuàng)建配置文件的詳細解析參考編程用戶指南。
為了下載并安裝配置文件,團隊程序必須完成以下步驟:
1.
進入iOS Dev Center的Provisioning portal頁面。
2.
創(chuàng)建一個新的配置文件,并包含你注冊用于APNs的App ID。
3.
在你下載這個新的配置文件之前修改任何已存在的配置文件。
你必須修改配置文件的一些細微部分(比如切換選項)來生成一個新的配置文件。如果配置文件并沒有“受損(dirtied)”,你不應該給以該原始配置文件任何推送的權(quán)利。
4.
找到文件的下載目錄,把該配置文件(通常是一個.mobileprovision擴展文件)拖拉到Xcode或iTunes應用程序的圖標上面。
可選的,你也可以把配置文件復制到~/Library/MobileDevice/Provisioning Profiles目錄。如果當前目錄不存在則生成一個新目錄。
5.
驗證該配置文件的權(quán)利是否正確。為此,使用文本編輯器打開.mobileprovision文件。該文件的內(nèi)容是一個XML的文本。查看在aps-environment鍵的位置的字典值。對于一個開發(fā)模式的配置文件,該值應該是development;而對應發(fā)布模式的配置文件,該字符值應該是production。
6.
在Xcode的Organizer窗口,查看Provisioning Profiles部分,并確認證書已經(jīng)安裝到你的設備上面。
當你編譯該工程的時候,二進制文件現(xiàn)在使用證書的私有密鑰簽名。
4.2.3
安裝SSL證書和密鑰到你的服務器上面
你必須安裝SSL發(fā)布證書和你之前獲取的私有加密密鑰到需要運行提供者代碼的服務器上,從該服務器連接到APNs的沙箱或產(chǎn)品環(huán)境。為此,需要完成以下步驟:
1.
打開Keychain Access實體并單擊左邊面板的My Certificates類別。
2.
找到你將要安裝的證書,并打開相應內(nèi)容。
你將會看到證書和私有密鑰。
3.
選中證書和密鑰,選中File > Export Items,并把它們導出個人信息交換文件(.p12)。
4.
如果服務器采用Buby或Perl語言來實現(xiàn)的話,那么它們更容易處理個人信息交換格式的文件。為了把證書轉(zhuǎn)換為該格式,需要完成以下步驟:
a)
在Keychain Access里面,選中相應證書并選擇File > Export Items。選擇個人信息交換格式選項(.p12)。選擇一個保存地址,并單擊Save按鈕。
b)
加載終端應用,并輸入如下的命令:
openssl pkcs12 -in CertificateName.p12 -out CertificateName.pem -nodes
5.
拷貝.pem證書文件到新的電腦并安裝它到合適的地方。
這次準備工作已經(jīng)完成了。
下面是客戶端的步驟了
一個應用程序必須在設備(iOS設備或Mac電腦)上面注冊了蘋果推送通知服務才能接收來自程序提供者的遠程通知。
注冊過程包含以下三個步驟:
一個應用程序必須在設備(iOS設備或Mac電腦)上面注冊了蘋果推送通知服務才能接收來自程序提供者的遠程通知。
注冊過程包含以下三個步驟:
1.
程序調(diào)用registerForRemoteNotificationTypes:方法。
2.
委托實現(xiàn)application:didRegisterForRemoteNotificationsWithDeviceToken:方法來接收設備令牌。
3.
把設備令牌作為非對象(二進制值)傳遞給程序提供者。
1.
程序調(diào)用registerForRemoteNotificationTypes:方法。
2.
委托實現(xiàn)application:didRegisterForRemoteNotificationsWithDeviceToken:方法來接收設備令牌。
3.
把設備令牌作為非對象(二進制值)傳遞給程序提供者。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[ViewController alloc] init] autorelease];
self.window.rootViewController = self.viewController;
[self.window setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"background.png"]]];
[self.window makeKeyAndVisible];
/** 注冊推送通知功能, */
[[UIApplication sharedApplication]
registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
//判斷程序是不是由推送服務完成的
if(launchOptions) {
NSDictionary* pushNotificationKey = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(pushNotificationKey) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"推送通知"
message:@"這是通過推送窗口啟動的程序,你可以在這里處理推送內(nèi)容"
delegate:nil
cancelButtonTitle:@"知道了"
otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
}
returnYES;
}
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString* token = [NSString stringWithFormat:@"%@",deviceToken];
NSLog(@"apns -> 生成的devToken:%@", token);
//把deviceToken發(fā)送到我們的推送服務器
DeviceSender* sender = [[[DeviceSender alloc]initWithDelegate:self ]autorelease];
[sender sendDeviceToPushServer:token ];
}
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSLog(@"apns -> 注冊推送功能時發(fā)生錯誤, 錯誤信息:\n %@", err);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(@"\napns -> didReceiveRemoteNotification,Receive Data:\n%@", userInfo);
//把icon上的標記數(shù)字設置為0,
application.applicationIconBadgeNumber = 0;
if([[userInfo objectForKey:@"aps"] objectForKey:@"alert"]!=NULL) {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"**推送消息**"
message:[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]
delegate:self
cancelButtonTitle:@"關(guān)閉"
otherButtonTitles:@"處理推送內(nèi)容",nil];
alert.tag = alert_tag_push;
[alert show];
}
}
至此已經(jīng)可以了,如果沒有服務器端可以參考pushMebaby