美文网首页
Swift JPush极光推送通知和自定义消息

Swift JPush极光推送通知和自定义消息

作者: Tony_Yang | 来源:发表于2017-05-05 18:23 被阅读1232次

    在开始之前,首先了解下自定义消息和通知的几点区别。

    自定义消息和通知的区别

    • 收到推送自定义消息时推送通知栏不显示
    • 自定义消息推送不经过APNS,所以说跟推送证书没有关系
    • 只有app在前台时才能收到自定义消息,未启动或者启动但处于后台时接收不到(解决了不想在app未启动时收到推送消息的问题)

    SDK初始化

    Appdelegate文件

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
            
            // 极光推送
            if (UIDevice.current.systemVersion as NSString).floatValue >= 10.0  {
                
                if #available(iOS 10.0, *) {
                    let entity = JPUSHRegisterEntity()
                    entity.types = NSInteger(UNAuthorizationOptions.alert.rawValue | UNAuthorizationOptions.badge.rawValue | UNAuthorizationOptions.sound.rawValue)
                    _ = JPUSHService.register(forRemoteNotificationConfig: entity, delegate: self)
                } else {
                    // Fallback on earlier versions
                }
                
            } else if  (UIDevice.current.systemVersion as NSString).floatValue >= 8.0 {
                //可以添加自定义categories
                JPUSHService.register(forRemoteNotificationTypes: UIUserNotificationType.badge.rawValue | UIUserNotificationType.sound.rawValue | UIUserNotificationType.alert.rawValue, categories: nil)
            } else {
                //categories 必须为nil
                JPUSHService.register(forRemoteNotificationTypes: UIUserNotificationType.badge.rawValue | UIUserNotificationType.sound.rawValue | UIUserNotificationType.alert.rawValue, categories: nil)
            }
            
            var isJpushProduction: Bool
            #if DEBUG
                isJpushProduction = false
            #else
                isJpushProduction = true
            #endif
            
            JPUSHService.setup(withOption: launchOptions, appKey: JPUSHService_appKey, channel: "Publish channel", apsForProduction: isJpushProduction, advertisingIdentifier: nil)
            
            return true
        }
    

    通知(极光远程推送)

    调用此 API 来取得应用程序对应的 RegistrationID。 只有当应用程序成功注册到 JPush 的服务器时才返回对应的值,否则返回空字符串。

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
            
            JPUSHService.registerDeviceToken(deviceToken)
            
            /**
             completionHandler用于处理设置返回结果
             resCode返回的结果状态码
             registrationID返回registrationID
             */
            JPUSHService.registrationIDCompletionHandler { (resCode, registrationID) in
                print("resCode--", resCode, "    registrationID---", registrationID ?? "没有")
            }
        }
    

    注册失败回调方法

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
            
            print("didFailToRegisterForRemoteNotificationsWithError----", error)
        }
    

    iOS10以下的系统版本,收到本地通知(LocalNotification)时调用

    func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
            
            let userInfo = notification.userInfo;
            print("userInfo-------", userInfo ?? ["":""])
        }
    

    基于iOS10以下iOS 7 及以上的系统版本,收到远程通知(RemoteNotification)时调用

    private func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
            
            JPUSHService.handleRemoteNotification(userInfo)
            // 收到远程通知后的处理
            handleTheRemoteNotification(userInfo: userInfo as NSDictionary)
            completionHandler(UIBackgroundFetchResult.newData)
        }
    

    在iOS 10出来后,极光推出了下面的两个新方法来替代了以上的两个方法。

    iOS10及以上系统版本,app在后台(1、app在后台运行 2、锁屏状态 3、app关闭时)收到通知并且当用户点击通知栏上的消息时调用

    @available(iOS 10.0, *)
        func jpushNotificationCenter(_ center: UNUserNotificationCenter!, didReceive response: UNNotificationResponse!, withCompletionHandler completionHandler: (() -> Void)!) {
            
            let userInfo = response.notification.request.content.userInfo
            if response.notification.request.trigger?.isKind(of: UNPushNotificationTrigger.classForCoder()) == true {
                
                JPUSHService.handleRemoteNotification(userInfo)
                print("iOS10后台收到通知(当用户点击通知栏的时候)...")
                // 收到远程通知后的处理
                handleTheRemoteNotification(userInfo: userInfo as NSDictionary)
                
            } else {
                print("----本地通知")
            }
            
            completionHandler() // 系统要求执行这个方法
        }
    

    iOS10及以上系统版本,app处于前台时接收到通知时调用

    @available(iOS 10.0, *)
        func jpushNotificationCenter(_ center: UNUserNotificationCenter!, willPresent notification: UNNotification!, withCompletionHandler completionHandler: ((Int) -> Void)!) {
            
            let userInfo = notification.request.content.userInfo
            
            if notification.request.trigger?.isKind(of: UNPushNotificationTrigger.classForCoder()) == true {
                JPUSHService.handleRemoteNotification(userInfo)
                print("iOS10 前台收到远程通知...")
                // 收到远程通知后的处理
                handleTheRemoteNotification(userInfo: userInfo as NSDictionary)
                
            } else {
                print("本地通知...")
            }
            
            let tempPresentationOptions = UNNotificationPresentationOptions.alert.rawValue |  UNNotificationPresentationOptions.sound.rawValue | UNNotificationPresentationOptions.badge.rawValue
            completionHandler(Int(tempPresentationOptions)) // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以选择设置
        }
    

    自定义方法,用于收到远程通知后的一些处理操作,比如取值以及页面的跳转等等

    func handleTheRemoteNotification(userInfo: NSDictionary) {
            
            let aps = userInfo["aps"] as? NSDictionary // 取得 APNs 标准信息内容
            let content = aps?["alert"] as? String ?? "" // 推送显示的内容
            let customizeField = aps?["customizeExtras"] as? String ?? "" // 服务端中Extras字段,key是自己定义的
            
            let ctrlAlert = UIAlertController(title: "提醒", message: content, preferredStyle: UIAlertControllerStyle.alert)
            
            let confirmAction = UIAlertAction(title: "确定", style: .default){ (action) in
                UIApplication.shared.applicationIconBadgeNumber -= 1
                // 所需业务逻辑处理。。。
            }
            let cancelAction =  UIAlertAction(title: "取消", style: .default) { (action) in
                UIApplication.shared.applicationIconBadgeNumber -= 1
                // 不作处理
            }
            
            ctrlAlert.addAction(cancelAction)
            ctrlAlert.addAction(confirmAction)
            
            let rootVC = UIApplication.shared.keyWindow?.rootViewController
    }
    

    通知(本地推送)

    对于一些业务需求,比如闹铃或者日历的一些提醒事件等,自己推送消息,实现推送通知的效果。

    func pushLocalNotification() {
            
            let notification = UILocalNotification()
            if #available(iOS 8.2, *) {
                notification.alertTitle = "小蜗牛"
            } else {
                // Fallback on earlier versions
            }
            notification.alertBody = "快来玩啊~"
            notification.userInfo = ["name": "Tony", "gender": "man"]
            UIApplication.shared.presentLocalNotificationNow(notification)
        }
    

    自定义消息

    功能说明:只有在前端运行的时候才能收到自定义消息的推送。
    从jpush服务器获取用户推送的自定义消息内容和标题以及附加字段等。
    这些内容是和后台的同学们协商好的,并且由他们来写好向极光推送的相应服务。

    获取iOS的推送内容需要在appDelegate类中注册通知并实现回调方法。

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
            
            // 极光推送,接收自定义消息
            let defaultCenter = NotificationCenter.default
            defaultCenter.addObserver(self, selector: #selector(networkDidReceiveMessage(notification:)), name: NSNotification.Name.jpfNetworkDidReceiveMessage, object: nil)
            
            return true
        }
    

    回调方法

    // 接收自定义消息
        func networkDidReceiveMessage(notification:NSNotification) {
    
            let userInfo: NSDictionary = notification.userInfo! as NSDictionary
            print("自定义消息---",userInfo)
            
            // 业务逻辑处理。。。
        }
    

    标签与别名

    别名 alias

    为安装了应用程序的用户,取个别名来标识。以后给该用户 Push 消息时,就可以用此别名来指定。
    每个用户只能指定一个别名。
    同一个应用程序内,对不同的用户,建议取不同的别名。这样,尽可能根据别名来唯一确定用户。
    系统不限定一个别名只能指定一个用户。如果一个别名被指定到了多个用户,当给指定这个别名发消息时,服务器端API会同时给这多个用户发送消息。
    举例:在一个用户要登录的游戏中,可能设置别名为 userid。游戏运营时,发现该用户 3 天没有玩游戏了,则根据 userid 调用服务器端API发通知到客户端提醒用户。

    标签 tag

    为安装了应用程序的用户,打上标签。其目的主要是方便开发者根据标签,来批量下发 Push 消息。
    可为每个用户打多个标签。
    举例: game, old_page, women

    别名与标签的设置
    因为别名和标签可以重复设置,所以我把它放在了登录方法中。

    func login() {
      //极光推送 注册别名
      let alias = String(format: "%d", userId)
      JPUSHService.setTags(["lowbeer","doubeer"], aliasInbackground: alias)
    }
    

    然后在退出登录时注销别名和标签,避免在多个设备上登录后,通过别名发送通知时,多个设备都会收到的情况。

    // 退出登录
    func logout() {
      // 注销推送别名和标签
      JPUSHService.setTags([], aliasInbackground: "")
    }
    

    参数说明

    alias
    • nil 此次调用不设置此值。
    • 空字符串 ("")表示取消之前的设置。
    • 每次调用设置有效的别名,覆盖之前的设置。
    • 有效的别名组成:字母(区分大小写)、数字、下划线、汉字,特殊- 字符(v2.1.9支持)@!#$&*+=.|。
    • 限制:alias 命名长度限制为 40 字节。(判断长度需采用UTF-8编码)
    tags
    • nil 此次调用不设置此值。
    • 空集合([NSSet set])表示取消之前的设置。
    • 集合成员类型要求为String类型
    • 每次调用至少设置一个 tag,覆盖之前的设置,不是新增。
    • 有效的标签组成:字母(区分大小写)、数字、下划线、汉字,特殊字符(v2.1.9支持)@!#$&*+=.|。
    • 限制:每个 tag 命名长度限制为 40 字节,最多支持设置 1000 个 tag,但总长度不得超过7K字节。(判断长度需采用UTF-8编码)
      单个设备最多支持设置 1000 个 tag。App 全局 tag 数量无限制。

    小结

    在推送测试时如果接收不到通知,不要着急,不要悲伤,深呼吸,淡定~~~

    • 要检查好项目的开发和生产证书是否配置正确,并上传到了极光应用后台,并保证证书没有过期。参考SDK集成指南证书设置指南
    • 项目Target的Push Notifications开关是否打开。
    • 卸载应用重新安装。我有次第一次收到了,但是后边却无论如何都接收不到了,然后拿着RegId和MsgId问了下极光的技术,他们告诉我:
      1、apple认为token失效了
      2、苹果建议程序每次启动的时候从 apns 获取 devicetoken
      重新获取一次新的token,测试时,简单的操作就是卸载重装
      ---该问题可以看下这个苹果APNs’ device token特性和过期更新
    • 在极光官网最下方有技术交流群,可以加群找技术咨询解决。

    相关文章

      网友评论

          本文标题:Swift JPush极光推送通知和自定义消息

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