美文网首页
swift5.x APNS(推送) 相关跳转处理包括(冷启动、热

swift5.x APNS(推送) 相关跳转处理包括(冷启动、热

作者: Bruce_XHG | 来源:发表于2019-12-24 17:43 被阅读0次

APNs推送是我们经常使用到的,现在我们使用的基本上是个推和极光两个三方
不同的需求对推送的要求也不一样,对于前端来说最主要的是对推送的处理
下面主要总结一下对推送的处理,由于目前是用swift开发的,下面就用swift总结一下。

1、首先在你的开发者账号里面创建推送证书,以及xcode推送相关的配置,对于了解的同学这是多余的话,对于不了解的同学这说的又太简单,如果是不了解的同学,这里创建证书和xcode配置可以自行百度一下。

2、如果你使用的是个推或极光,先集成他们的SDK,集成文档他们官网说的都很清楚。

3、以上配置好了以后我们先进行APNs通知注册,注册的调用要在didFinishLaunchingWithOptions该方法返回true之前

func registerRemoteNotification() {
            let systemVer = (UIDevice.current.systemVersion as NSString).floatValue
            if systemVer >= 10.0 {
                    if #available(iOS 10.0, *) {
                            let center:UNUserNotificationCenter = UNUserNotificationCenter.current()
                            center.delegate = self;
                            center.requestAuthorization(options: [.alert,.badge,.sound], completionHandler: { (granted:Bool, error:Error?) -> Void in
                                    if (granted) {
                                            logDebug("注册通知成功")  
                                    } else {
                                            logDebug("注册通知失败")  
                                    }
                            })
                            UIApplication.shared.registerForRemoteNotifications()
                            return;
                    }
            }
            if systemVer >= 8.0 {
                    if #available(iOS 8.0, *) {
                            let userSettings = UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil)
                            UIApplication.shared.registerUserNotificationSettings(userSettings)
                            
                            UIApplication.shared.registerForRemoteNotifications()
                    }
            }
    }

对于iOS12以后获取deviceToken的处理需要注意一下和之前不一样了

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        var deviceTokenString = String()
        let bytes = [UInt8](deviceToken)
        for item in bytes {
                deviceTokenString += String(format:"%02x", item&0x000000FF)
        }
     logDebug("deviceToken:\(deviceTokenString)")
        GeTuiSdk.registerDeviceTokenData(deviceToken);
        logDebug("[ TestDemo ] [ DeviceToken(NSData) ]: \(NSData.init(data: deviceToken))");
    }

对于需要在APP前台也弹出通知消息的设置,注意该方法只是设置允许前台弹出通知栏,但是如果要弹出还需要进行其他的设置

@available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
            logDebug("[ TestDemo ] [APNs] willPresentNotification: \(notification.request.content.userInfo)");
            
            completionHandler([.badge,.sound,.alert]);
    }

下面这方法是点击通知栏会执行的方法包括本地通知的点击,相关的处理逻辑都会在这里进行处理,所以代码会比较多

@available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
            logDebug("[ TestDemo ] [APNs] didReceiveNotificationResponse: \(response.notification.request.content.userInfo)");
            GeTuiSdk.handleRemoteNotification(response.notification.request.content.userInfo);
        if response.notification.request.identifier == "com.yungu.locaNotification" {
            let messageModel = dealDicToModel(dic: response.notification.request.content.userInfo as NSDictionary)
            if LibsManager.shared.isColdOpen == true {
                NotificationCenter.default.rx.notification(Notification.Name(rawValue: "rootControllerLoadFinshed")).subscribe(onNext: { _ in
                    self.dealDataWith(messageModel: messageModel)
                }).disposed(by: rx.disposeBag)
            }else{
                if getCurrentVC() != nil {
                    dealDataWith(messageModel: messageModel)
                }else{
                    NotificationCenter.default.rx.notification(Notification.Name(rawValue: "rootControllerLoadFinshed")).subscribe(onNext: { _ in
                        self.dealDataWith(messageModel: messageModel)
                    }).disposed(by: rx.disposeBag)
                }
            }
        }else{
            let userInfo = response.notification.request.content.userInfo
            let aps = userInfo["aps"] as! NSDictionary
            let alert = aps["alert"] as! NSDictionary
            if alert["action-loc-key"] != nil {
                let tempStr: NSMutableString = alert["action-loc-key"] as! String as! NSMutableString
                var character: NSString?
                for i in 0 ..< tempStr.length {
                    character = tempStr.substring(with: NSMakeRange(i,1)) as NSString
                    if character!.isEqual(to: "\\") {
                        tempStr.deleteCharacters(in: NSMakeRange(i,1))
                    }
                }
                let messageBody: String = tempStr as String
                let dic = getDictionaryFromJSONString(jsonString: messageBody)
                let messageModel = dealDicToModel(dic: dic)
                if LibsManager.shared.isColdOpen == true {
                    NotificationCenter.default.rx.notification(Notification.Name(rawValue: "rootControllerLoadFinshed")).subscribe(onNext: { _ in
                        self.dealDataWith(messageModel: messageModel)
                    }).disposed(by: rx.disposeBag)
                }else{
                    if getCurrentVC() != nil {
                        dealDataWith(messageModel: messageModel)
                    }else{
                        NotificationCenter.default.rx.notification(Notification.Name(rawValue: "rootControllerLoadFinshed")).subscribe(onNext: { _ in
                            self.dealDataWith(messageModel: messageModel)
                        }).disposed(by: rx.disposeBag)
                    }
                }
            }
        }
            completionHandler();
    }

其中if response.notification.request.identifier == "com.yungu.locaNotification" 这个if的判断是处理APP在前台时弹出消息的处理,由于数据结构有些不一致,所以做了判断处理。

if LibsManager.shared.isColdOpen == true 这个判断是处理是否是冷启动,如果是冷启动会走didFinishLaunchingWithOptions,在该方法中设置是冷启动,但是进入到根视图的时候再把LibsManager.shared.isColdOpen置为false;冷启动的时候点击的通知我是用了通知的方法处理的,在进入到根视图的时候一般是在viewwillapper里面keywindow才会加载出来,但是通知写在viewwillapper里面也会有问题,所以我做了一个延迟0.5秒再发送通知的操作,很好的解决了这个问题,如果启动的时候有独立的广告页,也是能很好的解决广告页造成的问题

else就是热启动的点击了,这个是比较容易处理的,因为这时候可以随时拿到当前的控制器进行相关的跳转处理.

有的同学可能会在集成的SDK回调里面进行相关的逻辑处理,其实之前我也是这么处理的,但是感觉不好,特别是那种不是进入APP就把推送消息角标置为0的需求.我们的需求是点击一条通知消息清除一条,sdk的回调是你进入到APP的时候如果有很多条消息他会走很多遍,把所有的消息接收完,那么对于你点击的是那一条其实回调里面是不知道的。

前台消息弹出相关处理

if offLine == false {//非离线消息 前台
            if UIApplication.shared.applicationState == .active {
                let content = UNMutableNotificationContent.init()
                content.title = messageModel.title ?? "ceshi"
                content.subtitle = messageModel.content ?? "ceshi"
                content.userInfo = dic as! [AnyHashable : Any]
                let requestIdentifier = "com.yungu.locaNotification"
                let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
                let request = UNNotificationRequest(identifier: requestIdentifier,
                                                                                        content: content, trigger: trigger)
                UNUserNotificationCenter.current().add(request) { error in
                    if error == nil {
                        print("Time Interval Notification scheduled: \(requestIdentifier)")
                    }
                }
            }
        }

这里是需要把消息组装,发送本地通知,才能在前台推出通知栏消息。

当然这里还有下拉通知消息进行回复消息的处理,比如微信、QQ都有这个功能
下拉回复的代码如下(这个是oc代码,swift我们这期没有这个需求,没有写 😺)

#pragma mark - 在通知栏快捷回复配置
- (void)setNoti{
    UIMutableUserNotificationAction  *unta = [[UIMutableUserNotificationAction alloc] init];
    [unta setBehavior:UIUserNotificationActionBehaviorTextInput];
    unta.title = @"测试点击";
    [unta setIdentifier:@"Reply"];
    [unta setActivationMode:UIUserNotificationActivationModeBackground];
    UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc] init];
    [category setIdentifier:@"Category"];
    [category setActions:@[unta] forContext:UIUserNotificationActionContextDefault];
    UIUserNotificationSettings * settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:[NSSet setWithArray:@[category]]];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}

#pragma mark -在通知栏点击发送触发的方法
-(void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler{
    
    NSString *messageStr = [responseInfo objectForKey:UIUserNotificationActionResponseTypedTextKey];
    NSLog(@"快捷回复信息:%@",messageStr);
}

相关文章

网友评论

      本文标题:swift5.x APNS(推送) 相关跳转处理包括(冷启动、热

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