iOS消息推送的工作機制可以簡單的用下圖來概括:
Provider是指某個iPhone軟件的Push服務器,APNS是Apple Push Notification Service的縮寫,是蘋果的服務器。
上圖可以分為三個階段:
第一階段:應用程序把要發送的消息、目的iPhone的標識打包,發給APNS。
第二階段:APNS在自身的已注冊Push服務的iPhone列表中,查找有相應標識的iPhone,並把消息發送到iPhone。
第三階段:iPhone把發來的消息傳遞給相應的應用程序,並且按照設定彈出Push通知。
從上圖我們可以看到:
1、應用程序注冊消息推送。
2、iOS從APNS Server獲取device token,應用程序接收device token。
3、應用程序將device token發送給PUSH服務端程序。
4、服務端程序向APNS服務發送消息。
5、APNS服務將消息發送給iPhone應用程序。
步驟一、
創建需要的證書 & 使用PHP編寫服務器端推送代碼
1. 登錄 iPhone Developer Connection Portal(http://developer.apple.com/iphone/manage/overview/index.action ) 然后點擊 App IDs
2. 創建一個 Apple ID ,如: com.tadpole.TestAPNs 注意:通配符 ID 不能用於推送通知服務。
3. 點擊Apple ID旁的“Configure”,根據“向導” 的步驟生成一個簽名上傳,然后下載生成的許可證。
4. 雙擊.cer文件將你的 aps_development.cer 導入Keychain中。
5. 在Mac上打開“鑰匙串訪問”,然后在“登錄”中選擇 "密鑰"分類,找到我們創建的證書,然后右擊“Apple Development IOS Push Services: com.tadpole.TestAPNs” > 導出 “Apple Development IOS Push Services: com.tadpole.TestAPNs”。保存為 cert.p12 文件。
6. 通過終端命令將這個cert.p12文件轉換為PEM格式,打開終端,cd 進入證書所在目錄,執行如下命令:
$ openssl pkcs12 -in cert.p12 -out apple_push_notification_production.pem -nodes -clcerts
執行完上面命令會在當前目錄下生成一個名為apple_push_notification_production.pem文件,這個文件就是我們需要得到php連接APNS 的文件,將apple_push_notification_production.pem和push.php放入同一目錄上傳到服務器,push.php的代碼如下:
<?php
// 這里是我們上面得到的deviceToken,直接復制過來(記得去掉空格)
$deviceToken = '740f4707bebcf74f 9b7c25d4 8e3358945f6aa01da5ddb387462c7eaf 61bb78ad';
// Put your private key's passphrase here:
$passphrase = 'abc123456';
// Put your alert message here:
$message = 'My first push test!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'apple_push_notification_production.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);
?>
步驟二、
創建一個具備推送通知的應用
首先,我們需要先對Xcode項目進行一些設置,確保App ID和provisioning profile都被設置成良好的狀態。做開發嗎,
1.在Supporting Files文件夾下選中ProjectName-Info.plist,對右側視圖中的Bundle Identifier選項進行修改,和你自己創建的App ID保持一致(形如:com.parseSampleApp)。
2.在左側的菜單中選中剛創建的project文件,在下面找到Build Settings然后搜索Code Signing Identity。
3.將對應provisioning profile的所有的值全部設置好。
4.選擇左手邊Targets下面的項目名稱,再次找到Build Settings,來到Code Signing Identity區域,確保所有的值都和新的provisioning profile保持一致。
代碼環節
接下來就開始進入編程模式了。我們需要對應用程序代理(app delegate)進行少量的修改,從而使得我們的應用可以接受到推送通知。步驟如下:
1.注冊設備需要在app delegate的[application:didFinishLaunchingWithOptions:]方法中調用[application registerForRemoteNotificationTypes:]方法,代碼如下:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Register for push notifications
[application registerForRemoteNotificationTypes:
UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound];
returnYES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken {
NSLog(@"regisger success:%@", pToken);
//注冊成功,將deviceToken保存到應用服務器數據庫中,因為在寫向ios推送信息的服務器端程序時要用到這個
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
// 處理推送消息
NSLog(@"userInfo == %@",userInfo);
NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];
UIAlertView *createUserResponseAlert = [[UIAlertViewalloc] initWithTitle:@"提示"
message: message
delegate:self
cancelButtonTitle:@"取消"
otherButtonTitles: @"確認",
nil];
[createUserResponseAlert show];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"Regist fail%@",error);
}
到這里一切順利的話我們就可以在真機運行了,注冊成功我們會得到iphone 的deviceToken,
步驟三、
接下來我們訪問http://localhost/push/push.php
iphone就會接收到一條推送消息了,如果有問題的話就檢查上面的操作步驟,特別是加紅的部分
另外去除標記的方法為,在viewDidApper中加入
int badge = [UIApplication sharedApplication].applicationIconBadgeNumber;
if(badge > 0)
{
badge--;
[UIApplication sharedApplication].applicationIconBadgeNumber = badge;
}