APNS rejects notification with reason "DeviceTokenNotForTopic" - ios

I'm receiving this error only when trying to register for remote notifications using UserNotifications framework.
When using PushKit everything works ok.
dispatch_queue_t mainQueue = dispatch_get_main_queue();
// Create a push registry object
self.voipRegistry = [[PKPushRegistry alloc] initWithQueue: mainQueue];
// Set the registry's delegate to self
self.voipRegistry.delegate = self;
// Set the push type to VoIP
self.voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
Since Xcode 11 and iOS13 there are changes in PushKit to support CallKit, so I'm trying to use UserNotifications instead, as described in Apple's documentation
Important
If you are unable to support CallKit in your app, you cannot use PushKit to handle push notifications. Instead, configure your app's push notification support with the UserNotifications framework.
I'm registering for remote notifications this way
- (BOOL) application:(UIApplication*) application didFinishLaunchingWithOptions:(NSDictionary*) launchOptions
{
[[UIApplication sharedApplication] registerForRemoteNotifications];
And receiving token:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
But when I'm sending notification from my server, I get DeviceTokenNotForTopic.
I'm not sure, if UserNotifications framework uses different APNs server or token format is different.

APNS sends such error if bundleID of your app different from the apns-topic that you are sending from the server in request for voip push.
Or a certificate for a voip push is generated for another bundleID.
Error code https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html
More discussions here. https://github.com/QuickBlox/quickblox-ios-sdk/issues/1020

For me, I had changed the app's name and bundle ID and I hadn't renewed the device token and the certificate for notifications with images.
To solve that, I firstly went to the Certificates, Identifiers & Profiles section of my Apple Developer account and generated a new certificate with the AppGroups Capability.
Then I got a new device token in the calling of the AppDelegate's function
application( _ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
After getting the token from the deviceToken parameter and using it for sending the notification, it started working again.

if u r facing devicetokennotfortopic
then just try this
topic should be your bundle id of u r application
i fixed my issue
ex this is u r bundle id
com.app.xxx.SumNotService
i have removed SumNotService
com.app.xxx(this worked for me)
try

Related

Firebase push notification in iOS

I am implementing Push Notification for iOS using Firebase. I have followed all the steps mentioned over there for push notifications.
When I try to send a message from Firebase server to my app, I get the error in server saying Unregistered registration token.
I am using the token generated in the app. Using this code to get the token :
[FIRApp configure];
NSString *refreshedToken = [[FIRInstanceID instanceID] token];
The Not Registered happens when GCM thinks the device could not handle the message. This happens if the app is uninstalled or misconfigured to handle the message, try uninstalling app manually from phone and run it again
In my app this line was in an If condition, so not called it always.
[[UIApplication sharedApplication] registerForRemoteNotifications];

How to debug Notifications on iOS With Firebase

I have followed the tutorial to setup Notifications on iOS and I have checked that in the application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken token: NSData) function that a FCM token was available FIRInstanceID.instanceID().token().
From the Firebase Console I tried to send a notification (status is Completed) but no notification was received on my iOS Device.
In order to check the 'Apple side', I have uploaded y push notification certificates into another Push Notification Service Provided and it works.
So I would like to know how can I debug my application?

didFinishLaunchingWithOptions not Showing Initial Alert (PubNub)

I am trying to create a PushNotification app and I am working with PubNub. I have gone through all of the necessary steps to:
Include PubNub libraries on my workspace
Create the proper provisioning profile for the App
Ensured PushNotification was in the profile
Create the proper SSL certificate for the app
Add the certificate to the keychain access
Create the proper .pem file
Uploaded the file to PubNub
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( NSDictionary *)launchOptions
{
// #2 Register client for push notifications
NSLog(#" Options set");
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
[PubNub setDelegate:self];
return YES;
}
After getting some initial compile errors, I was able run the app on my device. When I ran the app on my device, I did not receive the "...Would Like To Send Yo Push Notifications" message as I thought I should. I am able to use the PubNun console to send a message and I see the messages are received via the log, but I do not get any notification or banner. I placed an NSLog in the didFinishLaunchingWithOptions method and I see the display in the log.
After that, I deleted the app from the device, deleted the provisioning profile form the device, restated Xcode, and compile and an again with the same results. Not sure what to try next.
EDIT: The specific problem you're running into has to do with the fact that you are running the application through Xcode, and in a nutshell you can't test production push notifications this way, you'd have to use the sandbox push server and certs. If you want to test prod pushes you'll need to distribute the application signed with an Ad Hoc provisioning profile. I'm sure there are a million ways to do this, but actually my two favorites are using Testflight and Crashlytics' new Beta feature, that allows you to distribute ad hoc builds to devices basically using a single line of code, automatically once you archive a new build. I would recommend Crashlytics because it also automatically handles extremely useful analytics as well as crash reporting.
If you are referring to the initial push notifications permissions pop-up, that will only be displayed once or the lifetime of the application. The ONLY way I believe to get around this is to uninstall the up and leave it uninstalled for 3 days (I believe this is the limit).
I'm unfortunately not familiar with PubNub, but in your application are you registering for push notifications and receiving a device token?
Kevin,
If this is all what you try to do, to receive notifications using PubNub service, than it is not enough.
After you receive device push notification token, you need to pass it to PubNub client library, for example like this with default configuration:
- (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Initialise PubNub client.
// Warning, you should use pub/sub/secret keys for your account (at admin.pubnub.com) to
// which you uploaded your development push notification certificate (in .pem file).
[PubNub setupWithConfiguration:[PNConfiguration defaultConfiguration] andDelegate:self];
[PubNub connect];
UIRemoteNotificationType type = (UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound);
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:type];
return YES;
}
- (void) application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[PubNub enablePushNotificationsOnChannel:[PNChannel channelWithName:#"my-test-channe-for-push-notifications"]
withDevicePushToken:deviceToken];
}
// Observe for some PubNub delegate methods related to push notification observation (or use completion block enabled version of API):
- (void)pubnubClient:(PubNub *)client didEnablePushNotificationsOnChannels:(NSArray *)channels {
NSLog(#"PubNub client enabled push notifications on channels: %#", channels);
}
- (void)pubnubClient:(PubNub *)client pushNotificationEnableDidFailWithError:(PNError *)error {
NSLog(#"PubNub client failed push notification enable because of error: %#", error);
}
If you see that push notification enabling has been successful for you, then use http://pubnub.com/console with pub/sub/secret keys from your account at http://admin.pubnub.com to send message into the channel (in our case "aps" payload should be sent to the channel with "my-test-channe-for-push-notifications" name).

How can I implement Apple Push Notification Service on iOS Application?

Is there any sample project showing how to integrate APNS on IPhone, and how to get deviceToken?
there are a few simple steps you need to follow:
in your app delegate's didFinishLaunchingWithOptions you should register for remote notifications. notice that apple's documentations suggests to register each time the app runs since the token may change from time to time. you do this by calling:
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];
after registering for remote notifications a method in your app delegate will be called which had been passed the token, you need to implement this method in your app delegate and send the token to your server (that will send you notifications). the method will look like this:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
NSLog(#"device token is: %#",deviceToken);
[server sendToken:deviceToken];
}
you should also implement this as well:
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{}
you need to handle notifications once you get them. there are few different scenarios in which you handle received notifications (the app is in the background or foreground etc.), the method that handles a notification if the app is in the foreground when you receive it should be implemented in the app delegate. this is it:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
NSLog(#"received notification");
//handle the notification here
}
to learn more about the userInfo structure and cover all the different scenarios read carefully http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ApplePushService/ApplePushService.html. this was just the gist of things :)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Register for Push Notitications, if running on iOS 8
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0){
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}else{
[application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
}
return YES;
}
#pragma mark
#pragma mark -- Push Notification Delegate Methods
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings: (UIUserNotificationSettings *)notificationSettings{
//register to receive notifications
[application registerForRemoteNotifications];
}
-(void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken{
// Prepare the Device Token for Registration (remove spaces and < >)
NSString* devToken = [[[[deviceToken description]
stringByReplacingOccurrencesOfString:#"<"withString:#""]
stringByReplacingOccurrencesOfString:#">" withString:#""]
stringByReplacingOccurrencesOfString: #" " withString: #""];
NSLog(#"My token is: %#", devToken);
}
-(void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error{
// NSLog(#"Failed to get token, error: %#", error);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
NSLog(#"%s..userInfo=%#",__FUNCTION__,userInfo);
/**
* Dump your code here according to your requirement after receiving push
*/
}
Here is brief document about - How to enable and send push notification in iOS.
Enabling Push Notifications
The first step in setting up push notifications is enabling the feature within Xcode 8 for your app. Simply go to the project editor for your target and then click on the Capabilities tab. Look for Push Notifications and toggle its value to ON:
Toggle Capability
Xcode should display two checkmarks indicating that the capability was successfully enabled. Behind the scenes, Xcode creates an App ID in the Developer Center and enables the Push Notifications service for your app.
Registering Devices
Devices need to be uniquely identified to receive push notifications.
Every device that installs your app is assigned a unique device token by APNs that you can use to push it at any given time. Once the device has been assigned a unique token, it should be persisted in your backend database.
A sample device token looks like this:
5810F4C8C2AF5F7 F7 D6AF71A 22745D0FB50DED 665E0E882 BC5370D9CF0A F19E16
To request a device token for the current device, open AppDelegate.swift and add the following to the didFinishLaunchingWithOptions callback function, before the return statement:
// iOS 10 support
if #available(iOS 10, *) {
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in }
application.registerForRemoteNotifications()
}
// iOS 9 support
else if #available(iOS 9, *) {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
}
// iOS 8 support
else if #available(iOS 8, *) {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
}
// iOS 7 support
else {
application.registerForRemoteNotifications(matching: [.badge, .sound, .alert])
}
In iOS 10, a new framework called UserNotifications was introduced and must be imported in order to access the UNUserNotificationCenter class.
Add the following import statement to the top of AppDelegate.swift:
import UserNotifications
Next, go to the project editor for your target, and in the General tab, look for the Linked Frameworks and Libraries section.
Click + and select UserNotifications.framework:
Next, add the following callbacks in AppDelegate.swift which will be invoked when APNs has either successfully registered or failed registering the device to receive notifications:
// Called when APNs has assigned the device a unique token
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// Convert token to string
let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
// Print it to console
print("APNs device token: \(deviceTokenString)")
// Persist it in your backend in case it's new
}
// Called when APNs failed to register the device for push notifications
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
// Print the error to console (you should alert the user that registration failed)
print("APNs registration failed: \(error)")
}
It's up to you to implement logic that will persist the token in your application backend. Later in this guide, your backend server will connect to APNs and send push notifications by providing this very same device token to indicate which device(s) should receive the notification.
Note that the device token may change in the future due to various reasons, so use NSUserDefaults, a local key-value store, to persist the token locally and only update your backend when the token has changed, to avoid unnecessary requests.
Run your app on a physical iOS device (the iOS simulator cannot receive notifications) after making the necessary modifications to AppDelegate.swift. Look for the following dialog, and press OK to permit your app to receive push notifications:
Alert Dialog
Within a second or two, the Xcode console should display your device's unique token. Copy it and save it for later.
Prepare to Receive Notifications
Add the following callback in AppDelegate.swift which will be invoked when your app receives a push notification sent by your backend server:
// Push notification received
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
// Print notification payload data
print("Push notification received: \(data)")
}
Note that this callback will only be invoked whenever the user has either clicked or swiped to interact with your push notification from the lock screen / Notification Center, or if your app was open when the push notification was received by the device.
It's up to you to develop the actual logic that gets executed when a notification is interacted with. For example, if you have a messenger app, a "new message" push notification should open the relevant chat page and cause the list of messages to be updated from the server. Make use of the data object which will contain any data that you send from your application backend, such as the chat ID, in the messenger app example.
It's important to note that in the event your app is open when a push notification is received, the user will not see the notification at all, and it is up to you to notify the user in some way. This StackOverflow question lists some possible workarounds, such as displaying an in-app banner similar to the stock iOS notification banner.
Generate an APNs Auth Key
Open the APNs Auth Key page in your Developer Center and click the + button to create a new APNs Auth Key.
In the next page, select Apple Push Notification Authentication Key (Sandbox & Production) and click Continue at the bottom of the page.
Apple will then generate a .p8 key file containing your APNs Auth Key.
Download the .p8 key file to your computer and save it for later. Also, be sure to write down the Key ID somewhere, as you'll need it later when connecting to APNs.
Send Push Notifications
Now, look at here to understand, APNS flow: How do iOS Push Notifications work?

send device token to server from apple push notification service

I am working on apple push notification service. Now I have implemented the delegates methods as suggested in apple APNS guide. But this also says that one has to send device token received from APNS to provider server.
I am really confused about this thing.
Because when I launched application it asked me if I want to register for remote notifications but then later it never showed anything like that. At that time I had no code to handle this device token. But now it does not show anything like that even if I have deleted and reinstalled the whole application.
Any help would be greatly appreciated.
My code is this
- (void)viewDidLoad {
[super viewDidLoad];
//registring for remote notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound)];
}
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(#"Device token is %#", deviceToken)
}
The message to register for notifications is displayed just one time, at the first installation. To change notifications settings, you can go in notifications settings.

Resources