本地通知,local notification,用于基于时间行为的通知,比如有关日历或者todo列表的小应用。作用是让它们的用户或得相关消息通知的方式。消息通知可能是一条消息,即将发生的日历时间,或远程服务器的新数据。也可以显示一个警告消息或在应用程序的图标上面现在一个徽标,也可以在警告窗或徽标显示时播放一段声音。另外,应用如果在后台执行,iOS允许它在受限的时间内运行,它也会发现本地通知有用。比如,一个应用,在后台运行,向应用的服务器端取信息,当消息到达时,通过本地通知机制通知用户。
本地通知:是本地iPhone、iPad、或iPod touch上面的应用发起的。
本地通知:应用程序需要创建一个UILocalNotification对象,并给它设置发送的时间和日期,指定细节,并调用它。
当操作系统发送一个本地通知(只有iOS支持),如果此时应用程序没有运行在前台,它将会显示通知(警告窗、图标徽标、声音)。如果显示一个通知警告窗并且用户轻击或单击动作按钮(或移动动作滑块),相应的应用程序将会加载启动并调用本地通知对象相应方法。如果通知到达的时候应用程序正运行在前台,应用程序的委托接受一个本地通知。
本地通知:由同一设备上面的应用自己调度和传递;只能在iOS上面可用。
在iOS上面,一个应用指定提示信息或徽标数字时也可以指定一个声音文件。该声音文件应该包含一个短的,有特色的声音。在iOS显示提示窗或图标上显示徽标的时候,它会播放该声音文件的声音来告知通知已经到达
通知提示消息可以只包含一个按钮。当动作按钮被取消,用户只隐藏该提示窗。
操作系统传递一个本地通知,无论应用的程序此时是否运行在前台。如果过在通知达到的时候应用程序正在运行,没有提示窗或图标徽标或声音播放,即使此时设备是锁屏的。相反,应用的委托会被告知该通知以便其直接处理该通知。
本地通知(仅在iOS上面支持)非常适合基于时间的行为,包括简单的日历事件或To-Do列表应用。本地通知对iOS允许的特定时间内运行后台的应用程序也非常有帮助。本地通知是UILocalNotification的一个实例,包含了3个通用的属性:
对于iOS上面的远程通知,你可以在显示某个应用的本地或远程通知时指定一个自定义的声音来播放。但是声音文件必须在客户端程序的主目录下面(即main bundle)。因为自定义的警告声音由iOS的声音系统设备播放,所以它必须是一下的任意格式的音频文件:
然后可以把音频文件打包为aiff、wav、或caf文件,在Xcode里边把声音文件添加到你的工程里面作为程序目录的一个并非本地化的资源。
注意:自定义的声音文件播放时必须在30秒以内。如果一个自定义的声音文件播放超过30秒的限制,那将会被系统的声音替换
在iOS上面创建和调度本地通知需要你完成下面几个简单的步骤:
注意:对于alertBody和alertAction属性,它从主目录的本地化字符串里面获取用户偏好语言的相应字符(通过NSLocalizadString)。它同时把任务列表的相关名词赋值到userInfo属性里面。
例1:
- (void)scheduleNotification{
//本地通知
/* * 本地推送,最多支持64个 * @param fireDate 本地推送触发的时间 * @param timeZone 本地推送的时区 * @param alertBody 本地推送需要显示的内容 * @param badge 角标的数字。如果不需要改变角标传-1 * @param alertAction 弹框的按钮显示的内容(IOS 8默认为"打开",其他默认为"启动") * @param soundName 自定义通知声音,设置为nil为默认声音 * @param userInfo 自定义参数,可以用来标识推送和增加附加信息 * @param notificationKey 本地推送标示符 * IOS8新参数 * @param region 自定义参数 * @param regionTriggersOnce 自定义参数 * @param category 自定义参数 */
UILocalNotification *newNotification = [[UILocalNotification alloc] init];
if (newNotification) {
//获取当前时区
NSTimeZone* zone = [NSTimeZone defaultTimeZone];
NSDate *date = [NSDate date];
//和格林尼治时间差
NSInteger timeOff = [zone secondsFromGMT];
//获取当前时间
NSDate *timeOffDate = [date dateByAddingTimeInterval:timeOff];
// NSLog(@"date = %@",timeOffDate);
//本地推送的时区
newNotification.timeZone = zone;
//本地推送触发的时间---10秒后
newNotification.fireDate=[timeOffDate dateByAddingTimeInterval:10];
//推送内容
newNotification.alertBody = @"信号报警";
//应用右上角红色图标数字
newNotification.applicationIconBadgeNumber = 1;
//弹框的按钮显示的内容(IOS 8默认为"打开",其他默认为"启动")
newNotification.alertAction = @"open";
//soundName 自定义通知声音,设置为nil为默认声音
newNotification.soundName = UILocalNotificationDefaultSoundName;
//add key 给这个通知增加key 便于半路取消。nfkey这个key是我自己随便起的。
// 假如你的通知不会在还没到时间的时候手动取消 那下面的两行代码你可以不用写了。
NSDictionary *dict =[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1],@"nfkey",nil];
newNotification.userInfo = dict;
//启动这个通知
[[UIApplication sharedApplication] scheduleLocalNotification:newNotification];
}
}
你可以通过调用程序的cancelLocalNotification:方法来取消一个指定的已经调度的通知,甚至你可以通过调用cancelAllLocalNotifications方法来取消所有已调度的通知。这两个方法都可以隐藏当前已经显示的通知警告窗口。
例如:
[[UIApplication sharedApplication] cancelLocalNotification:newNotification];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
实例2:
当应用程序运行在后台的时候,一些用户感兴趣的消息,数据,或其他项抵达时,此时本地通知就会非常有帮助。在这种情况下,他们应该通过使用UIApplication的方法presentLocalNotificationNow:来立即显示通知(iOS给定有限的时间让应用程序在后台执行)。此处有不懂的地方
- (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;
if (friend) {
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif) {
localNotif.alertBody = @"信号报警";
localNotif.alertAction = @"open";
localNotif.soundName = @"alarmsound.caf";
localNotif.applicationIconBadgeNumber = 1;
friend = nil;
break;
}
}
}
[application endBackgroundTask:self->bgTask];
self->bgTask = UIInvalidBackgroundTask;
});
}
iOS注意:应用的委托可以实现applicationDidFinishLaunching:方法,而不是application:didFinishLaunchingWithOptions: ,但是强烈不建议这样做。后一种方法允许应用程序接收和它启动相关的信息,这些信息不仅仅包括通知。
iOS注意:在iOS上,你可以通过确定应用程序的状态来确定是否是应用程序由于用户点击了动作按钮而启动,或通知被提交给已经运行的应用。通过委托实现application:didReceiveLocalNotification:方法,获取应用程序的applicationState属性值并判定它。如果值为UIApplicationStateInactive,表明用户单击了动作按钮。如果值为UIApplicationStateAction,表明应用收到此通知的时候已经运行在前台。
实例3:
iOS应用程序的委托了application:didFinishLaunchingWithOptions:方法来处理本地通知。它使用键UIApplicationLaunchOptionsLocalNotificationKey从加载选项里面的字典获取了一个相关的UILocalNotification对象。从UILocalNotification对象的userInfo字典里面。它获取任何项目(这是通知的目的),并使用它来设置程序的初始化上下文。在该实例中,作为通知的一部分,你应该正确地重置应用程序图标的数字,或者如果没有额外的任务时把它移除。
//声音播放
static SystemSoundID shake_sound_male_id = 0;
#pragma mark 播放声音
- (void)playSound{
NSString* sound = [[NSUserDefaults standardUserDefaults]objectForKey:@"sound"];
NSArray* soundArr = [sound componentsSeparatedByString:@"."];
NSString *path = [[NSBundle mainBundle] pathForResource:[soundArr objectAtIndex:0] ofType:[soundArr objectAtIndex:1]];
if (path) {
//注册声音到系统
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path],&shake_sound_male_id);
//播放注册的声音,(此句代码,可以在本类中的任意位置调用,不限于本方法中)
AudioServicesPlaySystemSound(shake_sound_male_id);
}
//让手机震动
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
//app在前台运行,通知时间到了,调用的方法
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
if (notification)
{
application.applicationIconBadgeNumber = 0;
application.applicationIconBadgeNumber = 1;
application.applicationIconBadgeNumber = 0;
UIApplicationState state = application.applicationState;
if (state == UIApplicationStateActive){
//当程序处于活跃状态时
[self playSound];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"时间提醒" message:notification.alertBody delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alert show];
}else if(state == UIApplicationStateInactive){
//程序运行在后台时,点击启动程序按钮时
NSLog(@"后台点击进入");
}
}
}
#pragma mark -UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
//停止播放声音
AudioServicesDisposeSystemSoundID(shake_sound_male_id);
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
application.applicationIconBadgeNumber = 1;
application.applicationIconBadgeNumber = 0;
}
iOS8拥有了全新的通知中心,有全新的通知机制。当屏幕顶部收到推送时只需要往下拉,就能看到快捷操作界面,并不需要进入该应用才能操作。在锁屏界面,对于推送项目也可以快速处理。基本上就是让用户尽量在不离开当前页面的前提下处理推送信息,再次提高处理效率。能够进行互动的短信、邮件、日历、提醒,第三方应用,可以让你不用进入程序就能进行快捷操作,并专注于手中正在做的事情。但这些的前提下,iOS8需要申请权限,注册通知。
实例4:
//ios8 注册本地通知
if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *noteSetting =[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:noteSetting];
}
实例6:
添加快捷回复按钮,首先需要注册行为
//接受按钮
UIMutableUserNotificationAction *acceptAction = [[UIMutableUserNotificationAction alloc] init];
acceptAction.identifier = @"acceptAction";//按钮的标示
acceptAction.title = @"接受";//按钮的标题
acceptAction.activationMode = UIUserNotificationActivationModeForeground;//当点击的时候启动程序
//拒绝按钮
UIMutableUserNotificationAction *rejectAction = [[UIMutableUserNotificationAction alloc] init];
rejectAction.identifier = @"rejectAction";
rejectAction.title = @"拒绝";
rejectAction.activationMode = UIUserNotificationActivationModeBackground;//当点击的时候不启动程序,在后台处理
rejectAction.authenticationRequired = YES;//需要解锁才能处理,如果action.activationMode = UIUserNotificationActivationModeForeground;则这个属性被忽略;
rejectAction.destructive = YES;
UIMutableUserNotificationCategory *categorys = [[UIMutableUserNotificationCategory alloc] init];
categorys.identifier = @"alert";//这组动作的唯一标示
[categorys setActions:@[acceptAction,rejectAction] forContext:(UIUserNotificationActionContextMinimal)];
UIUserNotificationSettings *uns = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound) categories:[NSSet setWithObjects:categorys,nil]];
[[UIApplication sharedApplication] registerUserNotificationSettings:noteSetting];
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:10];
notification.timeZone = [NSTimeZone defaultTimeZone];
notification.alertBody = @"测试推送的快捷回复";
notification.category = @"alert"; //同上创建类的动作的唯一标识符一样
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
//本地推送通知
-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
//成功注册registerUserNotificationSettings:后,回调的方法
NSLog(@"%@",notificationSettings);
}
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
//收到本地推送消息后调用的方法
NSLog(@"%@",notification);
}
-(void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler { //在非本App界面时收到本地消息,下拉消息会有快捷回复的按钮,点击按钮后调用的方法,根据identifier来判断点击的哪个按钮,notification为消息内容 NSLog(@"%@----%@",identifier,notification); completionHandler();//处理完消息,最后一定要调用这个代码块 }
// 获得 UIApplication
UIApplication *app = [UIApplication sharedApplication];
//获取本地推送数组
NSArray *localArray = [app scheduledLocalNotifications];
if (localArray) {
for (UILocalNotification *noti in localArray) {
NSDictionary *dict = noti.userInfo;
if (dict) {
NSString *inKey = [dict objectForKey:@"key"];
if ([inKey isEqualToString:@"sound"]) {
[[UIApplication sharedApplication]cancelLocalNotification:noti];
break;
}
}
}
}