推送通知iOS客戶端編寫實(shí)現(xiàn)及推送服務(wù)器端編寫
1、iOS客戶端編程
推送通知技術(shù)在Mac OS X和iOS系統(tǒng)上都可以運(yùn)行,我們本章主要介紹iOS客戶端編程,推送通知的編程比較簡(jiǎn)單,編程的關(guān)鍵是獲得令牌,這是從APNS返回的,然后還有把提交給內(nèi)容提供商。下面我們看看開(kāi)發(fā)之前的一些準(zhǔn)備工作。
配置Xcode工程
編寫iOS推送應(yīng)用需要在Xcode工程中進(jìn)行一些配置,這些配置是主要是設(shè)置代碼簽名標(biāo)識(shí),代碼簽名標(biāo)識(shí)的前提要有配置概要文件(Provisioning Profiles)。
有了配置概要文件即可以設(shè)置代碼簽名標(biāo)識(shí)了,需要下載概要文件到本地,代碼簽名標(biāo)識(shí)需要選擇這個(gè)配置概要文件。選擇TAGETS→MyNotes→Code Signing Identity,選擇你自己的代碼簽名標(biāo)識(shí)。
設(shè)置完成之后可以開(kāi)始編碼工作了。
代碼實(shí)現(xiàn)
推送通知的代碼實(shí)現(xiàn)主要分為兩個(gè)步驟,第一步注冊(cè)接收通知,第二步接收注冊(cè)結(jié)果。這些工作都是在應(yīng)用程序委托對(duì)象AppDelegate中實(shí)現(xiàn)的。
我們先看看注冊(cè)部分的代碼:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//注冊(cè)接收通知類型
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge
| UIRemoteNotificationTypeSound
| UIRemoteNotificationTypeAlert)];
//設(shè)置圖標(biāo)標(biāo)記
application.applicationIconBadgeNumber = 1;
return YES;
}
注冊(cè)過(guò)程比較長(zhǎng),它通過(guò)APNS從蘋果公司返回,注冊(cè)結(jié)束后的回調(diào)方法代碼:
- (void)application:(UIApplication*)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
NSLog(@”設(shè)備令牌: %@”, deviceToken); ①
NSString *tokeStr = [NSString stringWithFormat:@"%@",deviceToken]; ②
if ([tokeStr length] == 0) {
return;
}
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"<>"];
tokeStr = [tokeStr stringByTrimmingCharactersInSet:set]; ③
tokeStr = [tokeStr stringByReplacingOccurrencesOfString:@" " withString:@""]; ④
NSString *strURL = @”http://192.168.1.103/push_chat_service.php”; ⑤
NSURL *url = [NSURL URLWithString:strURL];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:tokeStr forKey:@"token"];
[request setPostValue:@"98Z3R5XU29.com.51work6.PushChat" forKey:@"appid" ];
[request setDelegate:self];
NSLog(@”發(fā)送給服務(wù)器”);
[request startAsynchronous]; ⑥
}
- (void)application:(UIApplication*)application
didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
NSLog(@”獲得令牌失敗: %@”, error);
}
2、推送服務(wù)端編程
內(nèi)容提供者接收到設(shè)備的令牌并保存起來(lái),在有新的內(nèi)容需要推送的時(shí)候,他們將啟動(dòng)一個(gè)服務(wù)程序逐個(gè)設(shè)備推送他們的內(nèi)容。在推送具體的過(guò)程中并非直接 由內(nèi)容提供者,直接發(fā)送給用戶設(shè)備,而是服務(wù)程序與APNS通訊建立信任連接,然后把數(shù)據(jù)推送給APNS,再由APNS利用安全通道推送給用戶設(shè)備。
如果要編寫內(nèi)容提供者的推送服務(wù)程序,我們需要進(jìn)行SSL認(rèn)證編程,以及構(gòu)建APNS數(shù)據(jù)包,數(shù)據(jù)包分為3個(gè)主要部分:Command(命令)、deviceToken(令牌)和Payload(載荷)。載荷不能超過(guò)256字節(jié),是JSON格式,例如:
{“aps” : {
“alert” : ”You got your emails.”,
“badge” : 9,
“sound” : ”bingbong.aiff”
}
}
作為推出服務(wù)程序可以使用很多計(jì)算機(jī)語(yǔ)言實(shí)現(xiàn),如果從便于管理角度看,使用PHP、Java和.NET,甚至是Note.js都是可以選擇的。本書重點(diǎn)介紹PHP和Java編寫推送服務(wù)程序。
使用PHP實(shí)現(xiàn)推送服務(wù)
PHP是非常不錯(cuò)的服務(wù)器端腳本,這么多年來(lái)沒(méi)有被JavaEE和.NET蠶食掉,說(shuō)明它有過(guò)人之處。PHP編程簡(jiǎn)單很多人原意使用,實(shí)現(xiàn)本章推送服務(wù)也很簡(jiǎn)單。下面代碼是實(shí)現(xiàn)了推送的PHP代碼:
$deviceToken= ’1634899aef6c71ed5c0667d6658677a914c5ec3b545887e8173854970dee24db’;
//推送方式,包含內(nèi)容和聲音
$body = array(“aps” => array(“alert” => ’新年好. from PHP’,”badge” => 11,”sound”=>’default’)); ①
//創(chuàng)建數(shù)據(jù)流上下文對(duì)象
$ctx = stream_context_create();
//設(shè)置pem格式文件
$pem = ”apns-dev.pem”; ②
//設(shè)置數(shù)據(jù)流上下文的本地認(rèn)證證書
stream_context_set_option($ctx,”ssl”,”local_cert”, $pem); ③
$pass = ”51work6.com”;
//設(shè)置數(shù)據(jù)流上下文的密碼
stream_context_set_option($ctx, ’ssl’, ’passphrase’, $pass); ④
//產(chǎn)品發(fā)布APNS服務(wù)器,gateway.push.apple.com
//測(cè)試APNS服務(wù)器,gateway.sandbox.push.apple.com[!--empirenews.page--]
//socket通訊
$fp = stream_socket_client(“ssl://gateway.sandbox.push.apple.com:2195″, $err, $errstr, 60,
STREAM_CLIENT_CONNECT, $ctx); ⑤
if (!$fp) {
echo ”連接失敗.”;
return;
}
print ”連接OKn”;
//載荷信息,JSON編碼
$payload = json_encode($body); ⑥
//構(gòu)建發(fā)送的二進(jìn)制信息
$msg = chr(0) . pack(“n”,32) . pack(“H*”, str_replace(‘ ’, ”, $deviceToken))
. ack(“n”,strlen($payload)) . $payload; ⑦
echo ”發(fā)送消息:” . $payload .”n”;
fwrite($fp, $msg);
fclose($fp);
?>
打開(kāi)終端窗口執(zhí)行如下命令:
$ openssl pkcs12 -in 證書.p12 -out apns-dev.pem -nodes
Enter Import Password:
MAC verified OK
回車后需要輸入密碼,這個(gè)密碼是導(dǎo)出“證書.p12”時(shí)候設(shè)置的密碼。
PHP代碼編寫完成可以運(yùn)行PHP了,有兩種方法可以運(yùn)行,一種是把這個(gè)文件放到Apache HTTP服務(wù)器目錄下,并保證Apache下安裝和 PHP,然后用瀏覽器運(yùn)行,在瀏覽器中輸入http://localhost/phpPNs/Pusher.php,這個(gè)URL是我自己 Apache HTTP服務(wù)器上的PHP文件。
另外一種方法,簡(jiǎn)單的多,我們不需要安裝Apache HTTP服務(wù)器,只需要安裝了PHP解釋器就可以了,我們?cè)诮K端中運(yùn)行下面的指令:
$ php -f Pusher.php
連接OK
發(fā)送消息:{“aps”:{“alert”:”u65b0u5e74u597d. from PHP”,”badge”:11,”sound”:”default”}}
這樣就可以推送通知了,如果一切正常推送成功,用戶的設(shè)備就可以接收到通知了。
使用Java推送服務(wù)
上面我們介紹了PHP實(shí)現(xiàn)的推送服務(wù)程序,使用其它語(yǔ)言編寫基本的過(guò)程也一樣的,這一節(jié)我們就介紹Java推送服務(wù)程序。由于具體的流程與PHP一 樣,這里我們就不再自己編寫Java的實(shí)現(xiàn)代碼,而是使用別人已經(jīng)封裝好的javapns(http://code.google.com/p /javapns/)類庫(kù),它封裝了socket實(shí)現(xiàn)細(xì)節(jié)問(wèn)題,開(kāi)發(fā)起來(lái)變的比較簡(jiǎn)單了。
下面代碼是實(shí)現(xiàn)了推送的Java代碼:
package com._51work6;
import javapns.Push;
import javapns.notification.PushNotificationPayload;
public class Pusher {
public static void main(String[] args) {
try {
PushNotificationPayload payload = new PushNotificationPayload(); ①
payload.addCustomAlertBody(“新年好!from Java”); ②
payload.addBadge(11); ③
payload.addSound(“default”); ④
Push.payload(payload, ”ssl/證書.p12″, ”51work6.com”, false,
“1634899aef6c71ed5c0667d6658677a914c5ec3b545887e8173854970dee24db”); ⑤
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面的代碼還依賴與下面的類庫(kù):bcprov-jdk15-146.jar、JavaPNS_2.2.jar和log4j-1.2.15.jar。 其中bcprov-jdk15-146.jar和JavaPNS_2.2.jar可以在http://code.google.com/p /javapns/下載到。log4j-1.2.15.jar到http://logging.apache.org/log4j/1.2 /download.html下載。
這個(gè)Java程序的運(yùn)行我們就不再介紹了,它是一個(gè)Java Application可以在有jre環(huán)境運(yùn)行,我們可以把它做成JavaWeb程序,這樣就可以在瀏覽器中發(fā)送通知了。