IOS 推送(本地推送、遠端推送、三方推送[極光推送])
Provider是給你手機應用發出推送訊息的伺服器,而APNS(Apple Push Notification Service)則是蘋果訊息推送伺服器。你本地的伺服器當需要給應用推送一條訊息的時候,先要將訊息發出到蘋果推送伺服器,然後再由蘋果推送伺服器將訊息發到安裝了該應用的手機。
接下來再看一張解釋圖:
根據上圖的邏輯我來給大家解釋一下:
1.你的IOS應用需要去註冊APNS訊息推送功能。
2.當蘋果APNS推送服收到來自你應用的註冊訊息就會返回一串device token給你(很重要)
3.將應用收到的device Token傳給你本地的Push伺服器。
4.當你需要為應用推送訊息的時候,你本地的推送伺服器會將訊息,以及Device Token打包傳送到蘋果的APNS服
5.APNS再將訊息推送給目的iphone
第二部分
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.建立推送專案
- //
- // AppDelegate.m
- // TestPushNotifiy
- //
- // Created by silicon on 14-10-30.
- // Copyright (c) 2014年 silicon. All rights reserved.
- //
- #import "AppDelegate.h"
- @implementation AppDelegate
- @synthesize mainView = _mainView;
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
- {
- //IOS8
- //建立UIUserNotificationSettings,並設定訊息的顯示類型別
- UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];
- [application registerUserNotificationSettings:notiSettings];
- } else{ // ios7
- [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert)];
- }
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- // Override point for customization after application launch.
- self.window.backgroundColor = [UIColor whiteColor];
- [self.window makeKeyAndVisible];
- self.mainView = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
- self.window.rootViewController = self.mainView;
- return YES;
- }
- - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{
- NSLog(@"---Token--%@", pToken);
- }
- - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
- NSLog(@"userInfo == %@",userInfo);
- NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];
- UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil nil];
- [alert show];
- }
- - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
- NSLog(@"Regist fail%@",error);
- }
- @end
在appdelegate.m中加入以上程式碼,
- if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
- {
- //IOS8
- //建立UIUserNotificationSettings,並設定訊息的顯示類型別
- UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];
- [application registerUserNotificationSettings:notiSettings];
- } else{ // ios7
- [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert)];
- }
由於ios8的推送跟ios7及以下的不一樣,所以需要加判斷來註冊訊息推送。
函式:
- - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{
- NSLog(@"---Token--%@", pToken);
- }
會接收來自蘋果伺服器給你返回的deviceToken,然後你需要將它新增到你本地的推送伺服器上。(很重要,決定你的裝置能不能接收到推送訊息)。
- - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
- NSLog(@"userInfo == %@",userInfo);
- NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];
- UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil nil];
- [alert show];
- }
這個函式則是當裝置接收到來自蘋果推送伺服器的訊息時觸發的,用來顯示推送訊息。
- - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
- NSLog(@"Regist fail%@",error);
- }
當註冊失敗時,觸發此函式。
2.PHP服務端
將simplepush.php這個推送指令碼也放在push資料夾中
- <?php
- // ??????????deviceToken???????????????
- $deviceToken = 'c95f661371b085e2517b4c12cc76293522775e5fd9bb1dea17dd80fe85583b41';
- // Put your private key's passphrase here:
- $passphrase = 'abc123';
- // Put your alert message here:
- $message = 'My first push test!';
- ////////////////////////////////////////////////////////////////////////////////
- $ctx = stream_context_create();
- stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
- stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
- // Open a connection to the APNS server
- //??????????
- //$fp = stream_socket_client(?ssl://gateway.push.apple.com:2195?, $err, $errstr, 60, //STREAM_CLIENT_CONNECT, $ctx);
- //?????????????appstore??????
- $fp = stream_socket_client(
- 'ssl://gateway.sandbox.push.apple.com:2195', $err,
- $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
- if (!$fp)
- exit("Failed to connect: $err $errstr" . PHP_EOL);
- echo 'Connected to APNS' . PHP_EOL;
- // Create the payload body
- $body['aps'] = array(
- 'alert' => $message,
- 'sound' => 'default'
- );
- // Encode the payload as JSON
- $payload = json_encode($body);
- // Build the binary notification
- $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
- // Send it to the server
- $result = fwrite($fp, $msg, strlen($msg));
- if (!$result)
- echo 'Message not delivered' . PHP_EOL;
- else
- echo 'Message successfully delivered' . PHP_EOL;
- // Close the connection to the server
- fclose($fp);
- ?>
deviceToken填寫你接收到的token,passPhrase則填寫你的ck.pem設定的密碼。
此刻就是見證奇蹟的時候了
使用終端進入到push資料夾,在終端輸入 php simplepush.php
若顯示以上提示則表示推送成功了。
附上一張成功圖。