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

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

自定义消息和通知的区别

  • 收到推送自定义消息时推送通知栏不显示
  • 自定义消息推送不经过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极光推送通知和自定义消息)