IOS消息推送(轉)

第一部分php

首先第一步固然是介紹一下蘋果的推送機制(APNS)咯(ps:其實每一篇教程都有),先來看一張蘋果官方對其推送作出解釋的概要圖。ios

Provider是給你手機應用發出推送消息的服務器,而APNS(Apple Push Notification Service)則是蘋果消息推送服務器。你本地的服務器當須要給應用推送一條消息的時候,先要將消息發出到蘋果推送服務器,而後再由蘋果推送服務器將消息發到安裝了該應用的手機。json

接下來再看一張解釋圖:xcode


根據上圖的邏輯我來給你們解釋一下:安全

1.你的IOS應用須要去註冊APNS消息推送功能。服務器

2.當蘋果APNS推送服收到來自你應用的註冊消息就會返回一串device token給你(很重要)app

3.將應用收到的device Token傳給你本地的Push服務器。iphone

4.當你須要爲應用推送消息的時候,你本地的推送服務器會將消息,以及Device Token打包發送到蘋果的APNS服socket

5.APNS再將消息推送給目的iphoneide


第二部分

1.從證書頒發機構頒發證書

打開你mac的鑰匙串訪問: 而後點擊鑰匙串訪問

隨後它會彈出一個窗口 用戶電子郵件信息

就填寫你蘋果開發者帳號的名稱便可(應該是一個郵件名稱),點擊保存到磁盤的選項,點擊繼續,顯示以下



點擊存儲,文件名爲:CertificateSigningRequest.certSigningRequest 隨後將他放在一個文件夾中咱們取名push吧!


第三部分


訪問蘋果開發者網址:https://developer.apple.com/

選中MemberCenter選項,進入登錄頁面,用你的蘋果開發者帳號登錄,過一會網頁就會自動跳轉到下圖。

點擊紅色所選部分

內容進行下一步的操做。


選擇Certificates選項,設置證書,如圖所示先解釋一下

 

Development選項的做用顧名思義就是用來做爲開發使用的證書,Production選項則

是用來發布產品使用的,名稱很陌生是否是,以前的開發者網頁是沒有這一選項的,多是蘋果把他修改了,用這個名稱更加能讓人

理解吧(字面上解釋就是產品麼)。兩個選項生成證書的步驟是同樣的,如今咱們使用開發者的選項進行證書的製做,步驟以下:

選擇Development選項


點擊上面的加號選項,


選擇APNS選項(開發麼固然是在沙盒環境下了,模擬真實狀況),而後Continue


這個AppID咱們在下一部分講如何生成,如今我用的是已經生成好的一個應用ID,繼續Continue


這邊就要選擇在鑰匙串訪問環節下載下來的CertificateSigningRequest.certSigningRequest文件了,選擇並生成


點擊下載,獲得aps_development .cer,保存到push文件中去。


第四部分

新建一個AppID,選擇網頁上的AppIDs,而後點擊右上角的 「加號」


App的取名只要按照蘋果要求的就能夠了


而後BundleID是比較重要的,在提交審覈以及測試(蘋果的TestFlight)和付費環節都須要用到,也只需按照蘋果要求來寫就行了。


接下來就是對你的應用須要使用蘋果的哪些服務進行選擇就好了,例如廣告,遊戲中心,推送,付費等等狀況。


最後選擇「Submit」選項,在下一個界面中選擇「done」選項,這樣咱們設置AppID的步驟咱們就完成了。


第五部分:生成Provisioning Profiles

這個配置概要文件分爲兩種,一種是爲開發使用的,還有一種則是爲發佈到appStore上面。


建立發佈版的ProvisioningProfile與開發版的流程相同,點擊Development而後點擊右上角的加號

會進入選擇何種配置概要文件的界面


咱們如今時測試,因此選擇「IOS App Development」的選項,在下面的Distribution發佈選項中有兩個選擇,「App Store」以及「Ad hoc」,你能夠根據下面的描述

選擇你發佈所需的選項。點擊Continue進入下一步。


選擇你上一步建立的AppID,點擊Continue 進行下一步


選擇你的開發者帳號,Continue進行下一步


在這一步上選擇你的設備(你只有在這一步上勾選了你的設備,你才能在設備上用這個簽名進行調試)。關於如何將你的設備號添加進去也是很是

簡單的,選擇左側的"Devices",而後點擊右上角的加號,在隨後出來的頁面上添加你設備的UUID(在XCode中能夠查看到)以及name( 能夠隨便取,本身看的懂就行)

而後Register一下,照着流程走到最後一步就完成了。

好咋們繼續回到上面的Provisioning Profile配置環節,當你選好了你的設備後點擊「Continue」進入下一頁,


輸入一個文件名(最好是起的能看懂是幹嗎的,固然也能夠隨便起),點擊「Generate」進入下一個頁面,在這個頁面中就會有一個下載按鈕讓你下載這個文件,

咱們把它下載下來放在Push文件夾中。


第六部分

好了,前期的準備工做都已經作完了,如今讓咱們開始推送吧!(吼吼)

首先雙擊咱們生成的 「aps_development .cer」 文件,進入鑰匙串訪問,找到咱們的專用祕鑰(根據在第二部分中從證書機構頒發證書操做中填寫的經常使用名)


我在第二部分填寫的是「silicon」,因爲換了一臺mac以前安裝的沒有了,以前沒有截圖,因此隨便找了個圖給你們看一下,憑你們的聰明才智應該不難理解吧。

而後右擊導出,會彈出以下所示的圖。


 

將他存儲到push文件夾中,命名爲「push.p12」,在這一步中導出會讓你輸入密碼並驗證,你能夠自定義一個密碼,例如abc123


如今push文件夾中應該有幾個文件「aps_development .cer」 ,"push.p12",「CertificateSigningRequest.certSigningRequest」以及剛纔下下來的配置概要文件。

 

接下來咱們打開終端將他們生成.pem文件

1.把aps_development .cer文件生成.pcm文件,cd到push文件夾下


2.把push.p12文件生成爲.pem文件


上邊輸入的密碼則是你導出證書所設的密碼,即abc123.接着還會讓你輸入.pem文件的密碼,仍是使用abc123好了,防止混淆。

這樣咱們在push文件夾中就又獲得了兩個文件,PushChatCert.pem和PushChatKey.pem。


3.把PushChatCert.pem和PushChatKey.pem合併爲一個pem文件,


在push文件夾中又多了一個ck.pem文件,以上咱們把須要使用的文件都準備好了


接下來就要測試一下啦,是否是很激動~

爲了測試證書工做的情況,咱們可使用「telnet gateway.sandbox.push.apple.com 2195」來檢測一下,若是顯示


則表示成功了。


而後,咱們使用咱們生成的證書和私鑰來設置一個安全的連接去連接蘋果服務器

在終端輸入以下命令:openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem

須要輸入密碼(abc123 咱們剛纔所設置的)。

而後他會返回一系列的數據,這裏我就粘貼一部分啦:

 

CONNECTED(00000003)

depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C

verify error:num=20:unable to get local issuer certificate

verify return:0

---

Certificate chain

。。。。。(省略)

。。。。。(省略)

。。。。。(省略)

 

    Start Time: 1416389389

    Timeout   : 300 (sec)

    Verify return code: 0 (ok)

---

測試就到這裏啦。。。


第七部分

1.創建推送項目

 

[objc]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. //  
  2. //  AppDelegate.m  
  3. //  TestPushNotifiy  
  4. //  
  5. //  Created by silicon on 14-10-30.  
  6. //  Copyright (c) 2014年 silicon. All rights reserved.  
  7. //  
  8.   
  9. #import "AppDelegate.h"  
  10.   
  11. @implementation AppDelegate  
  12. @synthesize mainView = _mainView;  
  13.   
  14. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
  15. {  
  16.     if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])  
  17.     {  
  18.         //IOS8  
  19.         //建立UIUserNotificationSettings,並設置消息的顯示類類型  
  20.         UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];  
  21.           
  22.         [application registerUserNotificationSettings:notiSettings];  
  23.           
  24.     } else{ // ios7  
  25.         [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge                                       |UIRemoteNotificationTypeSound                                      |UIRemoteNotificationTypeAlert)];  
  26.     }  
  27.       
  28.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  
  29.     // Override point for customization after application launch.  
  30.     self.window.backgroundColor = [UIColor whiteColor];  
  31.     [self.window makeKeyAndVisible];  
  32.       
  33.     self.mainView = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];  
  34.     self.window.rootViewController = self.mainView;  
  35.     return YES;  
  36. }  
  37.   
  38. - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{  
  39.     NSLog(@"---Token--%@", pToken);  
  40. }  
  41.   
  42. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{  
  43.       
  44.     NSLog(@"userInfo == %@",userInfo);  
  45.     NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];  
  46.       
  47.     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"肯定", nil nil];  
  48.       
  49.     [alert show];  
  50. }  
  51.   
  52. - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{  
  53.   
  54.     NSLog(@"Regist fail%@",error);  
  55. }  
  56.   
  57. - (void)applicationWillResignActive:(UIApplication *)application  
  58. {  
  59.     // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.  
  60.     // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.  
  61. }  
  62.   
  63. - (void)applicationDidEnterBackground:(UIApplication *)application  
  64. {  
  65.     // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.   
  66.     // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.  
  67. }  
  68.   
  69. - (void)applicationWillEnterForeground:(UIApplication *)application  
  70. {  
  71.     // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.  
  72. }  
  73.   
  74. - (void)applicationDidBecomeActive:(UIApplication *)application  
  75. {  
  76.     // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.  
  77. }  
  78.   
  79. - (void)applicationWillTerminate:(UIApplication *)application  
  80. {  
  81.     // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.  
  82. }  
  83.   
  84. @end  


在appdelegate.m中加入以上代碼,

 

 

 

[objc]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])  
  2.     {  
  3.         //IOS8  
  4.         //建立UIUserNotificationSettings,並設置消息的顯示類類型  
  5.         UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];  
  6.           
  7.         [application registerUserNotificationSettings:notiSettings];  
  8.           
  9.     } else{ // ios7  
  10.         [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge                                       |UIRemoteNotificationTypeSound                                      |UIRemoteNotificationTypeAlert)];  
  11.     }  

因爲ios8的推送跟ios7及如下的不同,因此須要加判斷來註冊消息推送。

 

函數:

 

[objc]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{  
  2.     NSLog(@"---Token--%@", pToken);  
  3. }  

會接收來自蘋果服務器給你返回的deviceToken,而後你須要將它添加到你本地的推送服務器上。(很重要,決定你的設備能不能接收到推送消息)。

 

 

[objc]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{  
  2.       
  3.     NSLog(@"userInfo == %@",userInfo);  
  4.     NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];  
  5.       
  6.     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"肯定", nil nil];  
  7.       
  8.     [alert show];  
  9. }  


這個函數則是當設備接收到來自蘋果推送服務器的消息時觸發的,用來顯示推送消息。

 

 

[objc]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{  
  2.   
  3.     NSLog(@"Regist fail%@",error);  
  4. }  

當註冊失敗時,觸發此函數。

 


2.PHP服務端

將simplepush.php這個推送腳本也放在push文件夾中

 

[php]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. <?php  
  2.   
  3. // ??????????deviceToken???????????????  
  4. $deviceToken = 'c95f661371b085e2517b4c12cc76293522775e5fd9bb1dea17dd80fe85583b41';  
  5.   
  6. // Put your private key's passphrase here:  
  7. $passphrase = 'abc123';  
  8.   
  9. // Put your alert message here:  
  10. $message = 'My first push test!';  
  11.   
  12. ////////////////////////////////////////////////////////////////////////////////  
  13.   
  14. $ctx = stream_context_create();  
  15. stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');  
  16. stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);  
  17.   
  18. // Open a connection to the APNS server  
  19. //??????????  
  20.  //$fp = stream_socket_client(?ssl://gateway.push.apple.com:2195?, $err, $errstr, 60, //STREAM_CLIENT_CONNECT, $ctx);  
  21. //?????????????appstore??????  
  22. $fp = stream_socket_client(  
  23. 'ssl://gateway.sandbox.push.apple.com:2195', $err,  
  24. $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);  
  25.   
  26. if (!$fp)  
  27. exit("Failed to connect: $err $errstr" . PHP_EOL);  
  28.   
  29. echo 'Connected to APNS' . PHP_EOL;  
  30.   
  31. // Create the payload body  
  32. $body['aps'] = array(  
  33. 'alert' => $message,  
  34. 'sound' => 'default'  
  35. );  
  36.   
  37. // Encode the payload as JSON  
  38. $payload = json_encode($body);  
  39.   
  40. // Build the binary notification  
  41. $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;  
  42.   
  43. // Send it to the server  
  44. $result = fwrite($fp, $msg, strlen($msg));  
  45.   
  46. if (!$result)  
  47. echo 'Message not delivered' . PHP_EOL;  
  48. else  
  49. echo 'Message successfully delivered' . PHP_EOL;  
  50.   
  51. // Close the connection to the server  
  52. fclose($fp);  
  53. ?>  

deviceToken填寫你接收到的token,passPhrase則填寫你的ck.pem設置的密碼。

 

此刻就是見證奇蹟的時候了

使用終端進入到push文件夾,在終端輸入 php simplepush.php

若顯示以上提示則表示推送成功了。

附上一張成功圖。


推送就到這邊吧!

感謝這篇博客的指導:http://blog.csdn.net/showhilllee/article/details/8631734

相關文章
相關標籤/搜索