Получите токен устройства для push-уведомления

Я работаю над push-уведомлениями. Я написал следующий код для получения токена устройства.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    // Override point for customization after application launch.

    // Add the view controller's view to the window and display.
    [self.window addSubview:viewController.view];
    [self.window makeKeyAndVisible];

    NSLog(@"Registering for push notifications...");    
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

    return YES;
}

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 
    NSString *str = [NSString stringWithFormat:@"Device Token=%@",deviceToken];
    NSLog(@"This is device token%@", deviceToken);
}

- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { 
    NSString *str = [NSString stringWithFormat: @"Error: %@", err];
    NSLog(@"Error %@",err);    
}

Я могу успешно запустить приложение на устройстве, но не могу получить идентификатор устройства на консоли.

У меня нет проблем с сертификацией и профилями подготовки.


person jagzzz    schedule 10.01.2012    source источник
comment
Вы выполнили все шаги? Если у вас нет проблем с сертификацией и предоставлением, а также с кодом, вы, должно быть, делаете небольшую ошибку. Например, скажите мне, вы запускаете приложение на реальном устройстве, подключенном к вашей системе? Также вы замечаете, получаете ли вы токен устройства в журнале консоли или нет? Включили ли вы push-уведомления в iPhone?   -  person Yama Puvar    schedule 10.01.2012
comment
Я не могу получить токен устройства в журнале консоли.   -  person jagzzz    schedule 10.01.2012
comment
Я запускаю приложение на реальном устройстве без ошибок.   -  person jagzzz    schedule 10.01.2012
comment
Вы включили APNS, как показано в ссылке на iPhone?   -  person Yama Puvar    schedule 10.01.2012
comment
да, я включил APNS .. но токен устройства не может быть получен на cosole   -  person jagzzz    schedule 10.01.2012
comment
- (void) application: (UIApplication *) app didRegisterForRemoteNotificationsWithDeviceToken: (NSData *) метод devToken {} вообще не работает. когда я вижу в настройках, что мое приложение включено для push-уведомлений, это означает, что оно зарегистрировано, но не может видеть токен устройства на консоли.   -  person jagzzz    schedule 10.01.2012
comment
Сделайте одно: проверьте эту ссылку: mobiforge.com/developing/story/ Затем выполните все шаги соответствующим образом. Ваша проблема должна быть решена   -  person Yama Puvar    schedule 10.01.2012
comment
Что вы подразумеваете под консолью? Симулятор? BTW push-уведомление не будет работать на симуляторе   -  person KingofBliss    schedule 10.01.2012
comment
Также попробуйте распечатать значение str   -  person KingofBliss    schedule 10.01.2012
comment
Разблокированный iphone может получить токен устройства?   -  person jagzzz    schedule 10.01.2012
comment
да .. шахта тоже разблокирована и я получаю то же самое.   -  person Yama Puvar    schedule 10.01.2012


Ответы (14)


ПРИМЕЧАНИЕ. Приведенное ниже решение больше не работает на устройствах iOS 13+ - он вернет данные мусора.

Вместо этого используйте следующий код:

+ (NSString *)hexadecimalStringFromData:(NSData *)data
{
  NSUInteger dataLength = data.length;
  if (dataLength == 0) {
    return nil;
  }

  const unsigned char *dataBuffer = (const unsigned char *)data.bytes;
  NSMutableString *hexString  = [NSMutableString stringWithCapacity:(dataLength * 2)];
  for (int i = 0; i < dataLength; ++i) {
    [hexString appendFormat:@"%02x", dataBuffer[i]];
  }
  return [hexString copy];
}

Решение, которое работало до iOS 13:

Цель-C

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 
{
    NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"this will return '32 bytes' in iOS 13+ rather than the token", token);
} 

Swift 3.0

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
{
    let tokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
    print("this will return '32 bytes' in iOS 13+ rather than the token \(tokenString)")
}
person Wasif Saood    schedule 10.01.2012
comment
Затем проверьте свой профиль обеспечения, он должен соответствовать идентификатору приложения, с помощью которого вы создали сертификат ssl для push-уведомлений. - person Wasif Saood; 10.01.2012
comment
вам нужно добавить код в файл AppDelegate @jagzzz - person codercat; 08.12.2015
comment
Для тех, кто интересуется примером кода, написанным на Swift: gist.github.com/sawapi/a7cee65e4ad95578044d - person Benjamin; 12.01.2016
comment
Будьте осторожны, использование свойства description больше не работает: stackoverflow.com/questions/39495391/ - person hariseldon78; 16.11.2016
comment
Вы также должны предоставить настройки уведомлений, без этого у меня это не сработало. Для Swift 4 с xCode 9.x вы также можете проверить этот фрагмент кода. gist.github.com/sawapi/a7cee65e4ad95578044d#gistcomment-1458043 - person Gkiokan; 31.10.2018
comment
Метод Objective C нарушен с Xcode 11 и далее. Я отредактировал ответ, так как это широко распространенный ответ. - person codester; 11.09.2019
comment
Я опубликовал ответ о том, как написать это в xamarin / c #: stackoverflow.com/questions/58027344/ - person axlrtr; 20.09.2019
comment
@codester Я загрузил свою сборку с помощью Xcode 10.3, и она работает. Согласно вашему заявлению, метод Objective C будет нарушен XCode 11, но то, что я вижу в нашей базе данных, показывает длину данных вместо правильной строки токена apns. Поэтому я просто хочу знать, зависит ли это от версии Xcode или версии iOS (например, 13. *)? - person pradip sutariya; 27.09.2019
comment
Обновленное решение iOS 13+ было бы лучше, если бы его можно было копировать + вставлять! В настоящее время это только частичное решение, и его сложно использовать тем, кто не понимает синтаксис Obj C - person Jake Cronin; 28.09.2019
comment
Я думаю, что это предложение в связанной статье nshipster следует добавить к ответу, чтобы прояснить ситуацию: часть ... этот подход не будет работать в приложениях, скомпилированных с помощью iOS 13 SDK. Это немного отличается от приведенного ниже решения больше не работает на устройствах iOS 13+. Таким образом, приложение, которое не требует обновления с помощью xCode 11 и iOS13 SDK, может отправлять действительный токен. Или я здесь не прав? - person Tim Christmann; 30.09.2019
comment
@JakeCronin Я согласен с вами. Что ж, после долгих усилий я узнал, как это сделать: в вашем методе AppDelegate.m didRegisterForRemoteNotificationsWithDeviceToken просто передайте глобально NSData deviceToken, а затем используйте с ним пример ObjectiveC. Другими словами, перестаньте использовать описание NSString. - person Heitor; 26.11.2019
comment
А как насчет swift ios +13? - person newswiftcoder; 03.07.2020
comment
Просто хотел отдать должное Андрею Гагану за решение iOS 13+. - person CodeBrew; 24.02.2021

Чтобы получить Token Device, вы можете выполнить несколько шагов:

1) Включите APNS (Apple Push Notification Service) как для сертификации разработчиков, так и для распространения сертификатов, затем повторно загрузите эти два файла.

2) Повторно загрузите файл подготовки разработчика и файл подготовки распространения.

3) В интерфейсе Xcode: настройка обеспечения для PROJECT и TARGETS с двумя загрузками файлов.

4) Наконец, вам нужно добавить приведенный ниже код в файл AppDelegate, чтобы получить Token Device (примечание: запустите приложение на реальном устройстве).

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
     [self.window addSubview:viewController.view];
     [self.window makeKeyAndVisible];

     NSLog(@"Registering for push notifications...");    
     [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
 (UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
     return YES;
}

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 
     NSString *str = [NSString stringWithFormat:@"Device Token=%@",deviceToken];
     NSLog(@"%@", str);
}

- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { 
     NSString *str = [NSString stringWithFormat: @"Error: %@", err];
     NSLog(@"%@",str);
}
person Bkillnest    schedule 27.05.2013

Использование description, как предлагают многие из этих ответов, - это неправильный подход, даже если вы заставите его работать , он сломается в iOS 13+.

Вместо этого вы должны убедиться, что используете фактические двоичные данные, а не просто их описание. Андрей Гаган неплохо справился с решением Objective C, но, к счастью, в Swift все намного проще:

Swift 4.2 работает в iOS 13+.

// credit to NSHipster (see link above)
// format specifier produces a zero-padded, 2-digit hexadecimal representation
let deviceTokenString = deviceToken.map { String(format: "%02x", $0) }.joined()
person chris stamper    schedule 17.09.2019

Objective C для iOS 13+, предоставлено ответом Васифа Сауда

Скопируйте и вставьте приведенный ниже код в AppDelegate.m, чтобы распечатать токен APN устройства.

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
  NSUInteger dataLength = deviceToken.length;
  if (dataLength == 0) {
    return;
  }
  const unsigned char *dataBuffer = (const unsigned char *)deviceToken.bytes;
  NSMutableString *hexString  = [NSMutableString stringWithCapacity:(dataLength * 2)];
  for (int i = 0; i < dataLength; ++i) {
    [hexString appendFormat:@"%02x", dataBuffer[i]];
  }
  NSLog(@"APN token:%@", hexString);
}
person Jake Cronin    schedule 28.09.2019

Следующий код используется для извлечения токена устройства.

    // Prepare the Device Token for Registration (remove spaces and < >)
    NSString *devToken = [[[[deviceToken description] 
                            stringByReplacingOccurrencesOfString:@"<"withString:@""] 
                           stringByReplacingOccurrencesOfString:@">" withString:@""] 
                          stringByReplacingOccurrencesOfString: @" " withString: @""];


    NSString *str = [NSString 
                     stringWithFormat:@"Device Token=%@",devToken];
    UIAlertView *alertCtr = [[[UIAlertView alloc] initWithTitle:@"Token is " message:devToken delegate:self cancelButtonTitle:nil otherButtonTitles: nil] autorelease];
    [alertCtr show];
    NSLog(@"device token - %@",str);
person Nimit Parekh    schedule 10.01.2012
comment
Это никогда не было правильным решением. Никогда ничего не основывайте на description. - person rmaddy; 11.09.2019

И Swift-версия ответа Васифа:

Swift 2.x

var token = deviceToken.description.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "<>"))
token = token.stringByReplacingOccurrencesOfString(" ", withString: "")
print("Token is \(token)")

Обновление для Swift 3

let deviceTokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
person Antoine    schedule 30.08.2016
comment
Никогда не используйте description для двоичных данных (см. Любой другой ответ) - person chris stamper; 17.09.2019

Начиная с iOS 13 Apple изменила [deviceToken description]output. Теперь это похоже на {length=32,bytes=0x0b8823aec3460e1724e795cba45d22e8...af8c09f971d0dabc}, что неверно для токена устройства.

Я предлагаю использовать этот фрагмент кода для решения проблемы:

+ (NSString *)stringFromDeviceToken:(NSData *)deviceToken {
    NSUInteger length = deviceToken.length;
    if (length == 0) {
        return nil;
    }
    const unsigned char *buffer = deviceToken.bytes;
    NSMutableString *hexString  = [NSMutableString stringWithCapacity:(length * 2)];
    for (int i = 0; i < length; ++i) {
        [hexString appendFormat:@"%02x", buffer[i]];
    }
    return [hexString copy];
}

Он будет работать на iOS13 и ниже.

person Andrey Gagan    schedule 10.09.2019
comment
К вашему сведению - любой ответ, который когда-либо использовал description, всегда был неправильным. И это только одно из возможных решений для преобразования токена в строку. Гораздо более простое решение - преобразовать NSData в NSString с использованием стандартной кодировки base64. - person rmaddy; 11.09.2019

Если вы по-прежнему не получаете токен устройства, попробуйте ввести следующий код, чтобы зарегистрировать устройство для push-уведомлений.

Он также будет работать на ios8 или более поздних версиях.

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000

    if ([UIApplication respondsToSelector:@selector(registerUserNotificationSettings:)]) {
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeAlert|UIUserNotificationTypeSound
                                                                                 categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    } else {
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         UIRemoteNotificationTypeBadge |
         UIRemoteNotificationTypeAlert |
         UIRemoteNotificationTypeSound];

    }
#else
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     UIRemoteNotificationTypeBadge |
     UIRemoteNotificationTypeAlert |
     UIRemoteNotificationTypeSound];

#endif
person Nilesh    schedule 10.04.2015

Получите токен устройства в Swift 3

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})

    print("Device token: \(deviceTokenString)")

}
person Sedat Y    schedule 29.11.2016

В вашем AppDelegate в методе didRegisterForRemoteNotificationsWithDeviceToken:

Обновлено для Swift:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    print("\(deviceToken.reduce("") { $0 + String(format: "%02.2hhx", arguments: [$1]) })")
}
person vfn    schedule 26.11.2014

Swift 4 У меня работает:

Шаг 1 в ЦЕЛИ. Нажмите "Добавить возможность" и выберите Push-уведомления.

Шаг 2 в AppDelegate.swift добавьте следующий код:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
     
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound]) { (didAllow, error) in
            
        }
        UIApplication.shared.registerForRemoteNotifications()
        
        return true
    }
    
    //Get device token
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
    {
        let tokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
        
        print("The token: \(tokenString)")
    }
person James Ryan    schedule 18.08.2020

Для Objective-C

Есть некоторые изменения для push-токена iOS 13.

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *token = @"";
        if (@available(iOS 13, *)) {
        NSUInteger length = deviceToken.length;
        if (length == 0) {
            token = @"";
        }
        const unsigned char *buffer = deviceToken.bytes;
        NSMutableString *actualToken  = [NSMutableString stringWithCapacity:(length * 2)];
        for (int i = 0; i < length; ++i) {
            [actualToken appendFormat:@"%02x", buffer[i]];
        }
        token = [actualToken copy];
        } else {
            token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
                token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
        }
        NSLog(@"My token is: %@", token);
}
person Ruchin Somal    schedule 31.03.2021

В настройках сборки установите профиль подписи кода, если у вас есть сертификат APN Enable, тогда вы обязательно получите идентификатор токена. и удалить

Профиль предоставления: автоматический

и установить на

Профиль обеспечения: ваш сертификат профиля обеспечения.

person kalpesh    schedule 31.10.2015

Чтобы получить токен устройства, используйте следующий код, но вы можете получить токен устройства только с помощью физического устройства. Если у вас есть обязательная отправка токена устройства, то при использовании симулятора вы можете поставить следующее условие.

  if(!(TARGET_IPHONE_SIMULATOR))
    {
        [infoDict setValue:[[NSUserDefaults standardUserDefaults] valueForKey:@"DeviceToken"] forKey:@"device_id"];
    }
    else
    {
        [infoDict setValue:@"e79c2b66222a956ce04625b22e3cad3a63e91f34b1a21213a458fadb2b459385" forKey:@"device_id"];
    }



- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
    NSLog(@"My token is: %@", deviceToken);
    NSString * deviceTokenString = [[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""] stringByReplacingOccurrencesOfString: @">" withString: @""]   stringByReplacingOccurrencesOfString: @" " withString: @""];
    NSLog(@"the generated device token string is : %@",deviceTokenString);
    [[NSUserDefaults standardUserDefaults] setObject:deviceTokenString forKey:@"DeviceToken"];
}
person Yash    schedule 28.12.2017