极光推送 集成 使用 Token Authentication

iOS 设备集成推送,以前需要集成开发证书和生产证书,比较麻烦,现在极光推送集成了Token Authentication,就简单方便许多,简单配置,然后集成就可以了;


极光推送证书配置.png

一、配置 Token Authentication

1、首先在Developer 开发者中心 证书 添加 “Keys”
Keys_1.png
Keys_2.png
Keys_3.png

这一步很关键: 点击Download下载到本地,下载后是一个 p8 后缀格式 的文件,下载密钥后,由于服务器副本已被删除,因此无法重新下载。如果此时您还没有准备好下载密钥,请单击Done,稍后再下载。请务必将您的密钥备份保存在安全的地方。下载好后,做好备份,储存起来,丢失找不回的
记住下面的 Key ID


Keys_4.png
2、上传证书
配置证书.png

将p8文件上传,输入Key ID,Team ID ,Bundle ID 点击保存就 OK 了

二、集成极光推送SDK

1、导入SDK

根据需求选择是否需要集成 IDFA

无IDFA.png

    pod 'JCore', '2.1.2'   
    pod 'JPush', '3.2.6'   
2、设置Xcode

请先确保 targets 中的 Bundle ID 和 证书中的Bundle ID一致


配置.png

在TARGETS -> Signing & Capabilities -> + Capability 中添加
-- Access WIFI Information
-- Background Modes -> 勾选 “Remote notifications”
-- Push Notifications

extension AppDelegate: JPUSHRegisterDelegate {
    
    func registureJPUSH(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
        
        let appKey = ""
        
        let entity = JPUSHRegisterEntity()
        if #available(iOS 12.0, *) {
            entity.types = Int(JPAuthorizationOptions.alert.rawValue | JPAuthorizationOptions.badge.rawValue | JPAuthorizationOptions.sound.rawValue | JPAuthorizationOptions.providesAppNotificationSettings.rawValue)
        } else {
            // Fallback on earlier versions
        }
        JPUSHService.register(forRemoteNotificationConfig: entity, delegate: self)
        
        
        // 获取 IDFA
        // 如需使用 IDFA 功能请添加此代码并在初始化方法的 advertisingIdentifier 参数中填写对应值
        // NSString *advertisingId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

        // Required
        // init Push
        // notice: 2.1.5 版本的 SDK 新增的注册方法,改成可上报 IDFA,如果没有使用 IDFA 直接传 nil
        var apsForProduction = false
        #if DEBUG
        apsForProduction = false
        #else
        apsForProduction = true
        #endif
        JPUSHService.setup(withOption: launchOptions, appKey: appKey, channel: "App Store", apsForProduction:  apsForProduction , advertisingIdentifier: nil)
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        
        JPUSHService.registerDeviceToken(deviceToken)
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        
        debugPrint("did Fail To Register For Remote Notifications With Error: \(error)")
    }
    
    //  ios 12 Support
    @available(iOS 10.0, *)
    func jpushNotificationCenter(_ center: UNUserNotificationCenter!, openSettingsFor notification: UNNotification!) {
        
        if notification != nil && ((notification.request.trigger?.isKind(of: UNPushNotificationTrigger.self)) != nil) {
            debugPrint("从通知界面直接进入应用")
        } else {
            debugPrint("从通知设置界面进入应用")
        }
    }
    
    //  iOS 10 Support
    @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.self)) != nil) {
            JPUSHService.handleRemoteNotification(userInfo)
        }
        completionHandler(Int(JPAuthorizationOptions.alert.rawValue)) // 需要执行这个方法,选择是否提醒用户,有 Badge、Sound、Alert 三种类型可以选择设置
    }
    
    //  iOS 10 Support
    @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.self)) != nil) {
            JPUSHService.handleRemoteNotification(userInfo)
        }
        completionHandler() // 系统要求执行这个方法
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        
        // iOS 7 Support
        JPUSHService.handleRemoteNotification(userInfo)
        completionHandler(.newData)
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        
        // Required, For systems with less than or equal to iOS 6
        JPUSHService.handleRemoteNotification(userInfo)
    }
}

后续操作

class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?

    var isForceLandscape:Bool = false
    var isForcePortrait:Bool = false
    var isForceAllDerictions:Bool = false //支持所有方向

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        self.window = UIWindow.init(frame: UIScreen.main.bounds)
        self.window!.backgroundColor = .white
        self.window!.makeKeyAndVisible()
        registureJPUSH(launchOptions: launchOptions)
        testView(index: 0)
        return true
    }
    
    /*
     //极光推送 角标清0 未读消息不清空
     //本地推送UILocalNotification的applicationIconBadgeNumber影响到角标的显示,不出对通知栏的消息造成影响
     //3.UIApplication的applicationIconBadgeNumber属性既会影响角标的显示,又会影响通知栏通知的处理。
     //1)当applicationIconBadgeNumber>0时,角标会随之变化,通知栏通知不变。
     //2)当applicationIconBadgeNumber=0时,角标变为0不显示,通知栏通知清空。
     //3)当applicationIconBadgeNumber<0时,角标变为0不显示,通知栏通知清空。
     //所以要想不清除通知栏内容,极光就不能设置这个:[UIApplication sharedApplication].applicationIconBadgeNumber = 0;,极光的cleanBadgeNum方法也不能用。
     */
    
    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
        
        // UIApplication.shared.applicationIconBadgeNumber = 0
        // App 退至后台会走此方法
        
        testView(index: 1)
        
        /*
         if ([UIApplication sharedApplication].applicationIconBadgeNumber) {
             if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 11.0) {
                 [[UIApplication sharedApplication] setApplicationIconBadgeNumber:-1];
             } else {
                 UILocalNotification *localNotification = [[UILocalNotification alloc] init];
                 // 设置通知的发送时间,单位秒
                 localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:0.5];
                 //收到通知时App icon的角标
                 localNotification.applicationIconBadgeNumber = -1;
                 // 3.发送通知(🐽 : 根据项目需要使用)
                 [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
             }
         }
         [JPUSHService setBadge:0];
         */
    }
}
extension AppDelegate: JPUSHRegisterDelegate {
    
    func registureJPUSH(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
        
        let appKey = ""
        
        let entity = JPUSHRegisterEntity()
        if #available(iOS 12.0, *) {
            entity.types = Int(JPAuthorizationOptions.alert.rawValue | JPAuthorizationOptions.badge.rawValue | JPAuthorizationOptions.sound.rawValue | JPAuthorizationOptions.providesAppNotificationSettings.rawValue)
        } else {
            // Fallback on earlier versions
        }
        JPUSHService.register(forRemoteNotificationConfig: entity, delegate: self)
        
        
        // 获取 IDFA
        // 如需使用 IDFA 功能请添加此代码并在初始化方法的 advertisingIdentifier 参数中填写对应值
        // NSString *advertisingId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

        // Required
        // init Push
        // notice: 2.1.5 版本的 SDK 新增的注册方法,改成可上报 IDFA,如果没有使用 IDFA 直接传 nil
        var apsForProduction = false
        #if DEBUG
        apsForProduction = false
        #else
        apsForProduction = true
        #endif
        JPUSHService.setup(withOption: launchOptions, appKey: appKey, channel: "App Store", apsForProduction:  apsForProduction , advertisingIdentifier: nil)
    }
    
    
    /*
     //极光推送 角标清0 未读消息不清空
     //本地推送UILocalNotification的applicationIconBadgeNumber影响到角标的显示,不出对通知栏的消息造成影响
     //3.UIApplication的applicationIconBadgeNumber属性既会影响角标的显示,又会影响通知栏通知的处理。
     //1)当applicationIconBadgeNumber>0时,角标会随之变化,通知栏通知不变。
     //2)当applicationIconBadgeNumber=0时,角标变为0不显示,通知栏通知清空。
     //3)当applicationIconBadgeNumber<0时,角标变为0不显示,通知栏通知清空。
     //所以要想不清除通知栏内容,极光就不能设置这个:[UIApplication sharedApplication].applicationIconBadgeNumber = 0;,极光的cleanBadgeNum方法也不能用。
     */
    
    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
        
        // UIApplication.shared.applicationIconBadgeNumber = 0
        // App 退至后台会走此方法
        
        // testView(index: 1)
        
        /*
         if ([UIApplication sharedApplication].applicationIconBadgeNumber) {
             if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 11.0) {
                 [[UIApplication sharedApplication] setApplicationIconBadgeNumber:-1];
             } else {
                 UILocalNotification *localNotification = [[UILocalNotification alloc] init];
                 // 设置通知的发送时间,单位秒
                 localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:0.5];
                 //收到通知时App icon的角标
                 localNotification.applicationIconBadgeNumber = -1;
                 // 3.发送通知(🐽 : 根据项目需要使用)
                 [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
             }
         }
         [JPUSHService setBadge:0];
         */
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        
        JPUSHService.registerDeviceToken(deviceToken)
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        
        debugPrint("did Fail To Register For Remote Notifications With Error: \(error)")
    }
    
    //  ios 12 Support
    @available(iOS 10.0, *)
    func jpushNotificationCenter(_ center: UNUserNotificationCenter!, openSettingsFor notification: UNNotification!) {
        
        debugPrint("==================== 0")
        if notification != nil && ((notification.request.trigger?.isKind(of: UNPushNotificationTrigger.self)) != nil) {
            debugPrint("从通知界面直接进入应用")
            
            testView(index: 2)
        } else {
            debugPrint("从通知设置界面进入应用")
            
            testView(index: 3)
        }
    }
    
    //  iOS 10 Support
    @available(iOS 10.0, *)
    func jpushNotificationCenter(_ center: UNUserNotificationCenter!, willPresent notification: UNNotification!, withCompletionHandler completionHandler: ((Int) -> Void)!) {
        
        debugPrint("App正在运行时推送进入 = 1")
        UIApplication.shared.applicationIconBadgeNumber = 0
        let userInfo = notification.request.content.userInfo
        debugPrint((userInfo as NSDictionary))
        
        if ((notification.request.trigger?.isKind(of: UNPushNotificationTrigger.self)) != nil) {
            JPUSHService.handleRemoteNotification(userInfo)
        }
        // completionHandler(Int(JPAuthorizationOptions.alert.rawValue)) // 需要执行这个方法,选择是否提醒用户,有 Badge、Sound、Alert 三种类型可以选择设置
        completionHandler(Int(JPAuthorizationOptions.sound.rawValue))
        
        showOrderDetailsView(model: AppJPUSHModel.deserialize(from: userInfo as NSDictionary)!, show: true)
    }
    
    //  iOS 10 Support
    @available(iOS 10.0, *)
    func jpushNotificationCenter(_ center: UNUserNotificationCenter!, didReceive response: UNNotificationResponse!, withCompletionHandler completionHandler: (() -> Void)!) {
        
        debugPrint("App未运行,点击推送消息进入,App 已退至后台,收到消息推送,点击消息推送 = 2")
        let userInfo = response.notification.request.content.userInfo
        if ((response.notification.request.trigger?.isKind(of: UNPushNotificationTrigger.self)) != nil) {
            JPUSHService.handleRemoteNotification(userInfo)
        }
        completionHandler() // 系统要求执行这个方法
        
        // testView(index: 5)
        showOrderDetailsView(model: AppJPUSHModel.deserialize(from: userInfo as NSDictionary)!, show: false)
    }
    
    /*
     基于 iOS 7 及以上的系统版本,如果是使用 iOS 7 的 Remote Notification 特性那么处理函数需要使用
     */
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        
        debugPrint("==================== 3")
        // iOS 7 Support
        JPUSHService.handleRemoteNotification(userInfo)
        completionHandler(.newData)
        
        testView(index: 6)
    }
    
    /*
     基于 iOS 6 及以下的系统版本,如果 App 状态为正在前台或者点击通知栏的通知消息,那么此函数将被调用,并且可通过 AppDelegate 的 applicationState 是否为 UIApplicationStateActive 判断程序是否在前台运行
     */
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        
        debugPrint("==================== 4")
        // Required, For systems with less than or equal to iOS 6
        JPUSHService.handleRemoteNotification(userInfo)
        
        testView(index: 7)
    }
    
    
    func testModel() -> AppJPUSHModel {
        
        var model = AppJPUSHModel()
        model.status = 2
        model.type = 1
        model.title = "asdf dddf"
        model.address = "dfadsfadsfasdf "
        model.description = "asdfacxggg"
        model.attachments = "http://api.unicrom.cn/images/1588231332_494399.jpg,http://api.unicrom.cn/images/1588235202_118597.jpg"
        return model
    }
    
    func jpushRemoteNotificationInfo(userInfo:NSDictionary) {
        
       // // 取得 APNs 标准信息内容
       // NSDictionary *aps = [userInfo valueForKey:@"aps"];
       // NSString *content = [aps valueForKey:@"alert"]; //推送显示的内容
       // NSInteger badge = [[aps valueForKey:@"badge"] integerValue]; //badge 数量
       // NSString *sound = [aps valueForKey:@"sound"]; //播放的声音
        
       // // 取得 Extras 字段内容
       // NSString *customizeField1 = [userInfo valueForKey:@"customizeExtras"]; //服务端中 Extras 字段,key 是自己定义的
    }
    
    
    func showOrderDetailsView(model:AppJPUSHModel,show guideView:Bool) {

        guard GlobalData.share.api_token != nil else { return }
        
        UIApplication.shared.applicationIconBadgeNumber = 0
        /// 工单的状态1:未分配,2:处理中,3:待分配,4:已完成  5: 已取消
        let status:[OrderStatus] = [.undistributed,.processing,.unconfirmed,.finished,.canceled]
        
        guard guideView == true else {
            
            if model.type == 0 {
                pushViewController(orderStatue: status[model.status!-1], companyId: model.company_id, sheetId: model.sheet_id)
            } else {
                pushViewController(orderStatue: status[model.status!-1], companyId: model.company_id, sheetId: model.sheet_id)
            }
            return
        }
        
        if model.type == 0 {
            self.window!.addSubview(progressView)
            progressView.frame = self.window!.bounds
            progressView.setValues(text: model.process_note) {
                
                self.pushViewController(orderStatue: status[model.status!-1], companyId: model.company_id, sheetId: model.sheet_id)
            }
        }
        else {
            self.window!.addSubview(orderDetailView)
            orderDetailView.frame = self.window!.bounds
            orderDetailView.setValues(model: model) {
                
                self.pushViewController(orderStatue: status[model.status!-1], companyId: model.company_id, sheetId: model.sheet_id)
            }
        }
    }
    
    func pushViewController(orderStatue:OrderStatus,companyId:Int! = nil,sheetId:Int! = nil) {
        
        let vc = WorkUndistributedVC()
        vc.orderStatue = orderStatue
        vc.companyId = companyId
        vc.sheetId = sheetId
        topVC!.navigationController!.pushViewController(vc, animated: true)
    }
    
    
    
    
    func testView(index:Int) {
        
        let progressView = JPUSHViewOrderProgress.loadFromNib("JPUSHView", index: 0)
        self.window!.addSubview(progressView)
        progressView.frame = self.window!.bounds
        progressView.setValues(text: nil) {
            
        }
        progressView.detailTextView.text = "\(index)"
    }
}

推送消息

/*
 App 未运行,无推送消息: 0
 App 未运行,有推送消息: 1 - 0
 App 未运行,点击推送消息: 5 - 0
 App 正在前台运行: 4
 App 已退至后台,收到消息推送,未点击消息推送: 无
 App 已退至后台,收到消息推送,点击消息推送: 5
 */

具体文档请参考 : 极光推送-官方文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350