Device token for push notifications not generated - ios

Since a few days, I am unable to receive push notifications for one of my apps. I had a closer look and it seems it doesn't manage to generate a device token. I was able to reproduce it with a blank application and the following code (or the Swift equivalent):
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
NSLog(#"Granted.");
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
} else {
NSLog(#"Not granted.");
}
}];
return YES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(#"Token: %#", deviceToken);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(#"Error: %#", error);
}
Push notifications were added to the app's capabilities (I've blanked out the team name and part of the certificate description):
and this generated the following entitlements file:
When the app launches, I get the usual popup:
and the app reaches the 'Granted' block:
2022-06-12 19:55:28.665018+0200 Sandbox[1704:108535] Granted.
but I see neither a device token nor an error in the log.

Related

Registering for remote notifications does nothing

I have a button in my app that triggers registering for notifications. Say this is a UIBarButton.
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithTitle:#"Grant" style:UIBarButtonItemStyleDone target:self action:#selector(grantPermission:)];
self.navigationItem.rightBarButtonItem = rightButton;
This is the function the button triggers:
- (void)grantPermission:(id)sender {
if (SYSTEM_VERSION_LESS_THAN( #"10.0" )) {
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
} else {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
NSLog(#"Completion handler called");
if (!error) {
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
} else {
NSLog( #"Push registration FAILED" );
NSLog( #"ERROR: %# - %#", error.localizedFailureReason, error.localizedDescription );
NSLog( #"SUGGESTIONS: %# - %#", error.localizedRecoveryOptions, error.localizedRecoverySuggestion );
}
}];
}
}
I also added the following delegate methods:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(#"Did Register for Remote Notifications with Device Token (%#)", deviceToken);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(#"Did Fail to Register for Remote Notifications");
NSLog(#"%#, %#", error, error.localizedDescription);
}
When I run this code, I get the modal asking for permission. When I press 'accept' I see the Completion handler called log, but nothing after that. Nothing happens, no logs are shown. Nothing. Any ideas as to what I'm doing wrong?
You must test that code on a physical device. Simulators don't get notifications token. You will get an error callback.
Also check which version of iOS you are targeting because the callbacks in the app delegate which changed between ios9-10 (possibly 11) so you will have a deprecated method which won't get called (or visa versa depending on which version of iOS you are testing against)

Firebase messaging works only in foreground

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
UNAuthorizationOptions authOptions =
UNAuthorizationOptionAlert
| UNAuthorizationOptionSound
| UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
}];
[FIRMessaging messaging].remoteMessageDelegate = self;
[[UIApplication sharedApplication] registerForRemoteNotifications];
[FIRApp configure];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(tokenRefreshNotification:)
name:kFIRInstanceIDTokenRefreshNotification object:nil];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[FIRMessaging messaging] disconnect];
NSLog(#"Disconnected from FCM");
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[self connectToFcm];
}
- (void)applicationWillTerminate:(UIApplication *)application {
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
// Print message ID.
NSLog(#"message 1");
if (userInfo[kGCMMessageIDKey]) {
NSLog(#"Message ID: %#", userInfo[kGCMMessageIDKey]);
}
// Print full message.
NSLog(#"%#", userInfo);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// Print message ID.
NSLog(#"message 2");
if (userInfo[kGCMMessageIDKey]) {
NSLog(#"Message ID: %#", userInfo[kGCMMessageIDKey]);
}
NSLog(#"%#", userInfo);
completionHandler(UIBackgroundFetchResultNewData);
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
NSLog(#"message 3");
NSDictionary *userInfo = notification.request.content.userInfo;
if (userInfo[kGCMMessageIDKey]) {
NSLog(#"Message ID: %#", userInfo[kGCMMessageIDKey]);
}
NSLog(#"full data : %#", userInfo);
completionHandler(UNNotificationPresentationOptionAlert);
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler {
NSDictionary *userInfo = response.notification.request.content.userInfo;
NSLog(#"message 1");
if (userInfo[kGCMMessageIDKey]) {
NSLog(#"Message ID: %#", userInfo[kGCMMessageIDKey]);
}
// Print full message.
NSLog(#"%#", userInfo);
completionHandler();
}
- (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage {
// Print full message
NSLog(#"applicationReceivedRemoteMessage : %#", remoteMessage.appData);
}
- (void)tokenRefreshNotification:(NSNotification *)notification {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *refreshedToken = [[FIRInstanceID instanceID] token];
NSLog(#"InstanceID token: %#", refreshedToken);
if(!(refreshedToken== nil)){
[defaults setValue:refreshedToken forKey:#"FcmToken"];
}
[self connectToFcm];
}
- (void)connectToFcm {
if (![[FIRInstanceID instanceID] token]) {
return;
}
[[FIRMessaging messaging] disconnect];
[[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Unable to connect to FCM. %#", error);
} else {
NSLog(#"Connected to FCM.");
}
}];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(#"Unable to register for remote notifications: %#", error);
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(#"APNs token retrieved: %#", deviceToken);
}
enter code here
When app is in the background mode, message not coming. When app is running foreground mode message shows in applicationReceivedRemoteMessage function. I need to run some code when message comes when background mode. Can anyone give me the solution for get the notifications works in background mode.
FIRMessaging connection won’t be allowed to live when in background it
is prudent to close the connection.
Please find here reference for the same: disconnect()
FirebaseMessaging Framework Reference
Simple Logic About Chat Applications: Socket Connection
Generally, Chat applications connects with other nodes (devices) using socket connection to transmit real-time information between nodes. Socket connections are disconnected, when apps goes into background.
FirebaseMessaging works on same logic and hence is won't work in background.
To handle message transmission in background mode, use power of PushNotification.
Also mark your code: You are disconnecting FIRMessaging when application goes into background. And you've done this, because the same is instructed in FIRMessaging guidelines.
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[FIRMessaging messaging] disconnect];
NSLog(#"Disconnected from FCM");
}
As an alternate solution of your problem: You may have analyzed Whatapp or Facebook Messagner app. They use push notification to alert user for messages, when app goes into background. You should do the same.

Firebase ios notification token not generated in objective c

I completed all the steps followed by firebase notification document, finally when I run the app.showing the following error, how to generate device token? please refer screenshot below
Error:
Failed to fetch APNS token Error Domain=com.firebase.iid Code=1001 "(null)"
I tried this code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[[UINavigationBar appearance] setBarTintColor:[UIColor colorWithRed:156.0/255.0 green:39.0/255.0 blue:176.0/255.0 alpha:1.0]];
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
UIUserNotificationType allNotificationTypes =
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings =
[UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
// iOS 10 or later
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
UNAuthorizationOptions authOptions =
UNAuthorizationOptionAlert
| UNAuthorizationOptionSound
| UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter]
requestAuthorizationWithOptions:authOptions
completionHandler:^(BOOL granted, NSError * _Nullable error) {
}
];
// For iOS 10 display notification (sent via APNS)
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
// For iOS 10 data message (sent via FCM)
[[FIRMessaging messaging] setRemoteMessageDelegate:self];
#endif
}
[FIRApp configure];
// Add observer for InstanceID token refresh callback.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(tokenRefreshNotification:)
name:kFIRInstanceIDTokenRefreshNotification object:nil];
// [[UIApplication sharedApplication] registerForRemoteNotifications];
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
return YES;
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
[[FIRMessaging messaging] disconnect];
NSLog(#"Disconnected from FCM");
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
[self connectToFcm];
}
- (void)tokenRefreshNotification:(NSNotification *)notification {
// Note that this callback will be fired everytime a new token is generated, including the first
// time. So if you need to retrieve the token as soon as it is available this is where that
// should be done.
NSString *refreshedToken = [[FIRInstanceID instanceID] token];
NSLog(#"InstanceID token: %#", refreshedToken);
// Connect to FCM since connection may have failed when attempted before having a token.
[self connectToFcm];
// TODO: If necessary send token to application server.
}
// With "FirebaseAppDelegateProxyEnabled": NO
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[[FIRInstanceID instanceID] setAPNSToken:deviceToken
type:FIRInstanceIDAPNSTokenTypeSandbox];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// Print message ID.
NSLog(#"Message ID: %#", userInfo[#"gcm.message_id"]);
// Pring full message.
NSLog(#"%#", userInfo);
}
- (void)connectToFcm {
[[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Unable to connect to FCM. %#", error);
} else {
NSLog(#"Connected to FCM.");
}
}];
}
console screenshot:

GCM Registration token in iOS

I am completely new to GCM integration with iOS i have an GCMSENDERID all i want to get registration token with this sender id.The function is also not getting called.let me know what mistake i have done or please give me some examples to sort it out.
#import "AppDelegate.h"
static NSString *const INSTANCE_ID_REGISTRATION_NOTIF_KEY = #"instance-id-token";
static NSString *const GCM_SENDER_ID = #"19398749911";
#interface AppDelegate ()
{
}
#property (nonatomic, strong) NSDictionary *registrationOptions;
#property (nonatomic, strong) GGLInstanceIDTokenHandler registrationHandler;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UIUserNotificationType allNotificationTypes=(UIUserNotificationTypeSound|UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings=[UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
[[UIApplication sharedApplication]registerUserNotificationSettings:settings];
[[UIApplication sharedApplication]registerForRemoteNotifications];
self.registrationHandler = ^(NSString *registrationToken, NSError *error){
if (registrationToken != nil) {
//I do get the token, and I can store it
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:registrationToken forKey:INSTANCE_ID_REGISTRATION_NOTIF_KEY];
NSLog(#"Registration Token: %#", registrationToken);
} else {
NSLog(#"Registration to GCM failed with error: %#", error.localizedDescription);
}
};
return YES;
}
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// Start the GGLInstanceID shared instance with the default config and request a registration
// token to enable reception of notifications
NSLog(#"didRegisterForRemoteNotificationsWithDeviceToken");
[[GGLInstanceID sharedInstance] startWithConfig:[GGLInstanceIDConfig defaultConfig]];
self.registrationOptions = #{kGGLInstanceIDRegisterAPNSOption:deviceToken,
kGGLInstanceIDAPNSServerTypeSandboxOption:#NO};//I tried both YES and NO value
[[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:GCM_SENDER_ID
scope:kGGLInstanceIDScopeGCM
options:self.registrationOptions
handler:self.registrationHandler];
}
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSLog(#"Error in registration. Error: %#", err);
}
- (void)onTokenRefresh {
// A rotation of the registration tokens is happening, so the app needs to request a new token.
NSLog(#"The GCM registration token needs to be changed.");
[[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:GCM_SENDER_ID
scope:kGGLInstanceIDScopeGCM
options:self.registrationOptions
handler:self.registrationHandler];
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
NSLog(#"Notification received: %#", userInfo);//This log never prints so the method is never called
// This works only if the app started the GCM service
[[GCMService sharedInstance] appDidReceiveMessage:userInfo];
// Handle the received message
// Invoke the completion handler passing the appropriate UIBackgroundFetchResult value
// ...
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(#"Notification received: %#", userInfo);//This log never prints so the method is never called
// This works only if the app started the GCM service
[[GCMService sharedInstance] appDidReceiveMessage:userInfo];
// Handle the received message
// Invoke the completion handler passing the appropriate UIBackgroundFetchResult value
// ...
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Connect to the GCM server to receive non-APNS notifications
[[GCMService sharedInstance] connectWithHandler:^(NSError *error) {
if (error) {
NSLog(#"Could not connect to GCM: %#", error.localizedDescription);
} else {
NSLog(#"Connected to GCM");
// ...
}
}];
}

Don't receive push notifications with GCM on iOS

I followed this tutorial https://developers.google.com/cloud-messaging/ios/client to implement Google Cloud Messaging on my iOS application. I use google app engine as server side and the java library for GCM to send messages and it works perfectly for my Android application. However my iOS application does not receive messages from it.
I don't understand why because I do get the registration token and send it to my server side. I don't get any error log. Here is my AppDelegate.m code:
#import "AppDelegate.h"
#interface AppDelegate ()
#property (nonatomic, strong) NSDictionary *registrationOptions;
#property (nonatomic, strong) GGLInstanceIDTokenHandler registrationHandler;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//-- Start the GCMService
[[GCMService sharedInstance] startWithConfig:[GCMConfig defaultConfig]];
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)];
}
self.registrationHandler = ^(NSString *registrationToken, NSError *error){
if (registrationToken != nil) {
//I do get the token, and I can store it
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:registrationToken forKey:CLE_TOKENGCM];
NSLog(#"Registration Token: %#", registrationToken);
} else {
NSLog(#"Registration to GCM failed with error: %#", error.localizedDescription);
}
};
return YES;
}
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// Start the GGLInstanceID shared instance with the default config and request a registration
// token to enable reception of notifications
NSLog(#"didRegisterForRemoteNotificationsWithDeviceToken");
[[GGLInstanceID sharedInstance] startWithConfig:[GGLInstanceIDConfig defaultConfig]];
self.registrationOptions = #{kGGLInstanceIDRegisterAPNSOption:deviceToken,
kGGLInstanceIDAPNSServerTypeSandboxOption:#NO};//I tried both YES and NO value
[[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:SENDER_ID
scope:kGGLInstanceIDScopeGCM
options:self.registrationOptions
handler:self.registrationHandler];
}
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSLog(#"Error in registration. Error: %#", err);
}
- (void)onTokenRefresh {
// A rotation of the registration tokens is happening, so the app needs to request a new token.
NSLog(#"The GCM registration token needs to be changed.");
[[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:SENDER_ID
scope:kGGLInstanceIDScopeGCM
options:self.registrationOptions
handler:self.registrationHandler];
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
NSLog(#"Notification received: %#", userInfo);//This log never prints so the method is never called
// This works only if the app started the GCM service
[[GCMService sharedInstance] appDidReceiveMessage:userInfo];
// Handle the received message
// Invoke the completion handler passing the appropriate UIBackgroundFetchResult value
// ...
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(#"Notification received: %#", userInfo);//This log never prints so the method is never called
// This works only if the app started the GCM service
[[GCMService sharedInstance] appDidReceiveMessage:userInfo];
// Handle the received message
// Invoke the completion handler passing the appropriate UIBackgroundFetchResult value
// ...
}
#end
Thanks to ztan comment and to the Google GCM sample, I found out what was wrong: I had to implement applicationDidBecomeActive: like this:
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Connect to the GCM server to receive non-APNS notifications
[[GCMService sharedInstance] connectWithHandler:^(NSError *error) {
if (error) {
NSLog(#"Could not connect to GCM: %#", error.localizedDescription);
} else {
NSLog(#"Connected to GCM");
// ...
}
}];
}

Resources