最近整理了项目使用的推送资料,包括原生APNS、亚马逊推送、谷歌FireBase推送,从申请证书到代码工具调试,基本整理的差不多。
本篇文章主要介绍app在前台活跃时,有推送时显示系统的原始通知框。在网上查了很多资料,都说只能app在后台时才能调用系统的通知弹框,所以以前用的是自定义的弹框,最近发现在app活跃时,可以调用本地通知达到app前台活跃时显示系统的弹框。
//UIApplicationLaunchOptionsRemoteNotificationKey对应的是启动应用程序的远程通知信息userInfo(NSDictionary) -(void) dealPushNotificacton:(NSDictionary*) launchOptions { NSDictionary *remoteNotificationDic = nil; if (launchOptions != nil) { remoteNotificationDic = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]; if (remoteNotificationDic != nil) { UPDINFO(@"Launched from push notification: %@", remoteNotificationDic); self.remoteNotificationUserInfo = remoteNotificationDic; } } [self registerRemoteNotifications]; } - (void)registerRemoteNotifications { if ([UPIUtils deviceOS] < 10.0 ) { [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]]; dispatch_async(dispatch_get_main_queue(), ^{ [[UIApplication sharedApplication] registerForRemoteNotifications]; }); } else { UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; center.delegate = self; [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) { if(!error ) { dispatch_async(dispatch_get_main_queue(), ^{ [[UIApplication sharedApplication] registerForRemoteNotifications]; }); } else { } }]; } } ios 10之前和之后注册推送的方式不一样,要注意,下面需要注册通知成功和失败的代码。 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(nonnull NSData *)deviceToken { } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { }下面的方法,当app在后台时点击才会进,app在前台时,收到通知就会进,大家可以打断点调试一下。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { // 收到推送通知后逻辑 UPDINFO(@"didReceiveRemoteNotification %@",userInfo); self.remoteNotificationUserInfo = userInfo; //UIApplicationStateActive = 在app界面; UIApplicationStateInactive = 未在app界面; if (application.applicationState == UIApplicationStateActive) { [self showLocalNotification]; //[self showRemoteNotification]; } else { [self handlePushMessageInfo]; } }下面是不同的系统版本,调用本地通知,其中设置shouldAlwaysAlertWhileAppIsForeground参数直接决定了是否显示前台通知,大家要注意。其他的title,body,userinfo等信息看情况自己取值。
-(void)showLocalNotification { if ([UPIUtils deviceOS] < 10.0 ) { UILocalNotification *notification = [[UILocalNotification alloc] init]; notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:0.1]; notification.repeatInterval = NSCalendarUnitDay; notification.alertBody = self.remoteNotificationUserInfo[@"data"][@"content"]; notification.timeZone = [NSTimeZone defaultTimeZone]; notification.soundName = UILocalNotificationDefaultSoundName; [[UIApplication sharedApplication] scheduleLocalNotification:notification]; } else { //必须写代理,不然无法监听通知的接收与点击事件 UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; center.delegate = self; UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; content.body = self.remoteNotificationUserInfo[@"data"][@"content"]; content.userInfo = self.remoteNotificationUserInfo; content.sound = [UNNotificationSound defaultSound]; //ios 12 后失败,会导致闪退 //[content setValue:@(YES) forKeyPath:@"shouldAlwaysAlertWhileAppIsForeground"]; UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"Notif" content:content trigger:nil]; [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { }]; } }下面的这两个代理其实是声明通知方法的代理,适用于10及以上,这里注释掉通知点击之前的代码,只保留点击后的代理方法,在点击后方法中传值,跳转页面等。因为使用的是 didReceiveRemoteNotification方法,好像不兼容10及以上,但是系统会自动适配,所以注释掉了这个代理,不然只走点击前的方法,不走didReceiveRemoteNotification了。
// 该两个代理回调适用于10以上,点击前: //- (void)userNotificationCenter:(UNUserNotificationCenter *)center // willPresentNotification:(UNNotification *)notification // withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler { // // completionHandler(UNNotificationPresentationOptionSound); //} //点击后: - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { [self handlePushMessageInfo]; }下面的方法用不上,类似于didReceiveRemoteNotification这个方法。调试的时候试了很久,完全浪费时间。
收到本地通知进行,点击跳转 //- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification //{ // //前台跳转 // if (application.applicationState == UIApplicationStateActive) { // [self handlePushMessageInfo]; // } //}