遠程推送

這裏主要詳細介紹蘋果的遠程推送服務,在本文後會有本地通知的簡單示例。
一,IOS遠程通知服務APNs
蘋果的APNs(蘋果推送通知服務Apple Push Notification server)允許設備和蘋果的推送通知服務器保持鏈接,支持開發者推送消息到給用戶設備對應的應用程序。
蘋果的APNs基本原理是:
首先由應用註冊遠程通知。註冊成功之後APNs會返回一個唯一標示的設備令牌碼deviceToken,應用拿到分配的設備令牌碼之後,需要將該設備令牌碼連同其他設備以及帳戶相關信息(如果有必要的話)傳遞給該應用對應的後臺服務器。當後臺服務器需要推送消息時,就將消息以及需要推送設備對應的deviceToken傳遞給APNs,由APNs完成推送工作.
不僅如此,應用對應的後臺服務器還需要經常和APNs進行反饋通信,以便後臺服務器可以知道那些deviceToken已經不存在(可能的原因是用戶卸載了本應用),這種情況下我們不應該再向deviceToken對應的設備發送消息,否則會增加系統負荷。事實上,做蘋果的APNs大量的工作都在後臺,在前臺的app開發中需要做的就是獲取deviceToken並傳遞給後臺服務器。
下面特酷吧根據自己的實踐介紹下整個操作流程。
如果之前我們創建App ID時配置了開啓推送服務,那麼我們使用的開發和發佈版的Provisioning文件已經能夠滿足我們的操作,這種情況下需要做的就是製作後臺服務器使用的證書文件。
1,創建請求證書
使用該證書請求來申請一個用於開發的SSL證書。
1. 打開“鑰匙串訪問”應用程序。
2. 選擇“KeychainAccess[鑰匙串訪問]->Certificate Assistant[證書助理]->Request a Certificate From CertificateAuthority[從證書辦法機構請求證書]”
輸入賬戶等信息後以默認的文件名保存到本地。名稱一般爲CertificateSigningRequest.certSigningRequest。
2,申請開發的SSL證書
(1)創建App ID
使用APNs服務的IOS應用必須有一個唯一的App ID。首先我們需要創建App ID。
進入apple開發者中心
https://developer.apple.com/devcenter/ios/index.action
進入"Certificates,Identifiers & Profiles"。
[特酷吧寫這篇文章的時候是2013年5月,apple開發者中心的網站似乎改版過,和之前有些不一樣了]。
進入"ios Apps",點擊"Identifiers"。
點擊右上角的加號添加一個App ID.
App ID Description中name可以隨便取一個名字.
App Services中Enable Services字段需要勾選Push Notifications。[當前這些內容都可以在App ID創建好之後重新再配置]
Explicit App ID中的Bundle ID填入我們應用的Bundle ID即可。其他默認。
(2)配置App ID
創建好App ID之後,進入該App ID詳情頁面。進入setting。
選擇"Create an additional certificate to use for this App ID."進入"Create Certificate"頁面之後根據提示嚮導選擇第1步生成的請求證書上傳。
再根據操作嚮導下載生成好的開發版的SSL證書。下載之後[名稱爲aps_development.cer],雙擊將證書安裝到鑰匙串中。這個證書會允許你的程序接收APNs發送來的推送通知。
3,創建Provisioning Profile
進入https://developer.apple.com/account/ios/profile/profileList.action
Provisioning Profiles
點擊右上角加號添加Provisioning Profile, 選擇iOS App Development,選擇你剛纔創建的App ID。
過程中會讓你選擇你需要包含的設備(我是勾選所有設備)。再隨便輸入你取的證書的名字即可生成該證書。下載到本地安裝該文件。名稱一般爲XXXX.mobileprovision
將XXXX.mobileprovision導出p12格式的私鑰文件,這裏名稱爲Certificates.p12文件
4,製作後臺服務器(C#爲例)使用的p12文件
需要創建C#用的證書文件,具體制作過程如下:
製作p12文件,我們需要使用OpenSSL
我們需要上面幾步中得到的三個文件:
1、CertificateSigningRequest.certSigningRequest
2、Certificates.p12//本地導出的私鑰文件
3、aps_development.cer
操作如下,在終端中執行;
1、將aps_development.cer轉換成aps_development.pem格式。
openssl x509 -in aps_development.cer -inform DER -out aps_development.pem -outform PEM
2、將p12格式的私鑰轉換成pem,需要設置幾次密碼。
openssl pkcs12 -nocerts -out Certificates.pem -in Certificates.p12
3、用CertificateSigningRequest.certSigningRequest, Certificates.pem和aps_development.pem創建P12格式的文件。
openssl pkcs12 -export -in aps_development.pem -inkey Certificates.pem -certfile CertificateSigningRequest.certSigningRequest -name "aps_developer_identity" -out aps_developer_identity.p12
這樣我們就得到了在.net應用程序中使用的證書文件:aps_developer_identity.p12。
基於C#,JAVA等程序的開源的庫也比較多,如:https://github.com/Redth/APNS-Sharp提供了一個C#的版本。在該測試程序中,需要給出這裏的aps_developer_identity.p12文件以及密碼。
此外,爲了方便IOS開發者測試APNs,已經有很多做好的線程的服務器端的demo,比如:PushMeBaby[下載地址:https://github.com/stefanhafeneger/PushMeBaby].
下載完成後打開工程,將aps.developer.cer文件加入到工程中,修改工程中對應代碼:
self.deviceToken = /*填入第4步中didRegisterForRemoteNotificationsWithDeviceToken獲取到的deviceToken*/;
self.certificate = [[NSBundle mainBundle] pathForResource:@"aps_developer" ofType:@"cer"]; 
運行PushMeBaby工程,點擊push即可給app終端發送消息。
5,本地app代碼參考
1,在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions中註冊遠程通知
//註冊遠程通知
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
2,實現幾個代理方法:
  1. //獲取deviceToken令牌  
  2. -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken  
  3. {  
  4.     //獲取設備的deviceToken唯一編號  
  5.     NSLog(@"deviceToken=%@",deviceToken);  
  6.     NSString *realDeviceToken=[NSString stringWithFormat:@"%@",deviceToken];  
  7.     //去除<>  
  8.     realDeviceToken = [realDeviceToken stringByReplacingOccurrencesOfString:@"<" withString:@""];  
  9.     realDeviceToken = [realDeviceToken stringByReplacingOccurrencesOfString:@">" withString:@""];  
  10.     NSLog(@"realDeviceToken=%@",realDeviceToken);  
  11.     [[NSUserDefaults standardUserDefaults] setValue:realDeviceToken forKey:@"DeviceToken"];  
  12. }  
  13.   
  14. //獲取令牌出錯  
  15. -(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error  
  16. {  
  17.     //註冊遠程通知設備出錯  
  18.     NSLog(@"RegisterForRemoteNotification error=%@",error);  
  19. }  
  20. //在應用在前臺時受到消息調用  
  21. -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo  
  22. {  
  23.    //打印推送的消息  
  24.   NSLog(@"%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]):  
  25. }  
另外:
在進行IOS遠程推送的過程中,首先需要創建帶有“Enable for Apple Push Notification service”的App ID。如果之前的創建的App ID開啓了推送功能,則可以直接使用之前開發和發佈需要的Provisioning。如果之前的App ID沒有配置開啓遠程推送功能,則應該首先創建開啓了遠程推送功能的App ID,並根據該App ID生成對應的開發和發佈版本的Provisioning。
還需要製作服務器端的證書,如果app使用的是開發者證書,則需要使用此開發者證書製作服務器端的開發者證書,等到發佈版的時候,還需要製作發佈版本的證書。
使用開發者證書的測試地址
gateway.sandbox.push.apple.com:2195 
發佈版本的地址
gateway.push.apple.com:2195
另外一個值得注意的問題是:一般我們是使用開發版本的Provisioning做推送測試,如果沒有問題,再使用發佈版本證書的時候一般也應該是沒有問題的。爲了以防萬一,我們可以在越獄的手機上安裝我們的使用發佈版證書的ipa文件(最好使用debug版本,並打印出獲取到的deviceToken),安裝成功後在;XCode->Window->Organizer-找到對應的設備查看console找到打印的deviceToken。
在後臺的推送程序中使用發佈版製作的證書並使用該deviceToken做推送服務.
使用開發和發佈證書獲取到的deviceToken是不一樣的



 
遠程通知
 
/**
 遠程消息推送必須在真機上運行!
 */
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // 需要告訴蘋果的服務器,當前應用程序需要接收遠程通知
    [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | 
     UIRemoteNotificationTypeSound];
    returnYES;
}
 
#pragma mark - 獲取到設備的代號(令牌)
// 接收到蘋果返回的設備代號
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    // 第一次運行獲取到DeviceToken時間會比較長!
    NSLog(@"%@", deviceToken);
     
    // 將deviceToken轉換成字符串,以便後續使用
    NSString *token = [deviceToken description];
    NSLog(@"description %@", token);
     
    // =======================================================
    // 如果DeviceToken發生變化,需要通知服務器
    // 每次都記錄住從服務器獲取到得DeviceToken
    // 再次獲取時進行比對
    // 從偏好設置取出當前保存的Token
    NSString *oldToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"DeviceToken"];
     
    // 當Token發生變化時,提交給服務器保存新的Token
//    if (![oldToken isEqualToString:token]) {
//        
//        // 將deviceToken通過Post請求,提交給自己的服務器即可!
//        // 發送Post請求
//        NSURL *url = [NSURL URLWithString:@"公司後臺服務器的網址"];
//        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:
//        NSURLRequestUseProtocolCachePolicy timeoutInterval:10.f];
//        request.HTTPMethod = @"POST";
//        request.HTTPBody = @"轉換後的設備ID以及其他信息[之前的Token]";
//        
//        // SQL: update t_deviceTable set token = newToken where token = oldToken;
//        
//        // 同步:必須執行完才能繼續
//        // 異步:直接交給其他線程工作,不干擾主線程工作,用戶也感覺不到延遲
//        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(
//       NSURLResponse *response, NSData *data, NSError *connectionError) {
//            // 偷偷的將用戶信息傳送到公司的服務器
//        }];
//    }
     
    // 將Token保存至系統偏好
    [[NSUserDefaults standardUserDefaults] setObject:token forKey:@"DeviceToken"];
}

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