什么是推送通知?
首先明确:**此处的推送通知跟我们的”NSNotification”没有半毛钱关系
可以理解为: 向用户推送一条信息来通知用户某件事情
作用: 可以在APP退到后台,或者关闭时;继续推送一条消息告诉用户某件事情
推送通知的应用场景?
- (1) 一些任务管理APP,会在任务时间即将到达时,通知你做该任务;
(2) 健身App定时提醒你应该健身了;
(3) 买过电影票后,提前半小时告诉你,电影即将开场;
(4) 当你QQ或者微信收到消息时,即使退到后台,或者关闭APP,也可以收到信息通知告诉我们;
(5) 电商APP,推送一条消息通知我们有新品上架等等
推送通知的分类
-
本地推送通知
“本地”可以理解为”不联网”;即使没有网络情况下,也可以推送通知消息
应用场景: 确定知道未来某个时间点应该提醒用户什么
通知发送方:开发人员负责在app内部发送 -
远程推送通知
与“本地”相对,表示,必须在联网情况下才会向用户推送通知消息
远程推送服务,又称为APNs(Apple Push Notification Services)应用场景:
- 不确定未来某个时间点应该提醒用户什么,临时性的
- 当APP彻底退出时也想继续让用户获取一些最新消息
-
使用原则: 谁能确定通知时间和内容, 谁就可以发送(开发人员在APP内部通过代码发送=本地通知; 服务器可以确定通知时间和内容=远程通知)*
远程推送的呈现效果
image.png本地推送通知
在iOS8.0之后 使用本地通知需要得到用户的许可 在didFinishLaunchingWithOptions里面添加请求
if(系统版本 >= 8.0)
{
// 注册接收通知的类型
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:settings];
// 注册允许接收远程推送通知
[application registerForRemoteNotifications];
}
else
{
// 如果是iOS7.0,使用以下方法注册
[application registerForRemoteNotificationTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound];
}
//swfit:
if #available(iOS 8.0, *)
{
// 注册接收通知的类型
let type = UIUserNotificationType.alert.rawValue | UIUserNotificationType.badge.rawValue | UIUserNotificationType.sound.rawValue
let settings = UIUserNotificationSettings(types: UIUserNotificationType(rawValue: type), categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)
// 注册允许接收远程推送通知
UIApplication.shared.registerForRemoteNotifications()
}
发送一个本地通知
@IBAction func puchNotionfication(_ sender: Any)
{
// 如果是ios8.0以前, 以下代码, 可以直接发送一个本地通知,
// 但是, 如果是ios8.0以后, 你需要主动的请求授权, 才可以
// 通知显示的条件
// 必须不能再前台
//1.创建一个t本地通知
let localNoti = UILocalNotification()
//2. 设置通知内容
localNoti.alertBody = "这是一个好日字"
//3. 设置发送通知的时间触发时间
localNoti.fireDate = Date(timeIntervalSinceNow: 4)
//重复周期
// localNoti.repeatInterval = .weekday
//设置滑动文字
localNoti.hasAction = true
localNoti.alertAction = "回复"
// 启动图片(当用户点击了本地通知, 启动我们APP 的时候, 带的启动图片)
// 如果是在ios9.0以前, 当锁屏界面, 出现一个通知, 用户点击了通知, 启动APP 的时候, 会自动将我们设置的图片, 当做启动图像 来显示
// ios9.0, 这个属性, 不太灵
// 如果这个图片,找不到, 会使用系统默认的启动图片
localNoti.alertLaunchImage = "2"
// 设置通知弹框的标题
// 标题, 这对于, 通知中心的通知有效
if #available(iOS 8.2, *)
{
localNoti.alertTitle = "斗地主"
}
// 设置图标右上角的数字(0 代表不显示)
localNoti.applicationIconBadgeNumber = 3
// userInfo 额外信息
localNoti.userInfo = ["name":"哥哥", "sex":"女"]
//应用程序级别的操作 ,调度本地通知,完成之后,会在特定的fireDate发出通知
UIApplication.shared.scheduleLocalNotification(localNoti)
}
其他的属性和方法
调度本地推送通知(调度完毕后,推送通知会在特地时间fireDate发出)
[[UIApplication sharedApplication] scheduleLocalNotification:ln];
获得被调度(定制)的所有本地推送通知
@property(nonatomic,copy) NSArray *scheduledLocalNotifications;
(已经发出且过期的推送通知就算调度结束,会自动从这个数组中移除)
取消调度本地推送通知
- (void)cancelLocalNotification:(UILocalNotification *)notification;
- (void)cancelAllLocalNotifications;
立即发出本地推送通知
- (void)presentLocalNotificationNow:(UILocalNotification *)notification;
每隔多久重复发一次推送通知
@property(nonatomic) NSCalendarUnit repeatInterval;
点击推送通知打开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参数通过UIApplicationLaunchOptionsLocalNotificationKey取出本地推送通知对象
添加一些额外的操作
IMG_0497.PNGfunc registerAuthor()
{
// Override point for customization after application launch.
if #available(iOS 8.0, *)
{
// 注册接收通知的类型
let type = UIUserNotificationType.alert.rawValue | UIUserNotificationType.badge.rawValue | UIUserNotificationType.sound.rawValue
//1.创建z一组操作行为
let category = UIMutableUserNotificationCategory()
//1.1设置组标识
category.identifier = "select"
//1.2设置组里面的行为
let action1 = UIMutableUserNotificationAction()
action1.identifier = "queding"
action1.title = "确定"
// behavior todo
// 代表, 用户如果点击了这个动作, 拉到底, 是在前台运行这个动作, 还是在后台
action1.activationMode = .foreground
// 必须要解锁之后, 行为才会执行(如果activationMode, 是前台状态, 那这个属性, 就会被忽略)
action1.isAuthenticationRequired = true
// 是否是破坏性行为(会使用一个红色的标识, 来标识这个按钮)
action1.isDestructive = false
//1.1设置组标识
category.identifier = "select"
//1.2设置组里面的行为
let action2 = UIMutableUserNotificationAction()
action2.identifier = "huifu"
action2.title = "回复"
// behavior todo
if #available(iOS 9.0, *)
{
action2.behavior = .textInput
action2.parameters = [UIUserNotificationTextInputActionButtonTitleKey: "确定"]
}
// 代表, 用户如果点击了这个动作, 拉到底, 是在前台运行这个动作, 还是在后台
action2.activationMode = .background
// 必须要解锁之后, 行为才会执行(如果activationMode, 是前台状态, 那这个属性, 就会被忽略)
action2.isAuthenticationRequired = false
// 是否是破坏性行为(会使用一个红色的标识, 来标识这个按钮)
action2.isDestructive = false
let actions = [action1, action2]
// 如果针对于弹框样式的通知
// default 代表, 最多可以显示4个按钮
// minimal, 代表,最多可以显示2个按钮
category.setActions(actions, for: .default)
//附加操作行为组
let categorys : Set<UIUserNotificationCategory> = [category]
let settings = UIUserNotificationSettings(types: UIUserNotificationType(rawValue: type), categories: categorys)
UIApplication.shared.registerUserNotificationSettings(settings)
// 注册允许接收远程推送通知
UIApplication.shared.registerForRemoteNotifications()
}
}
// completionHandler, 系统提供的回调代码块, 执行这个代码块, 到时候, 系统会采集一些信息
func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, completionHandler: @escaping () -> Void)
{
print(identifier,notification)
print("old")
completionHandler()
}
// 9.0
// 如果实现了这个方法, 那么上面一个方法, 就不再执行
func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, withResponseInfo responseInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void) {
print("new")
print(identifier,responseInfo)
completionHandler()
}
远程推送
什么是远程推送通知
- 顾名思义,就是从远程服务器推送给客户端的通知(需要联网)
- 远程推送服务,又称为APNs(Apple Push Notification Services
为什么需要远程推送通知?
传统获取数据的局限性
只要用户关闭了app,就无法跟app的服务器沟通,无法从服务器上获得最新的数据内容
不管用户打开还是关闭app,只要联网了,都能接收到服务器推送的远程通知
所有的苹果设备,在联网状态下,都会与苹果的服务器建立长连接
-
什么是长连接
只要联网了,就一直建立连接 -
长连接的作用
时间校准
系统升级
查找我的iPhone
.. ... -
长连接的好处
数据传输速度快
数据保持最新状态
获取deviceToken
苹果需要用户的UDID和bundleID
获取过程
qq案例分析
-
app 发送设备的UDID和
应用的Bundle Identifier
给APNs服务器 -
经苹果加密生成一个
deviceToken 返还给当前app -
app发送当前用户的deviceToken
和用户的标志(比如id或者qq) 给qq服务器 -
qq服务器将用户的deviceToken存进数据库
-
当有人发送消息 李四的手机(昵称:李四 QQ:56789)
发给张三(QQ12345):吃饭没? -
消息先到qq服务器,然后去数据库查询张三的deviceToken
-
qq服务器通知苹果服务器
deviceTokoen:888
body:李四:吃饭没? -
苹果服务器通过deviceToken找到张三现在的设备
一.开发iOS程序的推送功能, iOS端需要做的事
1.请求苹果获得deviceToken
2.得到苹果返回的deviceToken,发送deviceToken给公司的服务器
- 监听用户对通知的点击
二.调试iOS的远程推送功能, 必备条件:
1.真机
2.调试推送需要的证书文件
1> aps_development.cer : 某台电脑就能调试某个app的推送服务
2> iphone5_qq.mobileprovision : 某台电脑就能利用某台设备调试某个程序
三.发布具有推送服务的app
1> aps_production.cer : 如果发布的程序中包含了推送服务,就必须安装这个证书
2> qq.mobileprovision : 某台电脑就能发布某个程序
制作证书
截屏2020-05-27下午4.42.59.png 截屏2020-05-27下午4.43.18.png 截屏2020-05-27下午4.43.09.png 截屏2020-05-27下午4.43.25.png截屏2020-05-27下午4.43.35.png 截屏2020-05-27下午4.43.44.png
注册远程推送通知
客户端如果想接收APNs的远程推送通知,必须先注册(得到用户的授权)
一般在App启动完毕后就马上注册
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 注册远程通知
UIRemoteNotificationType type = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:type];
return YES;
}
- 注册成功后会调用AppDelegate的下面方法,得到设备的deviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSLog(@"%@", deviceToken);
}
点击远程推送通知
当用户点击远程推送通知,会自动打开app,这里有2种情况
app并没有关闭,一直隐藏在后台
让app进入前台,并会调用AppDelegate的下面方法(并非重新启动app)
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;
app已经被关闭(进程已死)
启动app,启动完毕会调用AppDelegate的下面方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
launchOptions参数通过UIApplicationLaunchOptionsRemoteNotificationKey取出服务器返回的字典内容
网友评论