举一个常见的例子,咱们的手机上常常会有弹出一些信息,例如QQ信息、微信信息等等,这就是常见的消息推送。android
例如:ios
这是咱们常见的推送消息的样式,咱们能够在手机上自定义接收的消息如何展现。git
在一些软件中,若是用户不当心关闭了咱们的推送服务,咱们也能够这样提示用户怎么打开容许接收推送服务(iOS8之后)。github
注意:数组
发出推送通知时,若是当前程序正运行在前台,那么推送通知就不会被呈现出来服务器
点击推送通知后,默认会自动打开发出推送通知的app微信
无论app打开仍是关闭,推送通知都能如期发出网络
消息推送和日常的从服务器获取数据有什么不一样?app
主动向服务器
发送消息,而后服务器才会给咱们发送咱们须要的信息;而消息推送是当咱们不在聊天状态下,甚至是连QQ软件都没有打开的状况下,服务器主动向咱们
发送消息,告诉咱们一些信息。固然了,消息推送和通知(NSNotification)可不同,虽然它们的使用类名看起来有点类似。iphone
在iOS中,推送分为本地推送和远程推送,本地推送不须要网络(不须要服务器的支持),常见的应用场景例如:
事件提醒类的软件,到了咱们自定义的时间,就会弹出一些信息告诉咱们该干什么了。
记帐类软件,会提醒咱们的一些花销等等。
咱们先来学习一下本地推送
UILocalNotification *ln = [[UILocalNotification alloc] init];
//推送通知的触发时间(什么时候发出推送通知) @property(nonatomic,copy) NSDate *fireDate; //推送通知的具体内容 @property(nonatomic,copy) NSString *alertBody; //在锁屏时显示的动做标题(完整标题:“滑动来” + alertAction) @property(nonatomic,copy) NSString *alertAction; //音效文件名 @property(nonatomic,copy) NSString *soundName; //app图标数字 @property(nonatomic) NSInteger applicationIconBadgeNumber; //每隔多久重复发一次推送通知 @property(nonatomic) NSCalendarUnit repeatInterval; //点击推送通知打开app时显示的启动图片 @property(nonatomic,copy) NSString *alertLaunchImage; //附加的额外信息 @property(nonatomic,copy) NSDictionary *userInfo; //时区 @property(nonatomic,copy) NSTimeZone *timeZone; (通常设置为[NSTimeZone defaultTimeZone] ,跟随手机的时区) //调度本地推送通知(调度完毕后,推送通知会在特意时间fireDate发出) [[UIApplication sharedApplication] scheduleLocalNotification:ln]; //得到被调度(定制)的全部本地推送通知 @property(nonatomic,copy) NSArray *scheduledLocalNotifications; (已经发出且过时的推送通知就算调度结束,会自动从这个数组中移除) //取消调度本地推送通知 - (void)cancelLocalNotification:(UILocalNotification *)notification; - (void)cancelAllLocalNotifications; //当即发出本地推送通知 - (void)presentLocalNotificationNow:(UILocalNotification *)notification;
//当用户点击本地推送通知,会自动打开app,这里有2种状况 //app并无关闭,一直隐藏在后台 //让app进入前台,并会调用AppDelegate的下面方法(并不是从新启动app) - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification; //app已经被关闭(进程已死) //启动app,启动完毕会调用AppDelegate的下面方法 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions; //launchOptions参数经过UIApplicationLaunchOptionsLocalNotificationKey取出本地推送通知对象 //当点击通知进入app时,launchOptions参数才会有值,当正常启动app时,launchOptions为null
注意:
在iOS 8.0中,若是要使用本地通知,须要获得用户的许可
在didFinishLaunchingWithOptions方法中添加以下代码:
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil]; [application registerUserNotificationSettings:settings];
实例:
//在须要的地方注册本地消息推送 // 1.建立本地通知 UILocalNotification *localNote = [[UILocalNotification alloc] init]; // 2.设置本地通知的信息 // 2.1.设置提示信息 localNote.alertBody = @"吃饭了吗?"; // 2.2.设置通知弹出的时间 localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0]; // 2.3.设置滑块显示的文字 localNote.alertAction = @"快点"; // 2.4.是否让上面的文字生效 localNote.hasAction = NO; // 2.5.设置通知中心的标题 localNote.alertTitle = @"你大哥"; // 2.6.设置通知的声音 localNote.soundName = @"buyao.wav"; // 2.7.设置应用程序图标右上角的数字 localNote.applicationIconBadgeNumber = 10; // 3.调度通知 //调度前要先把原来的通知取消 UIApplication *app = [UIApplication sharedApplication]; [app cancelAllLocalNotifications]; [app scheduleLocalNotification:localNote];
在appdelegate类中实现相应的跳转方法
#import "AppDelegate.h" #define IS_iOS8 ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /* UIUserNotificationTypeNone = 0, 不发出通知 UIUserNotificationTypeBadge = 1 << 0, 改变应用程序图标右上角的数字 UIUserNotificationTypeSound = 1 << 1, 播放音效 UIUserNotificationTypeAlert = 1 << 2, 是否运行显示横幅 */ [application setApplicationIconBadgeNumber:0]; if (IS_iOS8) { UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil]; [application registerUserNotificationSettings:settings]; } // 若是是正常启动应用程序,那么launchOptions参数是null // 若是是经过其余方式启动应用程序,那么launchOptions就有值,里面存储的是通知的内容 if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) { // 当被杀死状态收到本地通知时执行的跳转代码 [self jumpToSession]; } return YES; } //程序没有关闭时,点击通知进入app才会调用,若是将程序彻底退出,点击通知进入app时只会调用上面的方法,不会调用这个方法 - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { // 在这里写跳转代码 // 若是是应用程序在前台,依然会收到通知,可是收到通知以后不该该跳转 if (application.applicationState == UIApplicationStateActive) return; if (application.applicationState == UIApplicationStateInactive) { // 当应用在后台收到本地通知时执行的跳转代码 [self jumpToSession]; } } - (void)jumpToSession { UILabel *redView = [[UILabel alloc] init]; redView.backgroundColor = [UIColor redColor]; redView.frame = CGRectMake(0, 100, 300, 400); redView.numberOfLines = 0; // redView.text = [NSString stringWithFormat:@"%@", launchOptions]; [self.window.rootViewController.view addSubview:redView]; } @end
先介绍一下iOS中远程推送的原理:
咱们先要明确一点,全部的iOS设备收到的远程推送消息都是经过苹果的服务器发出来的。咱们本身公司的服务器或者第三方的推送服务器都是将要发送给咱们的推送消息先推给苹果的服务器,而后再由苹果的服务器发送给咱们。
以下图:
因此,咱们的苹果设备在联网的状况下,都会默认和苹果的服务器保持一个长链接(这里不解释长链接的概念,你能够理解成是有一条线一直在二者之间联系着,为了保持服务器不断开和咱们设备的联系,咱们的设备默认每隔一段时间会向服务器发送心跳包(一个很小的文件),来告诉苹果服务器不要和咱们的设备断开链接)。
下面详细解释一下iOS中的远程推送原理
上图中1-8的步骤就能够很好的解释远程推送的过程了,而客户端须要作的只有几个步骤:
1:发送设备的UDID和
应用的Bundle Identifier
给APNs服务器
2:经苹果加密生成一个
deviceToken
3:发送当前用户的deviceToken
和用户的标志(好比id或者qq)到本身公司的服务器或者第三方推送服务器
4:监听通知的点击事件
其他的步骤由服务器端实现:
4:本身的服务器或者第三方推送服务器将客户端发送过来的用户信息保存在本身的服务器中
5:有人发送消息的时候,从服务器中(根据deviceToken)查询要发给谁
6:查询到要发送给某人之后,将信息发送给苹果服务器
7:苹果服务器根据获得的deviceToken和信息,查到要接受信息的设备和app,将信息发送给用户。
1.真机
2.调试推送须要的证书文件
1> aps_development.cer : 某台电脑就能调试某个app的推送服务
2> iphone5_qq.mobileprovision : 某台电脑就能利用某台设备调试某个程序
三.发布具备推送服务的app,须要的证书文件
1> aps_production.cer : 若是发布的程序中包含了推送服务,就必须安装这个证书
2> qq.mobileprovision : 某台电脑就能发布某个程序
下面就开始真正的使用一下远程推送功能吧。
证书配置01 – 建立App ID
配置明确的App ID
大概步骤以下:
先选择明确的App ID
配置远程推送的调试证书
配置远程推送的发布证书(使用第二种方法配置)
新建项目,将Bundle ID改为和上面配置的成相同名字。
若是仍是不行,检查这里
将配置好的证书下载后安装。
接下来就能够开始处理远程推送的消息了:
注意:
在iOS7和iOS8中的注册方法不同
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 请求获取DeviceToken if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { // 1.获取发送通知的权限 UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]; [application registerUserNotificationSettings:settings]; // 2.注册远程通知 [application registerForRemoteNotifications]; } else { [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound]; } return YES; } //获取到deviceToken - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSLog(@"%@", deviceToken); }
这里有两个方法,注意二者的区别,更具须要调用
//这个方法能够处理当用户点击消息进入前台作一些操做 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { NSLog(@"%@", userInfo); }
//这个方法能够实如今用户手机收到消息就能够在后台进行一些操做,例如更新UI //不过,这个方法要先设置后台模式,方法以下: /* 1.开启后台模式 2.调用completionHandler,告诉系统你如今是否有新的数据更新 3.userInfo添加一个字段:"content-available" : "1" : 只要添加了该字段,接受到通知都会在后台运行 */ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { UIView *redView = [[UIView alloc] init]; redView.frame = CGRectMake(100, 100, 100, 100); redView.backgroundColor = [UIColor redColor]; [self.window.rootViewController.view addSubview:redView]; completionHandler(UIBackgroundFetchResultFailed); }
添加后台模式方法:
下面介绍一种测试远程通知的工具PushMeBaby
使用步骤:
填写必要信息
deviceToken:用于找到设备的令牌
payload:推送的内容
什么是JPush
一套远程推送解决方案,支持android和iOS两个平台
它可以快捷地为iOS App增长推送功能,减小集成APNs须要的工做量、开发复杂度
更多的信息,能够参考JPush官方网站:https://www.jpush.cn
集成iOS SDK的步骤能够参考 http://docs.jpush.cn/pages/viewpage.action?pageId=2621727