【问题标题】:Get Device Token in iOS 8在 iOS 8 中获取设备令牌
【发布时间】:2014-08-17 01:04:27
【问题描述】:

我需要设备令牌来在我的应用中实现推送通知。
由于didRegisterForRemoteNotificationsWithDeviceToken 方法在 iOS 8 上不起作用,我如何获取设备令牌。 我在应用程序委托中尝试了此代码,但它没有给我设备令牌。

    [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
    [[UIApplication sharedApplication] registerForRemoteNotifications];

【问题讨论】:

  • 您可以在 iOS 8 文档中轻松找到此内容:UIUserNotificationSettings
  • 我注册了 UIUserNotificationSettings 但它会给我设备令牌。
  • 你实现application:didRegisterUserNotificationSettings:了吗?它在文档中!

标签: ios ios8


【解决方案1】:

阅读 UIApplication.h 中的代码。

你会知道怎么做的。

第一:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

添加这样的代码

#ifdef __IPHONE_8_0
  //Right, that is the point
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
|UIRemoteNotificationTypeSound
|UIRemoteNotificationTypeAlert) categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
#else
    //register to receive notifications
    UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
#endif

如果你没有同时使用 Xcode 5 和 Xcode 6,试试这个代码

if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
  UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
      |UIRemoteNotificationTypeSound
      |UIRemoteNotificationTypeAlert) categories:nil];
  [application registerUserNotificationSettings:settings];
} else {
  UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
  [application registerForRemoteNotificationTypes:myTypes];
}

(感谢@zeiteisen @dmur 的提醒)


第二:

添加此功能

#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
    //register to receive notifications
    [application registerForRemoteNotifications];
}

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
    //handle the actions
    if ([identifier isEqualToString:@"declineAction"]){
    }
    else if ([identifier isEqualToString:@"answerAction"]){
    }
}
#endif

你可以得到 deviceToken in

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

如果还是不行,使用这个函数并 NSLog error

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

【讨论】:

  • 感谢您的回答。我会检查并通知您。
  • 谢谢,这对我有用,但不应该是 UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert 而不是 UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert
  • 这将在低于 iOS 8 的 iOS 版本上崩溃。#ifdef 是一个编译器函数,并在编译时进行评估。您仍然需要运行时检查!
  • 你可以在方法中使用if (([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 && [[[UIDevice currentDevice] systemVersion] floatValue] < 9.0))
  • 我试过了,但是 (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 由于某种原因在 iOS 8 上没有被调用。(至少我的命令都没有,包括 NSLog正在经历。)任何可能的解决方案?
【解决方案2】:

在@Madao 的回复中附加一个小验证,以防您在旧 iOS 版本上遇到崩溃:

#ifdef __IPHONE_8_0
if(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) {
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert) categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
#endif

UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound |     UIRemoteNotificationTypeNewsstandContentAvailability;
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];

__IPHONE_8_0 宏的作用只是允许您在旧版本的 xCode/iOS 中编译,您不会收到编译错误或警告,但在 iOS 7 或更低版本的设备上运行代码会导致崩溃。

【讨论】:

  • 这就是我刚要评论麻道的帖子。
  • 我做了这个并且它有效,如果 ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) { UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert 类别:无]; [应用程序注册用户通知设置:设置]; } else { [应用程序 registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound]; }
【解决方案3】:

在iOS8+中获取设备令牌

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//This code will work in iOS 8.0 xcode 6.0 or later
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
    [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
    [[UIApplication sharedApplication] registerForRemoteNotifications];
}
else
{
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeNewsstandContentAvailability| UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
return YES;
}

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
NSString* deviceToken = [[[[deviceToken description]
                         stringByReplacingOccurrencesOfString: @"<" withString: @""]
                         stringByReplacingOccurrencesOfString: @">" withString: @""]
                         stringByReplacingOccurrencesOfString: @" " withString: @""] ;
NSLog(@"Device_Token     -----> %@\n",deviceToken);
}

【讨论】:

    【解决方案4】:

    2020年解决方案

    六个步骤,

    1。图书馆

    2。添加到 AppDelegate

    // APNs:
    
    func application(_ application: UIApplication,
          didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        print(">> getting an APNs token works >>\(deviceToken)<<")
        let tokenAsText = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    }
    
    func application(_ application: UIApplication,
          didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print(">> error getting APNs token  >>\(error)<<")
    }
    

    3。在您的应用中

    例如用户登录后

    import UserNotifications
    

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        askNotifications()
    }
    
    func askNotifications() {
        let n = UNUserNotificationCenter.current()
        n.requestAuthorization(options: [.alert, .sound, .badge]) {
            granted, error in
            print("result \(granted) \(String(describing: error))")
    
            guard granted else {
                print("not granted!")
                return
            }
    
            DispatchQueue.main.async {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }
    

    4。功能选项卡

    三个

    提防旧文章:那里不再有“开关”。

    5。系留电话,没有模拟器

    它将在模拟器中工作。必须是电话

    系留电话没问题,控制台可以正常工作

    6。最后... WIFI DANCE

    凭借 100% 的可重复性,从 2020 年开始,您必须执行以下操作:

    1. 从绑定的手机中完全删除应用
    2. 构建到手机并从 Xcode 运行 (它肯定行不通)
    3. 强制退出应用
    4. 从绑定的手机中完全删除应用
    5. 同时关闭 wifi/手机
    6. 构建到手机并从 Xcode 运行 (显然它不会起作用)
    7. 强制退出应用

    然后完全按照这个顺序:

    1. 从绑定的手机中完全删除应用
    2. 打开连接(wifi 或手机都可以 - 没问题)
    3. 构建到手机并从 Xcode 运行

    现在可以了。 (并且将从这里开始工作。)

    WIFI DANCE 只是那些奇怪的 Apple 产品之一。他们还没有修复它(Xcode 11.3)。事实上,它已成为“100% 可重复”:你必须跳 WIFI DANCE。

    【讨论】:

      【解决方案5】:

      除了对这个问题的其他居高临下的回答之外,对于已实现所有必需委托方法的知情开发人员来说,发生此问题的最可能原因是他们正在使用通配符配置文件(为什么不呢?它让创建和测试开发应用程序变得如此简单!)

      在这种情况下,您可能会看到错误Error Domain=NSCocoaErrorDomain Code=3000 "no valid 'aps-environment' entitlement string found for application"

      为了测试通知,您实际上必须回到 2000 年及以后,登录 developer.apple.com,并设置启用推送通知的特定于应用程序的配置文件。

      1. 创建与您的应用程序包标识符对应的应用程序 ID。请务必勾选“推送通知”(目前是底部的第二个选项)。
      2. 为该 App ID 创建配置文件。
      3. 完成我们都希望忘记的其余可怕的配置步骤。
      4. ?
      5. 利润!

      【讨论】:

        【解决方案6】:

        确保在您的开发者帐户中正确设置了您的应用 ID 中的推送通知,然后您需要重新生成并下载您的配置文件。我的问题是我下载了配置文件,但 xcode 运行的配置文件不正确。要解决此问题,请转到您的目标构建设置,向下滚动到代码签名,在配置文件部分下确保您使用的是与您生成的名称匹配的正确配置文件(如果您应该有一个带有选项的下拉菜单已安装多个)。

        【讨论】:

          【解决方案7】:

          这是解决方案。

          在 applicationDidFinishLaunchingWithOptions 中:

          {
          
           UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
              UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
              [[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
          }
          
          
          - (void)application:(UIApplication*)application didRegisterUserNotificationSettings:(nonnull UIUserNotificationSettings *)notificationSettings
          {
              [application registerForRemoteNotifications];
          }
          
          
          - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(nonnull NSError *)error
          {
              NSLog(@" Error while registering for remote notifications: %@", error);
          }
          
          - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(nonnull NSData *)deviceToken
          {
            NSLog(@"Device Token is : %@", deviceToken);
          }
          

          【讨论】:

            【解决方案8】:

            @madoa 的答案是绝对正确的。请注意,它在模拟器中不起作用

            在这种情况下

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

            调用时出现错误 REMOTE_NOTIFICATION_SIMULATOR_NOT_SUPPORTED_NSERROR

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-08-21
              • 2015-12-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多