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);
}
网友评论