You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS APNs推送返回BadDeviceToken错误原因及远程通知注册方案咨询

BadDeviceToken错误的常见原因

  • curl命令格式错误:你当前的请求头apns-push-type: alert没有加单引号包裹,curl会把alert识别为独立的主机地址,虽然第二次请求成功发送到APNs服务器,但流程中的参数混乱很容易伴随无效token的使用。
  • DeviceToken解析错误:你使用[deviceToken description]的方式提取token,该方法的输出格式在iOS 13及以上系统发生了变更,会得到包含多余字段的无效token,这是BadDeviceToken最常见的诱因。
  • 环境不匹配:新导入的provisioning profile如果是生产环境配置,生成的token属于生产环境,你向沙箱地址api.sandbox.push.apple.com发送请求就会返回BadDeviceToken;同理如果证书和token所属环境不匹配也会触发该错误。
  • 配置不匹配:provisioning profile没有开启推送能力、apns-topic和证书对应的Bundle ID不一致、测试设备没有添加到当前开发团队的设备列表中,都会导致token无效。

正确的远程通知注册及调试方案

1. 修正DeviceToken解析逻辑

不要使用description方法提取token,改用如下兼容所有iOS版本的解析代码:

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
    NSUInteger length = deviceToken.length;
    if (length == 0) {
        return;
    }
    const unsigned char *buffer = deviceToken.bytes;
    NSMutableString *newToken  = [NSMutableString stringWithCapacity:(length * 2)];
    for (NSInteger i = 0; i < length; ++i) {
        [newToken appendFormat:@"%02x", buffer[i]];
    }
    NSLog(@"My token is: %@", newToken);
    
    // 原有业务逻辑保留
    UINavigationController *navigationController = (UINavigationController*)_window.rootViewController;
    ChatViewController *chatViewController = (ChatViewController*)[navigationController.viewControllers objectAtIndex:0];
    DataModel *dataModel = chatViewController.dataModel;
    NSString* oldToken = [dataModel deviceToken];
    [dataModel setDeviceToken:newToken];
    if ([dataModel joinedChat] && ![newToken isEqualToString:oldToken]) {
        [self postUpdateRequest];
    }
}

2. 修正推送请求命令

给所有请求头加单引号,避免curl解析错误:

curl -v --header 'apns-topic: com.domain.appname' --header 'apns-push-type: alert' --cert aps.cer --cert-type DER --key PushChatKey.pem --key-type PEM --data '{"aps":{"alert":"Test"}}' --http2  https://api.sandbox.push.apple.com/3/device/你的正确deviceToken

如果是生产环境测试,把请求地址换成api.push.apple.com。

3. 修正注册代码的冗余逻辑

你当前的注册代码存在重复调用的问题,不管iOS版本判断结果如何,最后都额外调用了一次iOS8以前的注册接口,会导致高版本系统的注册逻辑异常,修正后代码如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
    _storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    //-- Set Notification
    if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
        // iOS 8及以上系统
        [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
        [application registerForRemoteNotifications];
    } else {
        // iOS 8以下系统
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         (UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge)];
    }

    if (launchOptions != nil) {
        NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        if (dictionary != nil) {
            NSLog(@"Launched from push notification: %@", dictionary);
            /*[self addMessageFromRemoteNotification:dictionary updateUI:NO];*/
        }
    } 
    return YES;
}

4. 配置文件校验

  • 确认Xcode中当前的Signing & Capabilities已经添加Push Notifications能力
  • 确认使用的provisioning profile属于开发环境,且对应的App ID已经开启推送服务
  • 确认当前测试设备的UDID已经添加到该开发配置文件的设备列表中
  • 确认推送证书和当前使用的App ID、环境完全匹配

内容的提问来源于stack exchange,提问作者programcode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 13:15:03