iOS中的系統通知
iOS系統可支持本地通知和遠程通知,一個通知在客戶端收到的時候可能是一個通知窗體,可能會播放一段通知聲音,還有可能在程序圖標上增加一個數字,還有可能三者皆有。
本文描述ios系統中計劃local notification,注冊 remote notification,以及處理 local和remote notification的步驟。本文中客戶端API中notification推送指的就是remote notfication的推送
第一個知識點:準備個人定制音頻作為提示音,
請注意下面四個小問題-----
1,
系統能播放的四種音頻數據格式
Linear PCM
MA4 (IMA/ADPCM)
μLaw
aLaw
對應的后綴名可以是aiff, wav, or caf file. Then,
2, 可以用afconvert來轉換音頻,例如把16位的線性PCM系統音頻格式文件 Submarine.aiff 轉換成IMA4音頻,存為.CAF文件。
在終端執行即可
afconvert /System/Library/Sounds/Submarine.aiff ~/Desktop/sub.caf -d ima4 -f caff -v
3, 如何確定音頻格式呢。
打開QuickTime Player-> Movie menu->Show Movie Inspector
4, 個人定制音頻必須是30s以下。否則就播放默認的聲音了。
第二個知識點:預定一個Local Notification
需要了解下面5個步驟
1, Allocate 和 initialize 一個 UILocalNotification對象。
2, fireDate屬性賦值
3, 設置別的幾個體型要素 提示框,提示音,圖標上的提示數字。也可以帶別的個性化數據:通過userInfo帶出去。
4, 然后Schedule這個通知。通過UIApplication.scheduleLocalNotification來預定執行或者立馬執行presentLocalNotificationNow:
5, 也可以取消這個通知。用這個方法:cancelLocalNotification和cancelAllLocalNotifications這個方法
看下代碼
/
/如何創建設定一個Notification - (void)scheduleNotificationWithItem:(ToDoItem *)item interval:(int)minutesBefore { NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar]; NSDateComponents *dateComps = [[NSDateComponents alloc] init]; [dateComps setDay:item.day]; [dateComps setMonth:item.month]; [dateComps setYear:item.year]; [dateComps setHour:item.hour]; [dateComps setMinute:item.minute]; NSDate *itemDate = [calendar dateFromComponents:dateComps]; [dateComps release]; UILocalNotification *localNotif = [[UILocalNotification alloc] init]; if (localNotif == nil) return; localNotif.fireDate = [itemDate addTimeInterval:-(minutesBefore*60)]; localNotif.timeZone = [NSTimeZone defaultTimeZone]; localNotif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"%@ in %i minutes.", nil), item.eventName, minutesBefore]; localNotif.alertAction = NSLocalizedString(@"View Details", nil); localNotif.soundName = UILocalNotificationDefaultSoundName; localNotif.applicationIconBadgeNumber = 1; NSDictionary *infoDict = [NSDictionary dictionaryWithObject:item.eventName forKey:ToDoItemKey]; localNotif.userInfo = infoDict; [[UIApplication sharedApplication] scheduleLocalNotification:localNotif]; [localNotif release]; } //程序運行在后臺時候如何提交一個UILocalNotification。 - (void)applicationDidEnterBackground:(UIApplication *)application { NSLog(@"Application entered background state."); // bgTask is instance variable NSAssert(self->bgTask == UIInvalidBackgroundTask, nil); bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{ dispatch_async(dispatch_get_main_queue(), ^{ [application endBackgroundTask:self->bgTask]; self->bgTask = UIInvalidBackgroundTask; }); }]; dispatch_async(dispatch_get_main_queue(), ^{ while ([application backgroundTimeRemaining] > 1.0) { NSString *friend = [self checkForIncomingChat]; if (friend) { UILocalNotification *localNotif = [[UILocalNotification alloc] init]; if (localNotif) { localNotif.alertBody = [NSString stringWithFormat: NSLocalizedString(@"%@ has a message for you.", nil), friend]; localNotif.alertAction = NSLocalizedString(@"Read Message", nil); localNotif.soundName = @"alarmsound.caf"; localNotif.applicationIconBadgeNumber = 1; [application presentLocalNotificationNow:localNotif]; [localNotif release]; friend = nil; break; } } } [application endBackgroundTask:self->bgTask]; self->bgTask = UIInvalidBackgroundTask; }); }
第三個知識點:注冊 Remote Notifications
需要注冊Apple Push Notification service ,有三步
1,調用 registerForRemoteNotificationTypes:方法
2,通過實現application:didRegisterForRemoteNotificationsWithDeviceToken:這個delegate來接受從APNs傳過來的device token。這個token是個binary的值
3,程序啟動即需調用theregisterForRemoteNotificationTypes: 方法來注冊推送。后期可以調用enabledRemoteNotificationTypes這個方法來改通知類型。
需要注意的事情:
如果網絡不通,application:didRegisterForRemoteNotificationsWithDeviceToken這個方法和 application:didFailToRegisterForRemoteNotificationsWithError:都不會被調用哦。 Wifi的時候,通過5223端口鏈接APNs通常連不上喲因為網管把端口封掉了喲。
建議每次程序啟動的時候都調用registerForRemoteNotificationTypes來重新獲取設備相關的token,而不要緩存token.
這是因為,如果用戶重裝了iOS或者用戶換了設備并且恢復程序備份到一個新的設備,都將導致這個token值不一樣。
那通知就收不到了唄。
看下代碼:
Listing 2-3 Registering for remote notifications - (void)applicationDidFinishLaunching:(UIApplication *)app { // other setup tasks here.... [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)]; } // Delegation methods - (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken { const void *devTokenBytes = [devToken bytes]; self.registered = YES; [self sendProviderDeviceToken:devTokenBytes]; // custom method } - (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { NSLog(@"Error in registration. Error: %@", err); }
第四個知識點:處理 Local and Remote Notifications
一般通知來時,程序有兩種狀態。
1,后臺運行發送,需要窗體,聲音和數字
點擊窗體,啟動程序。程序啟動了在application:didFinishLaunchingWithOptions: 方法里面獲取傳遞的數據
notification payload (for remote notifications) or
local-notification object (for local notifications).
點擊圖標,啟動程序。同樣調用application:didFinishLaunchingWithOptions,但是傳參將不會有遠程消息的任何信息
2,程序在前臺跑著呢。
程序直接就調用application:didReceiveRemoteNotification: (for remote notifications)這個方法了
application:didReceiveLocalNotification: method (for local notifications)
總之要實現UIApplicationDelegate協議
實現application:didFinishLaunchingWithOptions:方法
實現application:didReceiveRemoteNotification:方法
或者實現application:didReceiveLocalNotification:方法
3,那如何判斷區別前臺還是后臺這兩種狀況呢。
用這個屬性applicationState來判斷。
若為UIApplicationStateInactive就是用戶點擊通知框按鈕進來的。
若為UIApplicationStateActive,就是前臺正跑著呢。
當iOS收到遠程消息時,
看下代碼
//Handling a local notification when an application is launched - (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey]; if (localNotif) { NSString *itemName = [localNotif.userInfo objectForKey:ToDoItemKey]; [viewController displayItem:itemName]; // custom method application.applicationIconBadgeNumber = localNotif.applicationIconBadgeNumber-1; } [window addSubview:viewController.view]; [window makeKeyAndVisible]; return YES; }
這里可以通過UIApplicationLaunchOptionsRemoteNotificationKey來獲取通知傳遞過來的自定義數據
之后即可從provider方下數據了。
- (void)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)opts { // check launchOptions for notification payload and custom data, set UI context [self startDownloadingDataFromProvider]; // custom method app.applicationIconBadgeNumber = 0; // other setup tasks here.... } Listing 2-6 Handling a local notification when an application is already running - (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif { NSString *itemName = [notif.userInfo objectForKey:ToDoItemKey] [viewController displayItem:itemName]; // custom method application.applicationIconBadgeNumber = notification.applicationIconBadgeNumber-1; }
本文為意譯,原文地址:https://developer.apple.com/library/ios/#documentation /NetworkingInternet/Conceptual/RemoteNotificationsPG/IPhoneOSClientImp/IPhoneOSClientImp.html#//apple_ref/doc/uid/TP40008194-CH103-SW1