iOS,推送通知

推送通知css

推送通知跟NSNotification有所区别: 
1> NSNotification是抽象的,不可见的 
2> 推送通知是可见的(能用肉眼看到)ios

iOS中提供了2种推送通知: 本地推送通知, 远程推送通知 
1> 本地推送通知(Local Notification) 
2> 远程推送通知(Remote Notification)数组

推送通知能够不让在前台运行的app,告知app内部发生了什么变化,好比:有新的内容,新消息等.服务器

推送通知的使用: 
发出推送通知时,若是当前程序正运行在前台,那么推送通知就不会被呈现出来 
点击推送通知后,默认会自动打开发出推送通知的app 
无论app打开仍是关闭,推送通知都能如期发出网络

推送通知有5种呈现效果: 
1. 在屏幕顶部显示一块横幅(显示具体内容) 
2. 在屏幕中间弹出一个UIAlertView(显示具体内容,使用较少) 
3. 在锁屏界面显示一块横幅(锁屏状态下,显示具体内容) 
4. 播放音效(提醒做用) 
5. 更新app图标的数字(说明新内容的数量)app

推送通知分为本地推送通知和远程推送通知,下面一一介绍.ide

本地推送通知测试

本地推送通知不须要服务器的支持,不须要联网就能够发送通知.一般本地推送通知用于定时提醒用户,好比清理垃圾,淘宝购物,记念日提醒等任务. 
在苹果官方给出了本地推送通知的一些属性,以及使用.fetch

属性介绍:ui

@property(nonatomic,copy) NSDate *fireDate; // 设置本地推送的时间 @property(nonatomic,copy) NSTimeZone *timeZone; // 时区(通常设置为[NSTimeZone defaultTimeZone] ,跟随手机的时区) @property(nonatomic) NSCalendarUnit repeatInterval; // 没隔多久重复发出一次 @property(nonatomic,copy) NSCalendar *repeatCalendar; // 设置日期 @property(nonatomic,copy) CLRegion *region NS_AVAILABLE_IOS(8_0); // 好比某一个区域的时候发出通知 @property(nonatomic,assign) BOOL regionTriggersOnce NS_AVAILABLE_IOS(8_0); // 进入区域是否重复 @property(nonatomic,copy) NSDictionary *userInfo; // 附加的额外信息 @property(nonatomic,copy) NSString *alertBody; // 消息的内容 @property(nonatomic) BOOL hasAction; // 是否显示alertAction的文字(默认是YES) @property(nonatomic,copy) NSString *alertAction; // 设置锁屏状态下,显示的一个文字 @property(nonatomic,copy) NSString *alertLaunchImage; // 启动图片 @property(nonatomic,copy) NSString *soundName; // UILocalNotificationDefaultSoundName @property(nonatomic) NSInteger applicationIconBadgeNumber; // 应用图标右上角的提醒数字 @property(nonatomic,copy) NSArray *scheduledLocalNotifications; // 得到被调度(定制)的全部本地推送通知(已经发出且过时的推送通知就算调度结束,会自动从这个数组中移除) 

 

使用方法:

建立本地通知

UILocalNotification *localNoti = [[UILocalNotification alloc] init];

 

调度本地推送通知(调度完毕后,推送通知会在特意时间fireDate发出)

取消调度本地推送通知[[UIApplication sharedApplication] scheduleLocalNotification:localNoti];

- (void)cancelLocalNotification:(UILocalNotification *)notification; - (void)cancelAllLocalNotifications;

 

  • 当即发出本地推送通知
- (void)presentLocalNotificationNow:(UILocalNotification *)notification;

 

注意: 
iOS8.0之后在本地推送通知上新加了一些新功能,为了用户体验,以及更加人性化,若是要使用本地通知,须要获得用户的许可. 
须要在AppDelegate中添加以下代码

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /* UIUserNotificationTypeNone = 0, 没有,没有本地通知 UIUserNotificationTypeBadge = 1 << 0, 接受图标右上角提醒数字 UIUserNotificationTypeSound = 1 << 1, 接受通知时候,能够发出音效 UIUserNotificationTypeAlert = 1 << 2, 接受提醒(横幅/弹窗) */ // iOS8须要添加请求用户的受权 if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) { UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil]; [application registerUserNotificationSettings:settings]; } }

 

 

点击本地推送通知 
当用户点击本地推送通知,会自动打开app,这里有2种状况

1> app并无关闭,一直隐藏在后台(运行在后台) 
让app进入前台,并会调用AppDelegate的下面方法(并不是从新启动app)

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;
  • 1
  • 1

2> app已经被关闭(进程已死) 
启动app,启动完毕会调用AppDelegate的下面方法

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

 

launchOptions参数经过UIApplicationLaunchOptionsLocalNotificationKey取出本地推送通知对象

若要实现界面的跳转,须要分清当前应用程序的所处状态,进行判断: 
1> 如果当前应用在后台运行,接收到通知时,要想进行界面的跳转,能够在didReceiveLocalNotification:方法中实现跳转界面的方法 
2> 如果当前的应用程序已经关闭,咱们在前面说到,当应用关闭,推送通知也会如期发送.但此时,是不会走didReceiveLocalNotification:方法的,那咱们只有didFinishLaunchingWithOptions:方法利用,launchOptions参数经过UIApplicationLaunchOptionsLocalNotificationKey取出本地推送通知对象,实现跳转的功能.

下面是演示代码:

#import "ViewController.h"#import "AppDelegate.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /* UIUserNotificationTypeNone = 0, 没有,没有本地通知 UIUserNotificationTypeBadge = 1 << 0, 接受图标右上角提醒数字 UIUserNotificationTypeSound = 1 << 1, 接受通知时候,能够发出音效 UIUserNotificationTypeAlert = 1 << 2, 接受提醒(横幅/弹窗) */ // iOS8须要添加请求用户的受权 if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) { UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil]; [application registerUserNotificationSettings:settings]; } if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) { // 跳转界面 } return YES; } /** * 若是应用在后台,经过点击通知的时候打开应用会来到该代理方法 * 若是应用在前台,接受到本地通知就会调用该方法 * * @param notification 经过哪个通知来这里 */ - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { if (application.applicationState == UIApplicationStateActive) return; if (application.applicationState == UIApplicationStateInactive) { // 实现跳转 } } - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { return YES; }



 @interface ViewController () // 点击按钮以后添加通知 - (IBAction)addLocalNote; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; } - (IBAction)addLocalNote { // 1.建立本地通知 UILocalNotification *localNote = [[UILocalNotification alloc] init]; // 设置什么时间弹出 localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5]; // 设置弹出的内容 localNote.alertBody = @"您有新消息"; // 设置锁屏状态下,显示的一个文字 localNote.alertAction = @"快点打开"; // 是否显示alertAction的文字(默认是YES) localNote.hasAction = YES; // 设置音效 localNote.soundName = UILocalNotificationDefaultSoundName; // 应用图标右上角的提醒数字 localNote.applicationIconBadgeNumber = 1; // 设置UserInfo来传递信息 localNote.userInfo = @{@"alertBody" : localNote.alertBody, @"applicationIconBadgeNumber" : @(localNote.applicationIconBadgeNumber)}; // 2.调度通知 [[UIApplication sharedApplication] scheduleLocalNotification:localNote]; }

 

远程推送通知

远程推送通知:就是经过网络从远程服务器推送给客户端的通知.

为何须要远程推送通知? 
传统获取数据的局限性 
只要用户关闭了app,就没法跟app的服务器沟通,没法从服务器上得到最新的数据内容

远程推送通知能够解决以上问题 
无论用户打开仍是关闭app,只要联网了,都能接收到服务器推送的远程通知

远程推送通知的使用 
全部的苹果设备,在联网状态下,都会与苹果的服务器创建长链接 
长链接: 只要联网了,就一直创建链接

长链接的做用: 时间校准, 系统升级, 查找个人iPhone

长链接的好处 : 数据传输速度快 , 数据保持最新状态

远程推送功能机制

苹果给iOS和Mac添加了消息推送的功能,使得咱们能够经过后台服务器给应用程序(APP)发送消息,无论APP是否正在使用,好比邮箱的来件提示功能。这项服务被称为Apple Push Notification service(APNs)。里面一共涉及到四个角色:APP、设备、APNs和应用后台服务器(Provider),其中APP、后台服务器和APNs之间使用deviceToken惟一的标识一个用户。 
这里写图片描述

推送服务的工做流程:

APP向系统注册推送服务。
设备从APNs请求deviceToken。
经过代理方法将deviceToken返回给APP。
APP将deviceToken发送给应用后台服务器(Provider)。
应用后台服务器保存deviceToken,而后在须要推送通知的时候,给APNs发送信息,使用deviceToken标识所要送达的客户端。
APNs将后台服务器发过来的数据推送到设备。
设备将消息分发给应用程序。

在使用推送功能的时候,须要在开发者中心建立支持Push Notification的证书,而且将证书和私钥用于应用后台服务器与APNs之间通讯。

我也写了一个比较易懂的远程推送流程图! http://blog.csdn.net/ismilesky/article/details/48324723

远程推送近年来,都是经过第三方进行实现,由于第三方推送的功能比较强大. 
推送平台: 百度推送 , 极光推送, 腾讯信鸽推送, 个推 
远程推送咱们这里以极光推送(第三方)为例,进行测试.

极光远程推送的使用

如要使用极光第三方远程推送,咱们须要集成iOS SDK,须要进行应用的配置,和环境配置.在开发者中心有 
developer.apple.com开发者帐号 , iOS真机(iPhone、iPad、iPod)等。

远程推送应用配置过程:

  1. 建立支持远程推送功能的App ID
  2. 申请开发者证书,并选中刚刚建立的App ID
  3. 下载CER文件,并导入钥匙串管理
  4. 申请发布证书,并选中刚刚建立的App ID
  5. 下载CER文件,并导入钥匙串管理
  6. 检查App ID,确认证书已经指定

这些相关配置极光推送已经给了很是详细的文档资料, iOS SDK集成指南 :http://docs.jpush.io/guideline/ios_guide/ , iOS SDK调试指南 :http://docs.jpush.io/client/ios_tutorials/#ios-sdk, 只须要按照流程进行就能够.

实现代码:

测试时,运行完应用程序,要发送通知,进行推送的测试,真机收到通知才算成功. #define kDeviceVersion ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) #import "AppDelegate.h" #import "APService.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. #if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1 if (kDeviceVersion) { //能够添加自定义categories [APService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound |UIUserNotificationTypeAlert) categories:nil]; } else { //categories 必须为nil [APService registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert) categories:nil]; } #else //categories 必须为nil [APService registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert) categories:nil]; #endif [APService setupWithOption:launchOptions]; return YES; } #pragma mark - 获取device token (必须实现) // 当获得苹果的APNs服务器返回的DeviceToken就会被调用 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSLog(@"%@",deviceToken); // Required [APService registerDeviceToken:deviceToken]; } #pragma mark - 获取device token失败 - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { NSLog(@"function == %s line == %d error == %@",__FUNCTION__,__LINE__,error); } // 接收到远程通知,触发方法和本地通知一致 (必须实现) - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { // Required [APService handleRemoteNotification:userInfo]; } #pragma mark - 使用后台的远程消息推送 (必须实现) /** 1> 在Capabilities中打开远程推送通知 2> 实现该代理方法 远程消息数据格式: {"aps" : {"content-available" : 1},"content-id" : 42} 执行completionHandler有两个目的 1> 系统会估量App消耗的电量,并根据传递的UIBackgroundFetchResult 参数记录新数据是否可用 2> 调用完成的处理代码时,应用的界面缩略图会自动更新 注意:接收到远程通知到执行完网络请求之间的时间不能超过30秒 if (userInfo) { int contentId = [userInfo[@"content-id"] intValue]; ViewController *vc = (ViewController *)application.keyWindow.rootViewController; [vc loadDataWithContentID:contentId completion:^(NSArray *dataList) { vc.dataList = dataList; NSLog(@"刷新数据结束"); completionHandler(UIBackgroundFetchResultNewData); }]; } else { completionHandler(UIBackgroundFetchResultNoData); } */ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // IOS 7 Support Required [APService handleRemoteNotification:userInfo]; [[UIApplication sharedApplication]setApplicationIconBadgeNumber:0]; // 判断应用程序在前台仍是后台 if (application.applicationState == UIApplicationStateActive) { // 活跃状态 // 实现方法 } else if (application.applicationState == UIApplicationStateInactive) { // 不活跃状态 // 实现方法 } else { // application.applicationState == UIApplicationStateBackground // 后台 // 实现方法 } /** 必须回调 */ completionHandler(UIBackgroundFetchResultNewData); }

这里写图片描述

相关文章
相关标签/搜索