本地通知,local notification,用於基於時間行為的通知,比如有關日曆或者todo列表的小應用。另外,應用如果在後台執行,iOS允許它在受限的時間內運行,它也會發現本地通知有用。比如,一個應用,在後台運行,嚮應用的伺服器端擷取訊息,當訊息到達時,比如下載更新版本的提示訊息,通過本地通知機制通知使用者。
本地通知是UILocalNotification的執行個體,主要有三類屬性:
- scheduled time,時間周期,用來指定iOS系統發送通知的日期和時間;
- notification type,通知類型,包括警告資訊、動作按鈕的標題、應用表徵圖上的badge(數字標記)和播放的聲音;
- 自訂資料,本地通知可以包含一個dictionary類型的本機資料。
- 對本地通知的數量限制,iOS最多允許最近本地通知數量是64個,超過限制的本地通知將被iOS忽略。
如果就寫個簡單的定時提醒,是很簡單的,比如這樣:
樣本寫的很簡單,啟動應用後,就發出一個定時通知,10秒後啟動。這時按Home鍵退出,一會兒就會提示的提示資訊。如果應用不退出則無效。
代碼如下:
UILocalNotification *notification=[[UILocalNotification alloc] init];
if (notification!=nil) {
NSLog(@">> support local notification");
NSDate *now=[NSDate new];
notification.fireDate=[now addTimeInterval:10];
notification.timeZone=[NSTimeZone defaultTimeZone];
notification.alertBody=@"該去吃晚飯了!";
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
更詳細的代碼見官方文檔:《Scheduling, Registering, and
Handling Notifications》,可以設定比如聲音,比如使用者定義資料等。
設定更多本地通知的資訊:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
/////////////
application.applicationIconBadgeNumber = 0;
// Add the view controller’s view to the window and display.
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
#pragma mark –
#pragma mark onChageValue
-(IBAction)onChangeValue:(id)sender
{
UISwitch *switch1=(UISwitch *)sender;
if (switch1.on) {
UILocalNotification *notification=[[UILocalNotification alloc] init];
NSDate *now1=[NSDate date];
notification.timeZone=[NSTimeZone defaultTimeZone];
notification.repeatInterval=NSDayCalendarUnit;
notification.applicationIconBadgeNumber = 1;
notification.alertAction = NSLocalizedString(@"顯示", nil);
switch (switch1.tag) {
case 0:
{
notification.fireDate=[now1 dateByAddingTimeInterval:10];
notification.alertBody=self.myLable1.text;
}
break;
case 1:
{
notification.fireDate=[now1 dateByAddingTimeInterval:20];
notification.alertBody=self.myLable2.text;
}
break;
case 2:
{
notification.fireDate=[now1 dateByAddingTimeInterval:30];
notification.alertBody=self.myLable3.text;
}
break;
default:
break;
}
[notification setSoundName:UILocalNotificationDefaultSoundName];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:@"%d",switch1.tag], @"key1", nil];
[notification setUserInfo:dict];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}else {
NSArray *myArray=[[UIApplication sharedApplication] scheduledLocalNotifications];
for (int i=0; i<[myArray count]; i++) {
UILocalNotification *myUILocalNotification=[myArray objectAtIndex:i];
if ([[[myUILocalNotification userInfo] objectForKey:@"key1"] intValue]==switch1.tag) {
[[UIApplication sharedApplication] cancelLocalNotification:myUILocalNotification];
}
}
}
}
遠程通知
遠程通知的原理:《偷窺iPhone Push Notification的幕後》和《iPhone的Push(推播通知)功能原理淺析》。
首先要知道,push notification只能在真機上啟動並執行,無法在模擬器上使用,如果在模擬器上運行,在註冊裝置的時候會有類似如下報錯:
Error in registration. Error: Error Domain=NSCocoaErrorDomain Code=3010 "remote notifications are not supported in the simulator" UserInfo=0x5d249d0 {NSLocalizedDescription=remote notifications are not supported in the simulator}
真機也要注意,如果沒有越獄,沒有問題。越獄的話,比如通過blacksnOw,因為沒有經過iTunes,無法產生有效裝置認證(device certificate),因此註冊的時候不會成功。
檢查越獄版本是否可用,可以ssh到裝置上,執行命令:
ls /var/mobile/Library/Preferences/com.apple.apsd.plist -l
-rw——- 1 mobile mobile 119 Aug 24 19:21 /var/mobile/Library/Preferences/com.apple.apsd.plist
返回的檔案大小是119,就沒有問題。
2.擷取device token的原理
在說操作步驟之前,先說一下擷取device token的一些原理方面的事情。
device token,即裝置令牌,不是系統唯一標識(見擷取iOS裝置的基本資料),需要在應用啟動時發起到apple伺服器請求,註冊自己的裝置和應用,並獲得這個device token。
device token有什麼用?如果應用需要push notification給手機,那麼它要有個伺服器端(provider),但是它發出的資訊不是直接給手機的,而是必須統一交給apple的伺服器,這個伺服器就是apple push notification server(apns)。apple伺服器通過這個token,知道應用要發的訊息是給哪個手機裝置的,並轉寄該訊息給手機,手機再通知應用程式。
3.擷取device token的操作步驟
這裡主要參照了這篇文章:Programming Apple Push Notification Services
該文檔很詳細,照做就應該沒有問題。
需要注意的是identifier一定要和provision portal profile中的app id一致,即:
要和
一致。
另外,要確保裝置綁定的是唯一的profile:
編寫代碼,是在AppDelegate中增加兩個方法:
- didRegisterForRemoteNotificationsWithDeviceToken:當應用第一次啟動並執行時候,ios擷取到device token後調用,用於註冊裝置到apns上之後的操作(比如將device token通知應用的伺服器端provider)
- didFailToRegisterForRemoteNotificationsWithError:如果註冊的時候失敗,ios會調用這個方法,可以列印一些報錯日誌或者提醒使用者通知不可用
另外,有一個方法需要增加內容,主要是列印日誌,說明是否已經註冊:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
NSLog(@"Initiating remoteNoticationssAreActive");
if(!application.enabledRemoteNotificationTypes){
NSLog(@"Initiating remoteNoticationssAreActive1");
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge)];
}
UIApplication* myapp = [UIApplication sharedApplication];
myapp.idleTimerDisabled = YES;
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
第一次運行帶註冊方法的應用,會看到類似這樣的提示視窗:
然後,在日誌中看到類似下面的日誌,主要是看到列印出device token的64位字串,就說明成功了。
5.獲得認證
蘋果提供兩種接入方式的認證:
- developer,用於測試
- production,用於產品
如果是自我裝載,使用developer方式即可。
下載認證,通過ios provisioning portal:
這要求:
- 登入的apple developer program帳號必須是層級最高的agent(這是針對企業帳號來說的,如果是個人帳號就無所謂了),agent帳號即創始帳號,否則看不到configure連結;
- 必須經過configure操作,已經enable了developer和product。
然後進入configure連結,點擊download按鈕即可:
6.處理認證
如果是編寫在mac下跑的objc程式,無需對認證做處理,可跳過這一步。
如果是在java下使用,需要把打認證用的私人專用密鑰和上述的支援通知的認證(注意,不是iphone developer認證)合并匯出。
http://stefan.hafeneger.name/download/PushMeBabySource.zip
如果是用java編寫,可以用第三方庫,見:
http://code.google.com/p/javapns/
編寫簡單的發送通知代碼:
import org.json.JSONException;
import javapns.back.PushNotificationManager;
import javapns.back.SSLConnectionHelper;
import javapns.data.Device;
import javapns.data.PayLoad;
public class Main {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
PayLoad simplePayLoad = new PayLoad();
// Get PushNotification Instance
PushNotificationManager pushManager = PushNotificationManager.getInstance();
// Link iPhone’s UDID (64-char device token) to a stringName
pushManager.addDevice("iPhone", "00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ");
simplePayLoad.addAlert("My alert message測試");
simplePayLoad.addBadge(1);
simplePayLoad.addSound("default");
Device client = PushNotificationManager.getInstance().getDevice("iPhone");
PushNotificationManager.getInstance().initializeConnection("gateway.sandbox.push.apple.com", 2195, "/home/ubuntu/mypush.p12", "password", SSLConnectionHelper.KEYSTORE_TYPE_PKCS12);
PushNotificationManager.getInstance().sendNotification(client, simplePayLoad);
測試中文沒有亂碼問題。
編寫比較複雜的使用樣本(可以控制通知是否有提示視窗、是否有提醒聲音):
- aPayload.addBadge( 2),顯示在手機應用表徵圖上的數字
- aPayload.addAlert("軟體版本有更新"),顯示提示視窗文字
- aPayload.addSound("default.wav"),指定提示聲音
另外,也可以使用php的第三方實現,比如:
http://code.google.com/p/php-apns
基本原理是啟動一個php服務,監控memcacheq隊列,如果有訊息就發送給蘋果伺服器。
from:http://wangjun.easymorse.com/?p=1482