推送通知(一)-iOS<10的推送通知
简介
- 推送通知跟NSNotification区别
- NSNotification是抽象的,不可见的
- 推送通知是可见的(能用肉眼看到)
- iOS中提供了2种推送通知
- 本地推送通知(Local Notification)
- 远程推送通知(Remote Notification)
- 推送通知的作用
- 可以让不在前台运行的app,告知用户app内部发生了什么事情
- 推送通知的呈现效果
- 在屏幕顶部显示一块横幅(显示具体内容)
- 在屏幕中间弹出一个UIAlertView(显示具体内容)
- 在锁屏界面显示一块横幅(锁屏状态下,显示具体内容)
- 更新app图标的数字(说明新内容的数量)
- 播放音效(提醒作用)
- 推送通知呈现的效果设置.
- 显示横幅还是UIAlertView,取决于用户的设置
- 手机->设置->通知中心-> 相应应用-> 选择通知样式.
- 在该界面,用户也可以决定是否要开启以下4个功能:
- 显示App图标数字
- 播放音效
- 锁屏显示
- 显示在“通知中心”
- 推送通知的使用细节
- 发出推送通知时,如果程序正运行在前台,那么推送通知就不会被呈现出来
- 点击推送通知后,默认会自动打开发出推送通知的app
- 不管app打开还是关闭,推送通知都能如期发出
本地推送通知
- 定义:
- 顾名思义,就是不需要联网就能发出的推送通知(不需要服务器的支持)
- 本地推送通知的使用场景
- 常用来定时提醒用户完成一些任务,比如:清理垃圾、记账、买衣服、看电影、玩游戏
如何发送本地通知
-
创建本地推送通知对象
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;
-
-
调度本地推送通知(调度完毕后,推送通知会在特地时间fireDate发出)
[[UIApplication sharedApplication] scheduleLocalNotification:ln];
- 获得被调度的所有本地推送通知(等待发出的通知)
- (已经发出且过期的推送通知就算调度结束,会自动从这个数组中移除)
@property(nonatomic,copy) NSArray *scheduledLocalNotifications;
-
取消调度本地推送通知
- (void)cancelLocalNotification:(UILocalNotification *)notification; - (void)cancelAllLocalNotifications;
-
立即发出本地推送通知(使用价值:app在后台运行的时候)
- (void)presentLocalNotificationNow:(UILocalNotification *)notification;
本地推送通知的其他属性
-
每隔多久重复发一次推送通知
@property(nonatomic) NSCalendarUnit repeatInterval;
- 点击推送通知打开app时显示的启动图片
- 注意: 该字符串无论写什么,都会显示app最初设置的那个启动图片
- 使用场景: 当程序是杀死状态时,点击通知打开app时,默认会看到启动图片,但是当程序在后台时,点击时看不到启动图片的,因此为了让用户也看到启动图片,就可以设置这个属性
@property(nonatomic,copy) NSString *alertLaunchImage;
-
附加的额外信息
@property(nonatomic,copy) NSDictionary *userInfo;
-
时区
@property(nonatomic,copy) NSTimeZone *timeZone; (一般设置为[NSTimeZone defaultTimeZone] ,跟随手机的时区)
点击本地推送通知
- 当用户点击本地推送通知,会自动打开app,这里有2种情况
- app并没有关闭,一直隐藏在后台
-
让app进入前台,并会调用AppDelegate的下面方法(并非重新启动app)
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;
-
方法说明:
- 应用程序从前台或者后台进入都会调用该方法
-
- app已经被关闭(进程已死)
-
启动app,启动完毕会调用AppDelegate的下面方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
-
该方法说明:
launchOptions
参数:- 点击本地/远程/URL(应用间跳转)等通知时,当程序在后台或者在前台进入时,该值都为null,但是程序由杀死状态进入时,有值,该值就是发出的通知
launchOptions
常用的keyUIApplicationLaunchOptionsLocalNotificationKey
:- 通过本地通知把我打开,该值就是本地通知的值
UIApplicationLaunchOptionsRemoteNotificationKey
:- 远程通知
UIApplicationLaunchOptionsURLKey
:- URL应用建跳转
-
- 当拿到本地通知时,通常作如下处理:
- 根据当前app进入的不同状态,进行不同的处理
application.applicationState
key值获取进入状态:- UIApplicationStateActive : 应用程序在前台
- UIApplicationStateInactive: 应用程序由后台进入前台
- UIApplicationStateBackground: 应用程序在后台
iOS8的配置
- 在iOS8.0以后,如果要使用本地通知需要得到用户的许可
-
具体操作,在
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
方法中加入以下代码://判断iOS版本,iOS8.0以上版本需要的到用户的许可 if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert |UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil]; [application registerUserNotificationSettings:settings]; }
代码举例:
-
控制器中发送通知(延时5秒)
#import "ViewController.h" @interface ViewController () @property (nonatomic,assign) NSInteger number; @end @implementation ViewController //延迟5秒发送本地通知 - (IBAction)locationNotificationAction:(id)sender { //1.创建本地通知 UILocalNotification * localNote = [[UILocalNotification alloc] init]; //2.设置本地通知内容 //2.1设置通知发出的时间 localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0]; //2.2 设置通知的内容 localNote.alertBody = @"吃饭了吗???"; //2.3 设置滑块的文字 localNote.alertAction = @"快点"; //2.4 决定alertAction是否生效 localNote.hasAction = YES; //2.5 设置点击通知的启动图片(随便写) localNote.alertLaunchImage = @"随便写"; //2.6 设置alertTitle localNote.alertTitle = @"777777777777"; //2.7 设置有通知时的音效 // localNote.soundName = @"buyao.wav"; //也可以用系统自带的 localNote.soundName = UILocalNotificationDefaultSoundName; //2.8 设置应用程序图标右上角的数字 localNote.applicationIconBadgeNumber = self.number++; //2.9 设置额外信息(比如:告诉app点击通知时跳转到哪一个界面) localNote.userInfo = @{@"type" : @1 }; //3.调用本地通知 [[UIApplication sharedApplication] scheduleLocalNotification:localNote]; } @end#import "ViewController.h" @interface ViewController () @property (nonatomic,assign) NSInteger number; @end @implementation ViewController //延迟5秒发送本地通知 - (IBAction)locationNotificationAction:(id)sender { //1.创建本地通知 UILocalNotification * localNote = [[UILocalNotification alloc] init]; //2.设置本地通知内容 //2.1设置通知发出的时间 localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0]; //2.2 设置通知的内容 localNote.alertBody = @"吃饭了吗???"; //2.3 设置滑块的文字 localNote.alertAction = @"快点"; //2.4 决定alertAction是否生效 localNote.hasAction = YES; //2.5 设置点击通知的启动图片(随便写) localNote.alertLaunchImage = @"随便写"; //2.6 设置alertTitle localNote.alertTitle = @"777777777777"; //2.7 设置有通知时的音效 // localNote.soundName = @"buyao.wav"; //也可以用系统自带的 localNote.soundName = UILocalNotificationDefaultSoundName; //2.8 设置应用程序图标右上角的数字 localNote.applicationIconBadgeNumber = self.number++; //2.9 设置额外信息(比如:告诉app点击通知时跳转到哪一个界面) localNote.userInfo = @{@"type" : @1 }; //3.调用本地通知 [[UIApplication sharedApplication] scheduleLocalNotification:localNote]; } @end
-
AppDelegate配置/处理
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //设置程序右上角的数字 [application setApplicationIconBadgeNumber:0]; //判断iOS版本,iOS8.0以上版本需要的到用户的许可 if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert |UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil]; [application registerUserNotificationSettings:settings]; } //launchOptions 点击本地/远程/URL(应用间跳转)等通知时,当程序在后台或者在前台进入时,该值都为null,但是程序又杀死状态进入时,有值,该值就是发出的通知 //launchOptions 常用的key // UIApplicationLaunchOptionsLocalNotificationKey,通过本地通知把我打开,该值就是本地通知的值 // UIApplicationLaunchOptionsRemoteNotificationKey,远程通知 // UIApplicationLaunchOptionsURLKey ,URL应用建跳转 if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) { //获得本地通知 UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]; // NSNumber *type = notification.userInfo[@"type"]; //有type可以判断跳转到哪一个界面 UILabel *redView = [[UILabel alloc] init]; redView.frame = CGRectMake(0, 0, 200, 300); redView.numberOfLines = 0; redView.font = [UIFont systemFontOfSize:12.0]; redView.backgroundColor = [UIColor redColor]; redView.text = [NSString stringWithFormat:@"%@",notification]; [self.window.rootViewController.view addSubview:redView]; } return YES; } //应用程序从前台或者后台进入都会调用该方法 -(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{ //针对应用程序在后台的时候进行跳转 //UIApplicationStateActive,应用程序在前台 // UIApplicationStateInactive,应用程序由后台进入前台 // UIApplicationStateBackground应用程序在后台 if (application.applicationState == UIApplicationStateInactive) { //进行界面的跳转:跳转到指定的界面 //通知的额外信息可以再这里获得 UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; redView.backgroundColor = [UIColor redColor]; [self.window.rootViewController.view addSubview:redView]; } }
远程推送通知
- 定义:
- 就是从远程服务器推送给客户端的通知(需要联网)
- 远程推送服务,又称为APNs(Apple Push Notification Services)
- 与本地的区别
- 本地推送通知是app自己给自己发送的.
- 远程是由服务器发送过来的.
- 为什么需要远程推送通知?
- 传统获取数据的局限性
- 只要用户关闭了app,就无法跟app的服务器沟通,无法从服务器上获得最新的数据内容
- 远程推送通知可以解决以上问题
- 不管用户打开还是关闭app,只要联网了,都能接收到服务器推送的远程通知
- 传统获取数据的局限性
- 所有的苹果设备,在联网状态下,都会与苹果的服务器建立长连接
- 什么是长连接
- 只要联网了,就一直建立连接
- 长连接的作用
- 时间校准:(保证手机时间是最准的)
- 系统升级:(提示用户系统升级)
- 查找我的iPhone(iPhone丢了,可以通过苹果官网查找出来在哪)
- 长连接的好处
- 数据传输速度快
- 数据保持最新状态
- 什么是长连接
- 推送通知的基本原理
- 用户app关闭状态下
- qq服务器将消息推送给苹果的APNS服务器
- 苹果的APNS服务器通过devicetoken找到对应设备,并且推送给相应的应用qq
- 如下图:
- 远程推送的详细流程
说明:- 客户端发送设备的UDID和应用的Bundle Identifier给APNs服务器
- UDID: 苹果手机的唯一标识
- Bundle Identifier: 客户端的唯一标识
- 也由此可以看到,苹果的APNS服务器直接可以通过这个deviceToken就可以找到对应设备和设备上的对应应用
- 经苹果APNS加密生成一个deviceToken
- 发送当前用户的deviceToken和用户的标志(比如id或者qq)
- qq服务器将数据存进数据库
- 有人发送消息:李四的手机(昵称:李四 QQ:56789),发给张三(QQ12345):吃饭没?
- qq服务器去数据库查询张三的deviceToken
- 通知苹果服务器APNS:deviceTokoen:888;body:李四:吃饭没?
- 苹果服务器APNS通过deviceToken找到张三现在的设备推送消息
- 客户端发送设备的UDID和应用的Bundle Identifier给APNs服务器
开发步骤
- 开发iOS程序的推送功能, iOS端需要做的事
- 请求苹果获得deviceToken
- 得到苹果返回的deviceToken
- 发送deviceToken给公司的服务器
- 监听用户对通知的点击
- 调试iOS的远程推送功能, 必备条件:
- 真机
- 调试推送需要的证书文件
- aps_development.cer : 某台电脑就能调试某个app的推送服务
- iphone5_qq.mobileprovision : 某台电脑就能利用某台设备调试某个程序
- 发布具有推送服务的app
- aps_production.cer : 如果发布的程序中包含了推送服务,就必须安装这个证书
- qq.mobileprovision : 某台电脑就能发布某个程序
请求苹果获的deviceToken
-
在app启动方法中注册远程通知
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //1. 在程序启动那一刻向苹果的APNS服务器获取devicetoken //1.1 判断iOS版本,iOS8.0以上版本需要的到用户的许可 if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { //申请用户许可 UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]; [application registerUserNotificationSettings:settings]; //1.2 注册远程通知(调用该方法就是向苹果的apns服务器发送该设备的udid和bundle id,返回deviceToken) [application registerForRemoteNotifications]; }else{//iOS7不需要请示用户,直接注册 [application registerForRemoteNotificationTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound]; } return YES; }
-
监听deviceToken的获取情况
//2. 在这拿到苹果返回devicetoken发送给服务器 -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{ // 将DeviceToken传给服务器 NSLog(@"%@", deviceToken.description); } //向apns请求失败 -(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{ NSLog(@"===请求devicetoken失败==%@",error); }
- 会发现在在这里拿不到deviceToken
- 如果这么容易就能拿到,苹果的APNS服务器都爆了,那么多设备都可以访问了.
- 因此,苹果需要你买开发者账号,然后配置证书
-
配置证书
- 结论: (推送必备条件,必须告诉苹果)
- 哪个应用(app)需要推送
- 在哪台电脑上调试(发布)推送服务
- 在哪些设备(手机)上调试推送服务
- 在哪台电脑上用哪台设备调试哪个应用(app)
- 在哪台电脑上发布哪个应用(app)
- 配置步骤
- 用你购买的开发者账号,登录苹果的开发者中心,然后进入证书中心
- 告诉苹果是哪个应用需要推送
- 注册一个appid:
- 进入App IDs->添加->输入你的appid名字(随便起名,比如:ZhonghuaRemoteTest)和你的appID(即bundle identifier)->continue->register->done
- 给你刚才注册的app添加推送服务:
- 进入App IDs->找到你刚才注册的app点击->会看到一个列表,这个列表展示了你的这个app都有哪些服务(通常默认的只有:Game Center和In-App-Purchase这两个服务,绿色表示可用,黄色/没选择表示不可用)->点解编辑(Edit)->勾选你想要的服务->Push Notifications->done
- 注册一个appid:
- 告诉苹果哪台电脑需要调试这个app:
- 仍然回到上一步的Edit->找到Push Notifications->Development SSL Certificate->Create …-> Continue->ChooseFile…
- 这里就是要拿到你的是那一台电脑,即你的电脑的唯一标志(CSR文件)
- 如何生成CSR文件:
- 打开钥匙串-> 顶部工具栏中->钥匙串访问->证书助理->从证书颁发机构请求证书->邮件地址随便写/常用名(随便写)/勾选存储到磁盘-> 确定->保存到桌面即可
- 选择刚才保存的CSR文件->continue->down即可->得到一个aps_development.cer
- 告诉苹果哪台电脑需要发布这个app:
- 同理,重复第3步(但是不需要再次生成CSR了)…Production SSL Certificate->…得到aps.cer
- 告诉苹果哪台设备需要调试:
- 注册设备: 进入Devices,点击加号,将设备添加进去(一般情况下只要你用这个开发者账号调试过真机,他就会自动注册到这里面了)
- 生成描述文件:
- 调试描述文件: 告诉苹果,在哪台电脑上用哪台设备调试那个应用(app)
- 点击
provisioning Profiles
中的All
->添加-> 勾选iOS APP Development
->contuine
-> 选择你的APP ID
->continue
->选择调试证书(注意:这里是调试证书,可不是调试推送证书哦)->选择设备(selectAll
)->取一个名字->down即可.
- 点击
- 发布描述文件: 告诉苹果,在哪台电脑上可以发布哪个应用(app)
- 点击
provisioning Profiles
中的All
->添加-> 勾选App Store
->contuine
-> 选择你的APP ID
->continue
->选择发布证书(注意:这里是发布证书,可不是发布推送证书哦)->取一个名字->down即可.
- 点击
- 打包测试描述文件ADHoc:(用于蒲公英上传打包使用) 告诉苹果,在哪台电脑上可以打包哪个应用(app),并且那些设备可以下载调试
- 点击
provisioning Profiles
中的All
->添加-> 勾选Ad Hoc
-> 选择你的APP ID
->continue
->选择发布证书(注意:这里是发布证书,可不是发布推送证书哦)->选择设备(selectAll)->取一个名字->down即可
- 点击
- 从上面的区别就可以看出: 生成调试/打包测试描述文件时,要选择你要调试的设备,生成发布描述文件时不需要选择设备
- 调试描述文件: 告诉苹果,在哪台电脑上用哪台设备调试那个应用(app)
- 双击安装上面的所有证书(除了CSR)
- iOS10 配置(注意啊!!!!!!!!)
- 在工程Target中的Push Notifications 的开关要开启!否则死活获取不到token,打开后会发现项目中多了一个”项目名.entitlements”文件夹
- 经过以上步骤,再次运行程序,就可以获取到deviceToken了
- 证书说明:(此时,应该有8个证书)
- CSR: mac唯一标志
- ios_development.cer 调试证书
- ios_distribution.cer 发布证书
- aps_development.cer 调试推送证书
- aps.cer 发布推送证书
- 3个描述文件
- 注意: 注意生成调试/发布证书的过程这里就不在多说
- 结论: (推送必备条件,必须告诉苹果)
发送deviceToken给公司的服务器
- 由于远程推送需要服务器来搭配测试,为了方面别人写好了一个运行在mac上的服务器
- PushMeBaby是一款用来测试ANPs的开源Mac项目
- 它充当了服务器的作用,用法非常简单
- 它负责将内容提交给苹果的APNs服务器,苹果的APNs服务器再将内容推送给用户的设备
- PushMeBaby的使用步骤
-
直接注释掉不要的错误
//#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
- 填写必要信息
- 打开
ApplicationDelegate.m
文件 - deviceToken:用于找到设备的令牌(填入你获取到的devicetoken,注意不带”<>”)
- payload:推送的内容
-
这个是公司服务器推送给苹果APNS的标准格式:
@"{\"aps\":{\"alert\":\"This is some fancy message.\",\"badge\":1}}";
- alert:是你要推送的内容
- badge: 推动的未读消息数量
-
- 打开
- 将推送的调试证书(aps_development.cer)改为名apns.cer,添加到PushMeBaby项目中
- 注意:由此可以看出,服务器端必须有你的推送证书,这也就是为什么极光推送需要你上传P12的原因
- command + R启动程序,然后点击Push
- 接下来就可以在设备上接收到远程推送通知
-
SmartPush更好使用
监听用户对通知的点击
注意: 用户点击通知才会拿到通知,直接点击app是拿不到通知的.
-
方法1:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
- 当程序杀死状态,点击本地通知调用
-
方法2:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
- iOS7之前用这个方法(<iOS7)
- (程序在前台/在后台)前后台都会调用,杀死状态不会调用,只会调用方法1
- 实现后台调用:(即不点击通知也会调用)
- 推送的消息中包含content-available字段: 后台时,不点击也会调用
-
方法3:
//iOS7之后用这个方法(>iOS7) -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
- 是在iOS 7之后新增的方法,可以说是2的升级版本,如果app最低支持iOS 7的话可以不用添加 2了。
- 如果实现了该方法,2方法不会调用
- 使用条件
- 打开后台模式->
capablititles
->background Modes
->打开->勾选Remote notifications
- 告诉系统是否有新的更新->
completionHandler(UIBackgroundFetchResultNewData);
- 打开后台模式->
- 调用时刻:
- (程序在前台/在后台)前后台都会调用,杀死也会调用,先调用1,在调用3
- 实现后台调用:(即不点击通知也会调用)
- 推送的消息中包含content-available字段: 后台时,不点击也会调用
- 与方法2的区别是: app关闭(杀死)状态下,点击推送通知也会调用该方法.
-
测试代码如下:
@implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //1. 在程序启动那一刻向苹果的APNS服务器获取devicetoken //1.1 判断iOS版本,iOS8.0以上版本需要的到用户的许可 if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { //申请用户许可 UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]; [application registerUserNotificationSettings:settings]; //1.2 注册远程通知(调用该方法就是向苹果的apns服务器发送该设备的udid和bundle id,返回deviceToken) [application registerForRemoteNotifications]; }else{//iOS7不需要请示用户,直接注册 [application registerForRemoteNotificationTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound]; } // 5.1 当程序杀死状态,点击本地通知调用 if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) { //跳转 //获得本地通知 UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]; //有type可以判断跳转到哪一个界面 UILabel *redView = [[UILabel alloc] init]; redView.frame = CGRectMake(0, 0, 200, 300); redView.numberOfLines = 0; redView.font = [UIFont systemFontOfSize:12.0]; redView.backgroundColor = [UIColor redColor]; redView.text = [NSString stringWithFormat:@"%@",notification]; [self.window.rootViewController.view addSubview:redView]; } return YES; } //2. 监听苹果返回devicetoken /* 注意: 仅仅通过第一步是拿不到devicetoken的. 要不然苹果的APNS服务器都爆了,那么多设备都可以访问了. 因此,苹果需要你买开发者账号,然后配置证书 3. 配置证书 */ -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{ //4.将DeviceToken传给服务器 NSLog(@"%@", deviceToken.description); } //向apns请求失败 -(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{ NSLog(@"===请求devicetoken失败==%@",error); } //5. 接收远程推送 //前后台点击进入时调用 //iOS7之前用这个方法(<iOS7) /* 调用时刻: 点击通知:前后台都会调用,杀死不会调用,只会调用1 推送的消息中包含content-available字段: 后台时,不点击也会调用 */ -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{ NSLog(@"------调用了99999999"); if (application.applicationState == UIApplicationStateBackground) { //进行界面的跳转 //通知的额外信息可以再这里获得userInfo UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(150, 0, 100, 100)]; redView.backgroundColor = [UIColor blueColor]; [self.window.rootViewController.view addSubview:redView]; } } /* 是在iOS 7之后新增的方法,可以说是2的升级版本,如果app最低支持iOS 7的话可以不用添加 2了。 如果实现了该方法,2方法不会调用 点击应用程序图标无法获取推送消息,只有点击通知才会得到 使用条件 1.打开后台模式-> capablititles->background Modes->打开->勾选Remote notifications 2.告诉系统是否有新的更新->completionHandler(UIBackgroundFetchResultNewData); 调用时刻: 点击通知:前后台都会调用,杀死也会调用,先调用1,在调用3 推送的消息中包含content-available字段: 后台时,不点击也会调用 */ //iOS7之后用这个方法(>iOS7) -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{ //可以在这个方法中做些数据下载操作,争取在用户点击通知前,就将数据下载完毕 //进行界面的跳转 //通知的额外信息可以再这里获得userInfo UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(150, 0, 100, 100)]; redView.backgroundColor = [UIColor blueColor]; [self.window.rootViewController.view addSubview:redView]; NSLog(@"------调用了"); //下载完毕要调用completionHandler这个block,告知下载完毕 completionHandler(UIBackgroundFetchResultNewData); } @end
极光推送
- 什么是极光推送
- 一套远程推送解决方案,支持android和iOS两个平台
- 它能够快捷地为iOS App增加推送功能,减少集成APNs需要的工作量、开发复杂度
- 安卓做推送不需要经过Google服务器,可以通过自己的服务器直接推送
- 为何使用极光推送?
- 将远程通知推送中那个专门接收deviceToken的服务器替换成(不自己建了)第三方服务器->极光推送服务器.
- 通过第三方的服务器(极光推送)来给后台推送消息,而不是通过自己公司的服务器.一般第三方服务器都有个管理的后台(图形化界面).
- 原理:若要发送消息,到该第三方的后台中把推送的消息写上去,然后发送推送,那么该第三方服务器会自动推送消息(内部实现:极光服务器把你需要推送的消息内容发送给苹果的apns,然后苹果的apns在推送给你的设备),我们代码操作时,就是操作极光推送的服务器了
- 整体流程实现:
- 服务器方单向发送推送消息:(后台操作)
- 服务器将消息(消息+devicetoken)发送给极光服务器-极光服务器根据(devicetoken)到内存中找到对应的app->极光服务器将消息与devicetoken发送给Apns — apns发送推送给相应的设备(手机)
- 客户端双向发消息(患者端->医生端):
- 患者端通过(自己服务器)服务器提供接口,将消息传递给服务器,服务器向医生端推送消息(内部实现与上面一样)
- 服务器方单向发送推送消息:(后台操作)
- 集成简介:
- 创建应用:
- 百度-极光推送- 注册账号-登录-创建应用- 填写应用名称-上传图标(可以不传,不是推送给用户的图标,而是当该账户下有多个应用时,为了方便区分展示的图片)->此时可以拿到AppKey(有用)
- 到处调试/发布推送证书P12
- 打开钥匙串->找到当前应用的调试推送与发布推送证书
- 分别右击导出(切记千万不要展开!!!)->设置密码->导出2个p12
- 配置iOS应用(同样安卓也得配置)
- 点击推送设置->iOS->上传调试/发布推送P12证书->输入密码->保存->显示已验证,则成功了
- 下载SDK,根据开发文档集成即可.
- 创建应用:
- 极光推送上传P12注意事项 iOS开发极光引用后台(官网上)显示,开发证书没有通过验证,是否重新上传证书? 解决办法
- 当前上传的P12证书密码输入错误,
- 证书导出的时候展开了证书,把个人私钥导了出来,导证书的时候请不要展开证书
- 当前上传的证书环境不对,如: 在上传开发证书地方上传了生产证书
- 该证书已在本账号的其他应用使用
- 现上传的证书与当前应用已上传成功的证书BundleID不一致.
- 注意到处的是调试推送证书与开发推送证书,千万不要导成调试证书与开发证书了(这俩导出来是给其他同事公用的p12)
- 利用JPush发送通知
- JPush会自动记录和管理所有安装过此app的设备deviceToken
- 利用JPush,可以轻易地给所有设备发送远程推送通知