I need device token to implement push notification in my app.
How can I get device token since didRegisterForRemoteNotificationsWithDeviceToken method is not working on iOS 8.
I tried this code in app delegate but it is not giving me device token.
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
Read the code in UIApplication.h.
You will know how to do that.
First:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
add Code like this
#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
if you not using both Xcode 5 and Xcode 6 ,try this code
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];
}
(Thanks for #zeiteisen #dmur 's remind)
Second:
Add this Function
#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
And your can get the deviceToken in
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
if it still not work , use this function and NSLog the error
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
Appending a small validation to #Madao's response in case you are having crashes on older iOS versions:
#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];
What the __IPHONE_8_0 macro does is just allowing you to compile in older versions of xCode/iOS, you don't get compilation errors or warnings, but running the code on devices with iOS 7 or lower will cause a crash.
To get Device token in 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);
}
2020 solution
Six steps,
1. library
2. add to 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. in your app
For example, after user logon
import UserNotifications
and
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. capabilities tab
do three items
beware of old articles: there is no longer an "on switch" there.
5. tethered phone, no simulator
it will not work in simulator. must be a phone
tethered phone is fine, console will work fine
6. and finally ... WIFI DANCE
With 100% repeatability, as of 2020 you MUST do the following:
completely erase app from tethered phone
build to the phone and run from Xcode
(it definitely won't work)
force quit the app
completely erase app from tethered phone
turn off both wifi/cell
build to the phone and run from Xcode
(obviously it won't work)
force quit the app
then in exactly this order:
completely erase app from tethered phone
turn on connectivity (either wifi or cell is fine - no problem)
build to the phone and run from Xcode
It now works. (And will work from here onwards.)
The WIFI DANCE is just one of those weird Apple things. They have not fixed it yet (Xcode 11.3). In fact it has become "100% repeatable": you have to do the WIFI DANCE.
Aside from the rest of the condescending answers to this question, the most likely reason that this issue might occur for an informed developer who has implemented all the required delegate methods is that they are using a wild card provisioning profile (why wouldn't you? It makes it so easy to create and test development apps!)
In this case, you'll probably see the error Error Domain=NSCocoaErrorDomain Code=3000 "no valid 'aps-environment' entitlement string found for application"
In order to test notifications, you actually have to go back to 2000 and late, log into developer.apple.com, and set up your application-specific provisioning profile with push notifications enabled.
Create an App ID corresponding to your app's bundle identifier. Be sure to check off "push notifications" (currently 2nd option from the bottom).
Create a provisioning profile for that App ID.
Go through the rest of the horrible provisioning steps we'd all love to forget.
?
Profit!
On your developer account make sure you have your push notifications setup properly in your app ID and then you need to regenerate and download your provisioning profile. My problem was that I had downloaded the provisioning profile but xcode was running the incorrect one. To fix this go to your Target Build Settings, scroll down to Code Signing, under the provisioning profile section make sure that you are using the correct provisioning profile that matches the name of the one you generated (there should be a dropdown with options if you have installed more than one).
Here is the solution.
in 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);
}
#madoa answer is absolutely correct. Just note that it is not working in the simulator.
In this case
-(void)application:(UIApplication *)application
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
is called with a error REMOTE_NOTIFICATION_SIMULATOR_NOT_SUPPORTED_NSERROR
Related
all.
I want to ask you about push notification settings.
Environments:
MacOS[High Sierra10.13.3]
Xcode9.2(9C40b)
Devices
- iPhone6S[iOS10.3.3]
- iPhoneX [iOS11.2.6]
Language:
Cocos2d-x (Objective-c)
This problem occurs suddenly, and above methods are called before,
so basic settings must have been correctly done such as "Capabilities", "Provisioning Profiles".
And of course, network is connected to wifi.
So now, here is my code snippet.
- (BOOL)application: (UIApplication*)application didFinishLaunchingWithOptions: (NSDictionary*)launchOptions {
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
[[UIApplication sharedApplication] registerForRemoteNotifications];
}];
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[application registerForRemoteNotifications];
}
Also, I try this one.
- (BOOL)application: (UIApplication*)application didFinishLaunchingWithOptions: (NSDictionary*)launchOptions {
UIUserNotificationSettings* setting = [UIUserNotificationSettings settingsForTypes: (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories: nil];
[[UIApplication sharedApplication] registerUserNotificationSettings: setting];
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[application registerForRemoteNotifications];
}
I can see push notification dialog when app is launched, push allow or deny button, requestAuthorizationWithOptions callback is invoked, but nothing happens.
I repeatedly uninstall and install app, but nothing changed.
Added(14/03/2018 18:53)
I create new test project and use the same bundle identifier and Provisioning Profiles.
Then, didRegisterForRemoteNotificationsWithDeviceToken is invoked correctly.
So, maybe configuration of Provisioning Profiles and AppID are ok, my project's setting is incorrect...
If the project is targeting iOS version 10.0+, Apple recommends utilizing the new method for asking for notification permissions:
requestAuthorizationWithOptions:completionHandler:
https://developer.apple.com/documentation/usernotifications/unusernotificationcenter/1649527-requestauthorizationwithoptions?language=objc
I am facing issue while generating the device token with the real device.
I am debugging device and device token is not generating.
Sometimes it works and sometimes not.
Please let me know what could be issue.
Thanks
Did you put below in didFinishLaunchingWithOptions of AppDelegate.m?
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
NSLog(#"ios8 app");
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
else
{
NSLog(#"lower ios8 app");
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
}
As of now, I, too, am having trouble getting device tokens.
My projects stopped generating device tokens when it was "erased" and "installed" around 10 hours ago.
Also in the Korean iOS Developers forum, some people have been reporting problems with APNS tokens not generating in the past 10 hours.
There may be something wrong with some of the sandbox APNS servers.
Last checked time
2016-04-27 22:43 PM +0900 GMT : No device token, Push Notification Not Arriving.
Add this method,
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError)
{
print("application:didFailToRegisterForRemoteNotificationsWithError: %#", error)
}
You will get answer, why token is not generated.
#GopalDevra could you be more clear? Anyway, I have this code for Parse, maybe it's not your case, but you can get the idea.
You can use didRegisterForRemoteNotificationsWithDeviceToken in AppDelegate.m like:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// Store the deviceToken in the current installation and save it to Parse.
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:deviceToken];
currentInstallation.channels = #[ #"global" ];
[currentInstallation saveInBackground];
}
Edited
Have you put this in didFinishLaunchingWithOptions?
// - Push notifications
// -- Register for Push Notitications
UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert |
UIUserNotificationTypeBadge |
UIUserNotificationTypeSound);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes
categories:nil];
[application registerUserNotificationSettings:settings];
[application registerForRemoteNotifications];
//-- Set Notification
if ([application respondsToSelector:#selector(isRegisteredForRemoteNotifications)])
{
// iOS 8 Notifications
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[application registerForRemoteNotifications];
}
else
{
// iOS < 8 Notifications
[application registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
}
//--- your custom code
I need device token to implement push notification in my app as before I am getting the device token from didRegisterForRemoteNotificationsWithDeviceToken method but recently it does not work.
For more information please find the below code in didFinishLaunchingWithOptions method.
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];
}
And also I had added the delegate didRegisterUserNotificationSettings.
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
if (notificationSettings.types != UIUserNotificationTypeNone) {
NSLog(#"didRegisterUser");
[application registerForRemoteNotifications];
}
}
Thank you for such a prompt response in advance, I wish I could be clearer on my issue.
Any help is much appreciated.
I am facing same issue. I found some solution during searching as the WWDR intermediate certificate just expired (February 14, 2016). It may cause the issue.
you can try following steps :
In Keychain Access. View -> Show Expired Certificates. Delete expired certificate.
Download new WWDR certificate from your developer account.
Also there are couple of known issue listed by Apple. please refer below link : https://developer.apple.com/support/certificates/expiration/
I have integrated apple push notification and facing a strange problem in my application. when I directly install the application via Xcode through usb connection then the device token is being generate stored in database correctly and push notification is working fine. but when I create IPA and install the app via created ipa in the same device then the device token is getting generated wrong and push notification is not working. Below is my code:
if ([[UIApplication sharedApplication] respondsToSelector:#selector(registerUserNotificationSettings:)]) {
[[UIApplication sharedApplication] registerUserNotificationSettings: [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
} else {
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
}
application.applicationIconBadgeNumber = 0;
#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings
*)notificationSettings {
[application registerForRemoteNotifications];
}
#endif
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData
*)deviceToken {
const unsigned *tokenData = deviceToken.bytes;
NSString *deviceTokenString = [NSString stringWithFormat:#"%08x%08x%08x%08x%08x%08x%08x%08x", ntohl(tokenData[0]),ntohl(tokenData[1]),ntohl(tokenData[2]),ntohl(tokenData[3]),ntohl(tokenData[4]),ntohl(tokenData[5]),ntohl(tokenData[6]),ntohl(tokenData[7])];
[[NSUserDefaults standardUserDefaults]setObject:deviceTokenString forKey:#"devicetoken"];
NSLog(#"Device Token = %#", deviceTokenString);
}
//Failed to Register for Remote Notifications
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(#"Error in registration. Error: %#", error);
}
The device Token depends on the certificate you signed your application with. If you install directly it is the dev-certificate, while when signing for AdHoc it is a distribution certificate. For push you need a corresponding distribution or development certificate packed on your server.
Been stuck on this forever, but could not get the following methods to be called. I am able to get the phone to ask for permission but after that it gets stuck.
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
NSLog(#"My token is: %#", deviceToken);
}
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
NSLog(#"Failed to get token, error: %#", error);
}
I have tried quite a few things including:
1) everything offered in the following stackoverflow post: why didRegisterForRemoteNotificationsWithDeviceToken is not called
2) Looking at this technical note from Apple: https://developer.apple.com/library/ios/technotes/tn2265/_index.html
3) This entire tutorial: http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1 (so hopefully my certificates are all good)
4) (And yes I have internet connection)
Does anyone have any possible solutions? I have been rattling my brains out for the last 2-3 days and have already had to factory reset my phone twice, as well as change the date on my phone N^e number of times in order to get the notification popup to appear to test over and over again.
Would love any help! Thanks!
Here is what I am using to call... (tried a few other versions):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//other stuff not related
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
#ifdef __IPHONE_8_0
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert) categories:nil];
[application registerUserNotificationSettings:settings];
[application registerForRemoteNotifications];
#endif
} else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
return YES;
}
iOS 8 introduced a change in the flow of registration that requires explicitly asking to register remote notifications after getting permission from the user.
You are calling this code?
[[UIApplication sharedApplication] registerUserNotificationSettings: settings];
And implementing this in your Application Delegate?
- (void) application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[application registerForRemoteNotifications];
}
That said, the old APIs are now deprecated but are still required if you plan to support iOS 7. To support both you can check to see if UIApplication responds to the new selector:
if ([[UIApplication sharedApplication] respondsToSelector:#SEL(registerUserNotificationSettings:)]) {
// iOS 8
[[UIApplication sharedApplication] registerUserNotificationSettings: settings];
// [[UIApplication sharedApplication] registerForRemoteNotifications]
// will be called in your UIApplicationDelegate callback
} else {
// iOS 7
[[UIApplication sharedApplication] registerForRemoteNotifications];
}