好久沒有寫過部落格啦,今天就由本菜鳥給大家做一個簡單的IOSApp訊息推送教程吧!一切從0開始,包括XCode6, IOS8, 以及蘋果開發人員中心最新如何註冊應用,申請認證以及下載配置概要檔案,相信很多剛開始接觸iOS的人會很想瞭解一下。(ps:網上看了一下雖然有很多講述推送的好教程,我也是看著一步步學會的,但是這些教程的時間都是去年或者更早時期的,對引導新手來說不是很合適)
第一部分
首先第一步當然是介紹一下蘋果的推送機制(APNS)咯(ps:其實每一篇教程都有),先來看一張蘋果官方對其推送做出解釋的概要圖。
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 - L1Cverify error:num=20:unable to get local issuer certificateverify 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); } - (void)applicationWillResignActive:(UIApplication *)application { // 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. // 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. } - (void)applicationDidEnterBackground:(UIApplication *)application { // 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. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // 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. } - (void)applicationDidBecomeActive:(UIApplication *)application { // 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. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @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
若顯示以上提示則表示推送成功了。附上一張成功圖。
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。