美文网首页
IOS 推送通知 本地推送和远程推送

IOS 推送通知 本地推送和远程推送

作者: 越天高 | 来源:发表于2020-05-27 16:53 被阅读0次

    什么是推送通知?

    首先明确:**此处的推送通知跟我们的”NSNotification”没有半毛钱关系
    可以理解为: 向用户推送一条信息来通知用户某件事情
    作用: 可以在APP退到后台,或者关闭时;继续推送一条消息告诉用户某件事情

    推送通知的应用场景?

    • (1) 一些任务管理APP,会在任务时间即将到达时,通知你做该任务;
      (2) 健身App定时提醒你应该健身了;
      (3) 买过电影票后,提前半小时告诉你,电影即将开场;
      (4) 当你QQ或者微信收到消息时,即使退到后台,或者关闭APP,也可以收到信息通知告诉我们;
      (5) 电商APP,推送一条消息通知我们有新品上架等等

    推送通知的分类

    • 本地推送通知

      “本地”可以理解为”不联网”;即使没有网络情况下,也可以推送通知消息
      应用场景: 确定知道未来某个时间点应该提醒用户什么
      通知发送方:开发人员负责在app内部发送

    • 远程推送通知

      与“本地”相对,表示,必须在联网情况下才会向用户推送通知消息
      远程推送服务,又称为APNs(Apple Push Notification Services)

      应用场景:

      1. 不确定未来某个时间点应该提醒用户什么,临时性的
      2. 当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种情况

    1. app并没有关闭,一直隐藏在后台
      让app进入前台,并会调用AppDelegate的下面方法(并非重新启动app)
    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;
    
    1. app已经被关闭(进程已死)
      启动app,启动完毕会调用AppDelegate的下面方法
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
    launchOptions参数通过UIApplicationLaunchOptionsLocalNotificationKey取出本地推送通知对象
    

    添加一些额外的操作

    IMG_0497.PNG
    func 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案例分析

    1. app 发送设备的UDID和
      应用的Bundle Identifier
      给APNs服务器

    2. 经苹果加密生成一个
      deviceToken 返还给当前app

    3. app发送当前用户的deviceToken
      和用户的标志(比如id或者qq) 给qq服务器

    4. qq服务器将用户的deviceToken存进数据库

    5. 当有人发送消息 李四的手机(昵称:李四 QQ:56789)
      发给张三(QQ12345):吃饭没?

    6. 消息先到qq服务器,然后去数据库查询张三的deviceToken

    7. qq服务器通知苹果服务器
      deviceTokoen:888
      body:李四:吃饭没?

    8. 苹果服务器通过deviceToken找到张三现在的设备

    一.开发iOS程序的推送功能, iOS端需要做的事

    1.请求苹果获得deviceToken
    2.得到苹果返回的deviceToken,发送deviceToken给公司的服务器

    1. 监听用户对通知的点击

    二.调试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取出服务器返回的字典内容
    

    相关文章

      网友评论

          本文标题:IOS 推送通知 本地推送和远程推送

          本文链接:https://www.haomeiwen.com/subject/mpiiahtx.html