92

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.

klefevre
  • 8,595
  • 7
  • 42
  • 71
Jag
  • 967
  • 1
  • 7
  • 11
  • What you mean by console? Simulator? BTW push notification wont work on simulator – KingofBliss Jan 10 '12 at 08:42
  • Also try printing the value of str – KingofBliss Jan 10 '12 at 08:44
  • Did you follow [all the steps](http://stackoverflow.com/questions/8075255/push-notification-for-development-certificate/8075436#8075436)? If you are not having any problem with certification and provision as well as code then you must be doing some small mistake. Like..tell me, are you running the app on real device attaching the same with your system? Also are you noticing whether you are getting the device token in console log or not? [Have you enable Push notification in iPhone](http://ipod.about.com/od/iphonehowtos/ht/enable-push-notifications.htm)? – Yama Jan 10 '12 at 06:10
  • I am not able to get device token on console log. – Jag Jan 10 '12 at 06:41
  • I am running the app on real device with out any error. – Jag Jan 10 '12 at 06:43
  • Did you enable APNS as shown in the link on iPhone? – Yama Jan 10 '12 at 06:46
  • yes i enabled APNS..but the device token is not able to fetch on cosole – Jag Jan 10 '12 at 06:51
  • - (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken { } method is not running at all. when i see in settings my application is enable for push notification that means it is registered but m not able to see the device token on console. – Jag Jan 10 '12 at 07:31
  • Do 1 thing : check this link : http://mobiforge.com/developing/story/programming-apple-push-notification-services Then follow all the steps accordingly. Your problem must resolve – Yama Jan 10 '12 at 07:38
  • Unclocked iphone are able to get device token? – Jag Jan 10 '12 at 09:40
  • yes..mine is also unlocked and I am getting the same. – Yama Jan 10 '12 at 09:51

16 Answers16

166

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)")
}
Community
  • 1
  • 1
Wasif Saood
  • 1,998
  • 1
  • 11
  • 12
  • 5
    Then please check your provisioning profile,it should be of that app ID by which you have created your ssl certifcate for push notification. – Wasif Saood Jan 10 '12 at 07:55
  • 1
    you need to add the code into AppDelegate file @jagzzz – codercat Dec 08 '15 at 07:03
  • 2
    For those interested in a code example writtent in Swift: https://gist.github.com/sawapi/a7cee65e4ad95578044d – Benjamin Jan 12 '16 at 16:53
  • 3
    Careful, using the "description" property no longer works: http://stackoverflow.com/questions/39495391/swift-3-device-tokens-are-now-being-parsed-as-32bytes – hariseldon78 Nov 16 '16 at 15:11
  • 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. https://gist.github.com/sawapi/a7cee65e4ad95578044d#gistcomment-1458043 – Gkiokan Oct 31 '18 at 16:28
  • Objective C method is broken from Xcode 11 onwards. I have edited the answer as it is widely accepted answer. – codester Sep 11 '19 at 07:02
  • I posted an answer of how to write this in xamarin/c#: https://stackoverflow.com/questions/58027344/how-to-get-device-token-in-ios-13-with-xamarin – axlrtr Sep 20 '19 at 12:51
  • 1
    @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.*)? – Pradip Sutariya Sep 27 '19 at 06:21
  • 1
    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 – Jake Cronin Sep 28 '19 at 19:35
  • 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? – Tim Christmann Sep 30 '19 at 09:20
  • @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. – Heitor Nov 26 '19 at 02:27
  • What about swift ios +13? – newswiftcoder Jul 03 '20 at 15:48
  • Just wanted to give the credit of the iOS 13+ solution to Andrey Gagan below. – CodeBrew Feb 24 '21 at 19:36
13

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);
}
Irfan
  • 4,301
  • 6
  • 29
  • 46
Bkillnest
  • 722
  • 9
  • 16
13

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()
emma ray
  • 13,336
  • 1
  • 24
  • 50
9

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);
}
Jake Cronin
  • 1,002
  • 13
  • 15
6

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.

Andrey Gagan
  • 1,338
  • 13
  • 13
  • 1
    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. – rmaddy Sep 11 '19 at 16:24
5

And the Swift version of the Wasif's answer:

Swift 2.x

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

Update for Swift 3

let deviceTokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
Antoine
  • 23,526
  • 11
  • 88
  • 94
5

Following code is use for the retrive the device token.

    // 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);
Nimit Parekh
  • 16,776
  • 8
  • 50
  • 72
4

If you are still not getting device token, try putting following code so to register your device for push notification.

It will also work on ios8 or more.

#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
Doug Smith
  • 29,668
  • 57
  • 204
  • 388
Nilesh
  • 438
  • 5
  • 15
1

In your AppDelegate, in the didRegisterForRemoteNotificationsWithDeviceToken method:

Updated for Swift:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    print("\(deviceToken.reduce("") { $0 + String(format: "%02.2hhx", arguments: [$1]) })")
}
vfn
  • 6,026
  • 2
  • 34
  • 45
1

Get device token in Swift 3

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

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

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

}
Sedat Y
  • 561
  • 5
  • 6
0

Swift 4 This works for me:

Step 1 into TARGETS Click on add capability and select Push Notifications

Step 2 in AppDelegate.swift add the following code:

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)")
    }
James Ryan
  • 61
  • 1
0

For Objective-C

There are some changes for the iOS 13 push token

- (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);
}
Ruchin Somal
  • 1,073
  • 12
  • 14
0

Use the following code to get device token:

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

You can reach Netmera Guide for push payloads and to get more push notification information.

ecem
  • 11
  • 3
-1

In a build setting set code signing Provision Profile if you have APN Enable certificate then you will definitely get the token id. and remove

Provision Profile : Automatic

and set to

Provision Profile : Your provision profile certificate.

kalpesh
  • 1,285
  • 1
  • 17
  • 30
-2
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    let tokenParts = deviceToken.map { data -> String in
        return String(format: "%02.2hhx", data)
        }
    let token = tokenParts.joined()

    print("Token\(token)")
}
Nikos Hidalgo
  • 3,666
  • 9
  • 25
  • 39
-4

In order to get the device token use following code but you can get the device token only using physical device. If you have mandatory to send the device token then while using simulator you can put the below condition.

  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"];
}
Nawrez
  • 3,314
  • 8
  • 28
  • 42
Yash
  • 171
  • 2
  • 8