说实话,极光推送接触过好几遍了,但是每次开发都是实现简单的展示功能,最近接手的一款app要求只在后台展示,还要实现点击通知栏跳转到相应的详情界面,于是便以为很简单的开始了,而且还很嗨的那种,以为自己没问题了(当时自己用的iOS10以上的iPhone)。但是最后测试阶段,出现各种问题,各种调试都不行,简单总结一下当时出现的问题(不过前提条件是已经按照极光官方文档的要求集成好了,而且用极光的控制台发送消息通知一切都正常)
1)不同系统的手机,app在后台通知的展示和点击会走不同的代理方法
比如说iOS8系统下,展示通知和点击通知都会走这个方法
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void
(^)(UIBackgroundFetchResult))completionHandler
又比如说iOS10系统下,展示通知居然会走上面的方法,还会在点击通知的时候走下面这个方法
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler
2)前台和后台,也会影响调用不同的代理方法
3)你以为这是最后一个问题,那你就错了,这是都没法继续总结了,总之就是出现毫无规律可言的乱
相信看到这里,很多人还是不理解,这里尽量放心,是可以直接忽略跳过前面的。要想实现点击极光推送去跳转详情,主要看下面的这张图,重点来了!重点来了!重点来了!
上面这张图是我问了极光的技术人员我的某一个问题之后给我的一个网页链接里面的,看到这我真的是悲喜交加,我瞬间精神了。当务之急是立马联系我们项目的后台,确定是否给推送的加了content-available字段,自己也打印日志看了一番,果然,在极光的后台推送是没有content-available字段,但是我们的php后台给我们iOS这边加上了这个字段,后台也回复我他加了。在这里告诉你,你千万别信后台说什么去不掉,改不了这个字段的鬼话,在极光技术人员的帮助下,我复制各种能解决的方法,甚至代码样例给后台,最后终于还是给我解决了这个问题,终于能看见打印的日志里面没有了content-available字段,终于看到了曙光。不要以为这就结束了,你这就错了,还有一个地方得注意,app这边还得注意前后台,从上面的图片也是可以看出来的,就是在下面的方法里面得加一个前台的判断,不在前台才去实行跳转的逻辑。最后拿着iOS8,iOS9,iOS10,iOS11的手机各种测试,终于正常了,我只想说上面这个图我太喜欢了!
下面我把项目里面相关的极光源码(包括集成)粘贴出来,小伙伴们可以随意看看
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
......省略不写
// Required 注册通知 我们项目是只支持iOS7以上的设备
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1
if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
entity.types = UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound;
[JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
}else if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
//categories
[JPUSHService
registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert)
categories:nil];
} else {
//categories nil
[JPUSHService
registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert)
#else
//categories nil
categories:nil];
[JPUSHService
registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert)
#endif
// Required
categories:nil];
}
[JPUSHService setupWithOption:launchOptions appKey:@"482c5c296d169dcfbebec15b" channel:@"AppStore" apsForProduction:YES advertisingIdentifier:nil];
//自定义消息需要用到的
// NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
// [defaultCenter addObserver:self selector:@selector(networkDidReceiveMessage:) name:kJPFNetworkDidReceiveMessageNotification object:nil];
//2.1.9版本新增获取registration id block接口。
[JPUSHService registrationIDCompletionHandler:^(int resCode, NSString *registrationID) {
if(resCode == 0){
NSLog(@"registrationID获取成功:%@",registrationID);
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:registrationID forKey:JPushRegistrationID];
[defaults synchronize];
}
else{
NSLog(@"registrationID获取失败,code:%d",resCode);
}
}];
......省略不写
}
// 将极光推送得到的deviceToken传给SDK
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
[JPUSHService registerDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
// Required
NSLog(@"iOS6?????");
[JPUSHService handleRemoteNotification:userInfo];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void
(^)(UIBackgroundFetchResult))completionHandler {
// IOS 7 Support Required
if (application.applicationState != UIApplicationStateActive) {//不在前台,必须判断
[self didJpushJumpToDetail:userInfo];
}
[JPUSHService handleRemoteNotification:userInfo];
completionHandler(UIBackgroundFetchResultNewData);
}
//IOS 10 点击通知走这里
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSLog(@"iOS10以后处理后台点击消息通知的代理方法");
// Required
NSDictionary *userInfo = response.notification.request.content.userInfo;
[self didJpushJumpToDetail:userInfo];
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[JPUSHService handleRemoteNotification:userInfo];
}
completionHandler(); // 系统要求执行这个方法
}
//实现点击通知跳转到相应的详情界面
- (void)didJpushJumpToDetail:(NSDictionary *)userInfo {
NSLog(@"userInfo = %@", userInfo);
int t = [[userInfo objectForKey:@"type"] intValue];
if (t == 2) {// 1:即时问答 2:问题广场
NSString *type= [NSString stringWithFormat:@"%d",t];
if ([userInfo objectForKey:@"qid"] && [userInfo objectForKey:@"waitType"]) {// && [userInfo objectForKey:@"rid"]
NSString *qid = [NSString stringWithFormat:@"%d", [[userInfo objectForKey:@"qid"] intValue]];
NSString *rid = [NSString stringWithFormat:@"%d", [[userInfo objectForKey:@"rid"] intValue]];
NSString *waitType = [userInfo objectForKey:@"waitType"];//zhuiwen ques
[[NSNotificationCenter defaultCenter]postNotificationName:@"notificationGotoVc" object:nil userInfo:@{@"t":type, @"qid":qid, @"waitType":waitType, @"rid":rid}];
}
}else if(t == 1) {
NSString *type= [NSString stringWithFormat:@"%d",t];
if ([userInfo objectForKey:@"qid"] && [userInfo objectForKey:@"uid"] && [userInfo objectForKey:@"qtype"]) {
NSString *qid = [NSString stringWithFormat:@"%d",[[userInfo objectForKey:@"qid"] intValue]];
NSString *uid = [NSString stringWithFormat:@"%d",[[userInfo objectForKey:@"uid"] intValue]];
NSString *qtype = [NSString stringWithFormat:@"%d",[[userInfo objectForKey:@"qtype"] intValue]];
[[NSNotificationCenter defaultCenter]postNotificationName:@"notificationGotoVc" object:nil userInfo:@{@"t":type, @"qid":qid, @"uid":uid, @"qtype":qtype}];
}
}
}
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {
NSLog(@"iOS10新增:处理前台收到通知的代理方法");
// Required
NSDictionary * userInfo = notification.request.content.userInfo;
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[JPUSHService handleRemoteNotification:userInfo];
}else {
//应用处于前台时的本地推送接受
}
//注意:::注释掉下面这行,则app在前台不会展示顶部通知,如果去掉注释则是会在顶部展示通知的,根据项目需求而定,我们要求不展示
// completionHandler(UNNotificationPresentationOptionAlert); // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以选择设置
}
补偿一条极光的小坑:极光的官方文档说自定义消息只有app在前台才会收到,但是通过xcode打印还是能看到在后台还是会调用networkDidReceiveMessage方法,最后通过和官方技术客服沟通,才知道极光连着 xcode 会自动后台刷新,就是可以与极光保持长连接状态,你断开xcode测试就不会有问题了。