前言
之前接触过iOS上的推送服务,当时做的是在线推送,虽然已经有很多开发商提供集成的推送服务,但作为了解原理的方式也是一个不错的过程。
最近打算应用本地通推送的功能,本来以为会和在线推送一样麻烦,又要弄证书,又要提交验证,所以一直没动手。今天稍微了解后,发现本地推送就是很简单的一件事。
介绍
本地推送是什么
在线推送一般是通过服务器发送消息到对应设备,并由对应设备做出响应通知用户。而本地推送则是直接在本地由程序控制发送消息通知用户。由于减少了服务器以及验证设备的过程,所以本地推送其实就是一个简单的通知服务。
本地推送能做什么
GTD应用一般需要根据设定在规定时间通知用户完成某个任务。GTD的事务在本地基本都有备份,也当然是通过本地来通知用户何时应用完成任务。在这里,本地推送服务的作用就突显出来了。
某些游戏,比如升级建筑装备等,一般都需要时间去完成,玩家不可能在游戏前一直等待。当升级结束,游戏在本地把通知推送给玩家,玩家响应并再次进入游戏,不仅节约玩家的时间,也给游戏的激活带来更多的流量。
虽然本地推送不如在线推送的使用频率那么高,但还是很有用途的。
如何实现本地推送
添加通知
本地推送的实现很简单,更多的是自定义的过程。来看看下面的代码:
UILocalNotification *notification = [[UILocalNotification alloc] init]; // ARC环境 notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:3]; // 推送时间 notification.timeZone = [NSTimeZone defaultTimeZone]; notification.repeatInterval = 0; // 推送间隔 notification.soundName = UILocalNotificationDefaultSoundName; // 推送声音 notification.alertBody = @"Push Notification"; // 推送内容 notification.applicationIconBadgeNumber = 1; // 消息个数 notification.userInfo = [NSDictionary dictionaryWithObject:@"value" forKey:@"key"]; [[UIApplication sharedApplication] scheduleLocalNotification:notification];
实例化一个`UILocalNotification`对象,并根据具体的要求设置这个对象的属性。
`fireDate`表示推送的时间。`timeZone`是对应的时区。
`repeatInterval`表示推送的重复间隔,它的类型是`NSCalendarUnit`,可以用这个枚举值来赋值,表示每天、每周或每月等。如果为0则表示不重复推送。
`soundName`是推送的声音,可以写上bundle资源里已有的音乐文件名称,这样就可以自定义推送的声音了。
`alertBody`是推送的内容。
`applicationIconBadgeNumber`表示显示在该应用图标上的消息个数。在接受消息后需要把这个属性重置。
`userInfo`可以存放通知的相关信息。
最后,通过调用`scheduleLocalNotification`达到推送通知的目的。
接收通知
接收推送通知更加容易,在`AppDelegate`的`didReceiveLocalNotification`方法中就可以接收了。
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification*)notification { NSLog(@"Notification : %@", notification.alertBody); // 输出推送信息 application.applicationIconBadgeNumber = 0; // 消息数置为0 }
上面在`didReceiveLocalNotification`方法中打印出了推送消息的内容,并把消息数置为0。当然也可以通过判断`notification`的具体信息显示弹窗、修改消息数等。
取消通知
NSArray *array = [[UIApplication sharedApplication] scheduledLocalNotifications]; // 获取本地推送数组 [[UIApplication sharedApplication] cancelLocalNotification:notification]; // 取消某个推送 [[UIApplication sharedApplication] cancelAllLocalNotifications]; // 取消所有推送
上面这段代码展示了几个API,但其中没有必然的调用关系。
`scheduledLocalNotifications`可以获取本地的推送数组,其中的每个成员都是UILocalNotification,可以根据它们的userInfo区分推送的类型。
`cancelLocalNotification`可以取消某个具体的推送通知。比如取消通过`scheduledLocalNotifications`获取的某个通知。
`cancelAllLocalNotifications`则可以一次性取消所有的通知。
本地推送会有哪些坑
iOS8
在iOS8之后,要使用本地推送都需要为本地注册通知类型,否则无法接收到通知。具体的做法是在`AppDelegate`的`didFinishLaunchingWithOptions`中注册。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]]; return YES; }
音乐
推送通知可以自定义音乐,但并不是所有音乐都可以调用。目前只支持30秒的音乐,因为推送最多只能维持30秒。
声音
如果手机置为静音,则音乐无法播放。
如果在手机打开的时候显示通知,也不会播放音乐,甚至也不会震动。
applicationIconBadgeNumber
如果是从通知栏点击通知进入应用,会响应通知的回调,同时在回调中奖消息数置为0。
而如果是在有消息的情况下直接打开应用,并不会走通知回调的流程。
可以根据需要接入这部分逻辑。
总结
本地通知的处理还是比较简单的。
闹钟的实现原理也是利用了本地通知,但是如果要考虑震动等问题,则会更加复杂。有需要再慢慢研究。