Get device token for push notification

212,592

Solution 1

NOTE: The below solution no longer works on iOS 13+ devices - it will return garbage data.

Please use following code instead:

+ (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];
}

Solution that worked prior to iOS 13:

Objective-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)")
}

Solution 2

To get Token Device you can do by some steps:

1) Enable APNS (Apple Push Notification Service) for both Developer Certification and Distribute Certification, then redownload those two file.

2) Redownload both Developer Provisioning and Distribute Provisioning file.

3) In Xcode interface: setting provisioning for PROJECT and TARGETS with two file provisioning have download.

4) Finally, you need to add the code below in AppDelegate file to get Token Device (note: run app in real 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);
}

Solution 3

Using description as many of these answers suggest is the wrong approach - even if you get it to work, it will break in iOS 13+.

Instead you should ensure you use the actual binary data, not simply a description of it. Andrey Gagan addressed the Objective C solution quite well, but fortunately it's much simpler in swift:

Swift 4.2 works in 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()

Solution 4

Objective C for iOS 13+, courtesy of Wasif Saood's answer

Copy and paste below code into AppDelegate.m to print the device APN token.

- (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);
}

Solution 5

Starting from iOS 13 Apple has changed [deviceToken description]output. Now it is like this {length=32,bytes=0x0b8823aec3460e1724e795cba45d22e8...af8c09f971d0dabc} which is incorrect for device token.

I suggest to use this code snippet to resolve a problem:

+ (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];
}

It will work for iOS13 and lower.

Share:
212,592
jagzzz
Author by

jagzzz

Updated on March 31, 2021

Comments

  • jagzzz
    jagzzz about 3 years

    I am working on push notifications. I wrote the following code for fetching a device token.

    - (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);    
    }
    

    I am able to run application on device successfully but not able to get the device id on console.

    I have no issues with certification and provisioning profiles.

  • Wasif Saood
    Wasif Saood over 12 years
    Then please check your provisioning profile,it should be of that app ID by which you have created your ssl certifcate for push notification.
  • codercat
    codercat over 8 years
    you need to add the code into AppDelegate file @jagzzz
  • Benjamin
    Benjamin over 8 years
    For those interested in a code example writtent in Swift: gist.github.com/sawapi/a7cee65e4ad95578044d
  • hariseldon78
    hariseldon78 over 7 years
    Careful, using the "description" property no longer works: stackoverflow.com/questions/39495391/…
  • Gkiokan
    Gkiokan over 5 years
    You have to provide the Notification Settings also, without it didn't worked for me. For Swift 4 with xCode 9.x you can also check this code snipped. gist.github.com/sawapi/a7cee65e4ad95578044d#gistcomment-1458‌​043
  • codester
    codester almost 5 years
    Objective C method is broken from Xcode 11 onwards. I have edited the answer as it is widely accepted answer.
  • rmaddy
    rmaddy almost 5 years
    This has never been the correct solution. Never base anything on the description.
  • rmaddy
    rmaddy almost 5 years
    FYI - any answer that ever used description was always wrong. And this is only one possible solution to convert the token to a string. A much simpler solution is to convert the NSData to an NSString using standard base64 encoding.
  • chris stamper
    chris stamper almost 5 years
    Never use description on binary data (see any other answer)
  • axlrtr
    axlrtr almost 5 years
    I posted an answer of how to write this in xamarin/c#: stackoverflow.com/questions/58027344/…
  • Pradip Sutariya
    Pradip Sutariya almost 5 years
    @codester I had uploaded my build using Xcode 10.3 and it is live. As per your statement, the Objective C method is going to broken onward XCode 11 but what I can see in our database it is showing the data length instead of a correct string of apns token. So I just want to know that, Is it depending on Xcode version or iOS version (i.e 13.*)?
  • Jake Cronin
    Jake Cronin over 4 years
    The updated iOS 13+ solution would be better if it was copy+pasteable! It is currently only a partial solution, and tough to use by those who do not understand Obj C syntax
  • Tim Christmann
    Tim Christmann over 4 years
    I think this sentence in the linked nshipster article should be added to the answer to make the situation a bit more clear: The part "... this approach won’t work in apps compiled with the iOS 13 SDK". This is a bit different to "The below solution no longer works on iOS 13+ devices" So an app that needs no update with xCode 11 and iOS13 SDK can still send a valid token. Or am I wrong here?
  • Heitor
    Heitor over 4 years
    @JakeCronin I agree with you. Well, after a lot of struggling, I found out how to do it: in your AppDelegate.m didRegisterForRemoteNotificationsWithDeviceToken method, just pass globally the NSData deviceToken, then use the ObjectiveC example with it. In other words, stop using the NSString description.
  • newswiftcoder
    newswiftcoder almost 4 years
    What about swift ios +13?
  • CodeBrew
    CodeBrew over 3 years
    Just wanted to give the credit of the iOS 13+ solution to Andrey Gagan below.