iOS 极光推 Not get deviceToken yet,didReceiveRemoteNotification withCompletionHandler

前言:

真的,我就挺服气的,哪里来的这么多bug。

在聊bug之前,我们首先来做个测试用的 demo,我们把极光推送集成进来。

1、假设你在Apple后台已经配置好了推送的开发证书和生产证书,并且你把这个证书导出p12文件上传到极光并且通过了验证。 (我这里开发环境和生产环境是区分开的),极光教程:

极光推送官方证书配置教程

我的配置.png

2、假设你已经创建了新工程,使用 pod 集成极光推送。
3、你需要在把项目配置一下,允许项目使用通知,允许在后台接收到通知消息。
项目配置添加推送.png
4、把极光推送的示例代码拷贝到 AppDelegate.m
#import "AppDelegate.h"

// 引入 JPush 功能所需头文件
#import "JPUSHService.h"
// iOS10 注册 APNs 所需头文件
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import <UserNotifications/UserNotifications.h>
#endif

@interface AppDelegate ()<JPUSHRegisterDelegate>

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        
    //Required
    //notice: 3.0.0 及以后版本注册可以这样写,也可以继续用之前的注册方式
    JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
    if (@available(iOS 12.0, *)) {
        entity.types = JPAuthorizationOptionAlert|JPAuthorizationOptionBadge|JPAuthorizationOptionSound|JPAuthorizationOptionProvidesAppNotificationSettings;
    } else {
        // Fallback on earlier versions
    }
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
        // 可以添加自定义 categories
        // NSSet<UNNotificationCategory *> *categories for iOS10 or later
        // NSSet<UIUserNotificationCategory *> *categories for iOS8 and iOS9
    }
    [JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
    
    
    // Optional
    // 获取 IDFA
    // 如需使用 IDFA 功能请添加此代码并在初始化方法的 advertisingIdentifier 参数中填写对应值
    //NSString *advertisingId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
    
    // Required
    // init Push
    // notice: 2.1.5 版本的 SDK 新增的注册方法,改成可上报 IDFA,如果没有使用 IDFA 直接传 nil
    [JPUSHService setupWithOption:launchOptions appKey:@"d25a9995b0198799bc47b1ef"
                          channel:@"AKK"
                 apsForProduction:NO
            advertisingIdentifier:nil];
    
    
    return YES;
}


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    /// Required - 注册 DeviceToken
    [JPUSHService registerDeviceToken:deviceToken];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    //Optional
    NSLog(@"did Fail To Register For Remote Notifications With Error: %@", error);
}

#pragma mark- JPUSHRegisterDelegate
// iOS 12 Support
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center openSettingsForNotification:(UNNotification *)notification{
    if (notification && [notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        //从通知界面直接进入应用
        NSLog(@"从通知界面直接进入应用");
    }else{
        //从通知设置界面进入应用
        NSLog(@"从通知设置界面进入应用");
    }
}

// iOS 10 Support
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {
    // Required
    NSDictionary * userInfo = notification.request.content.userInfo;
    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];
    }
    completionHandler(UNNotificationPresentationOptionAlert); // 需要执行这个方法,选择是否提醒用户,有 Badge、Sound、Alert 三种类型可以选择设置
}

// iOS 10 Support
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
    // Required
    NSDictionary * userInfo = response.notification.request.content.userInfo;
    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];
    }
    completionHandler();  // 系统要求执行这个方法
}

- (void)jpushNotificationAuthorization:(JPAuthorizationStatus)status withInfo:(NSDictionary *)info {
    
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    
    NSLog(@"APP在后台收到消息:  \n %@", userInfo);
    
    // Required, iOS 7 Support
    [JPUSHService handleRemoteNotification:userInfo];
    completionHandler(UIBackgroundFetchResultNewData);
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    NSLog(@"APP在后台收到消息:  \n %@", userInfo);
    // Required, For systems with less than or equal to iOS 6
    [JPUSHService handleRemoteNotification:userInfo];
}

#pragma mark - UISceneSession lifecycle
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options  API_AVAILABLE(ios(13.0)){
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}

- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions  API_AVAILABLE(ios(13.0)){
    // Called when the user discards a scene session.
    // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
    // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}

5、Command + R,运行项目,发送通知。

然而,有些时候,期望不尽人意,你没有收到推送。

BUG 1 :[JPUSHClientController] Not get deviceToken yet.

极光控制台打印提示:
[JPUSHClientController] Not get deviceToken yet. Maybe: your certificate not configured APNs? or current network is not so good so APNs registration failed? or there is no APNs register code? Please refer to JPush docs.

出现这个提示,基本上就是因为注册通知失败了,也就是项目启动的时候没有调用下面这个函数:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {}

这个函数必须被调用,你才能收到通知。在调试的时候,在这个函数上打断点,看是否成功注册。

注册设备.png

如果你打了断点,发现仍然没有调用这个函数,而且,就连注册失败的回调都不走:

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {}

那么,原因可能有以下:

1、尝试在 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {}
添加 :[[UIApplication sharedApplication] registerForRemoteNotifications]; 强行注册通知。

2、你在调试的时候,多次卸载 App 然后重新运行,如此操作,该代理方法就不会走了。要么换手机,要么就等到它能回调。我等过几个小时才好,如果等到第二天,它也能好,因为,我等过。MD。

或者参考以下玩家的文章:

IOS didRegisterForRemoteNotificationsWithDeviceToken没有执行

关于推送(无法获取DeviceToken)

Not getting APNS Device token on ios 13

BUG 2 :didReceiveRemoteNotification: fetchCompletionHandler: 方法不回调

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {}
方法不回调。

当你把App退到后台(没有杀掉),然后你发推送,期望App在后台也能收推送的内容。然而你的手机上出现了通知横幅,但是却没有触发后台收到通知的函数(didReceiveRemoteNotification:fetchCompletionHandler:),因此你也就无法拿到通知的内容。原因有以下:

1、检查通知的内容是否包含 “content-available” 这个字段,这个字段对应布尔值,设置为true,App在后台才能收到内容:
在极光后台发送通知的时候,需要勾选这个字段:


极光推送页.png

在你的项目调试里面,这个字段是这样的:


字段.png

2、确保你的项目里面,在 Background Modes 里面 勾选了 Remote notification

3、如果你已经成功注册了设备,并且你已经正确设置了content-available = 1字段,也勾选了勾选了 Remote notification,但是!这个回调还是没有走,那么可能是iOS系统问题。我遇到过。我在调试的时候,用的手机是 iOS 13.5,iOS 13.3,这玩意就像抽疯了一样,时好时坏,上午怎么调试都收不到,睡一觉等到下午调试,又莫名其妙地收到通知了。隔天,我拿了自己的测试机,iOS 10.2.1,把App退到后台,我100%能收到通知,没有一个漏的。关于这个问题,我找了很多网上资料,也给极光提问了,以下文章给玩家参考:

我在极光官网上的提问

极光官网的回复

极光:iOS13 出现 Not get deviceToken yet, iOS12 不会

极光社区问题汇总页

苹果官网有人提问 iOS 13.3 收不到通知

stackoverflow 上的提问

后续

「JPush」收不到消息的排查方案

iOS 收不到消息 / 排查不出请根据第 5 点说明提供信息

iOS,APP退到后台,获取推送成功的内容并且语音播报内容。

iOS开发之极光推送的那些坑

iOS极光推送突然收不到推送消息

(Not get deviceToken yet )极光推送不成功deviceToken未获取

添加推送功能时 didRegisterForRemoteNotificationsWithDeviceToken不调用

关于didRegisterForRemoteNotificationsWithDeviceToken不执行的问题

IOS 不走didRegisterForRemoteNotificationsWithDeviceToken的解决方案

结语:

来这家写代码,每次需求,都能遇到些疑难杂症,bug还比较硬,很特么的是烦。今年因为 iOS系统 和 Mac系统 而导致的bug格外地多。就让人感觉很无语,很无聊,啥也不是。我都不想再写代码了。

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