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)
Related
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.
I am trying to print a device token to the Debugger Window. When building and running the app on a test device, the app receives a Would Like to Send You Push Notifications alert, but the NSLog doesn't print the device token.
//REGISTER FOR THE NOTIFICATIONS TYPES
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
//-- Set Notification
if (#available(iOS 8, *)) {
// iOS 8 Notifications: Registering for notifications and types
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[application registerForRemoteNotifications];
} else {
// iOS < 8 Notifications
_storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
if (launchOptions != nil)
{
NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil)
{
NSLog(#"Launched from push notification: %#", dictionary);
/*[self addMessageFromRemoteNotification:dictionary updateUI:NO];*/
}
}
return YES;
}
- (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);
}
didFailToRegisterForRemoteNotificationsWithError isn't being called or printed either. How can this code be edited to print the device token in the NSLog?
I'm trying to be notified in background, I followed the documentation Firebase and Apple but I can´t solve my problem.
Problem: When I send a notification from the console Firebase I receive notification perfectly foreground, but sending the same notification from Firebase and my application is in background I do not receive any data, however if I open the application, the application shows me notification, but never in background. And the funny thing is that the next day I receive all notifications in the background with the closed application.
Device: iPhone 6 - v10.0.1
EDIT: My payload:
When I send a notification in Firebase, I receive this payload, I selected high priority in Firebase but I don´t receive any priority in the payload.
My code:
#define SYSTEM_VERSION_GRATERTHAN_OR_EQUALTO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self registerForRemoteNotifications];
[FIRApp configure];
[self connectToFcm];
return YES;
}
- (void)registerForRemoteNotifications {
if(SYSTEM_VERSION_GRATERTHAN_OR_EQUALTO(#"10.0")){
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error){
if(!error){
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
}];
NSLog(#"Version >= 10");
}
else {
NSLog(#"version < 10");
// Code for old versions
}
}
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSLog(#"MODO 1: User Info: %#",notification.request.content.userInfo);
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}
//Called to let your app know which action was selected by the user for a given notification.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
NSLog(#"MODO 2: User Info: %#",response.notification.request.content.userInfo);
completionHandler();
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
}
- (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);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
for (NSString *key in userInfo) {
NSLog(#"key value: %#", key);
if ([key isEqualToString:#"notification"]) {
NSString *body = [[userInfo valueForKeyPath:key] objectForKey:#"body"];
NSLog(#"message content: %#", body);
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:5];
notification.repeatInterval = NSDayCalendarUnit;
notification.alertBody = body;
notification.timeZone = [NSTimeZone defaultTimeZone];
notification.soundName = UILocalNotificationDefaultSoundName;
notification.applicationIconBadgeNumber = 0;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
}
NSLog(#"Message ID: %#", userInfo[#"gcm.message_id"]);
if( [UIApplication sharedApplication].applicationState == UIApplicationStateInactive )
{
NSLog( #"INACTIVE" );
completionHandler( UIBackgroundFetchResultNewData );
}
else if( [UIApplication sharedApplication].applicationState == UIApplicationStateBackground )
{
NSLog( #"BACKGROUND" );
completionHandler( UIBackgroundFetchResultNewData );
}
else
{
NSLog( #"FOREGROUND" );
completionHandler( UIBackgroundFetchResultNewData );
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(#"enter in background");
}
- (void)connectToFcm {
[[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Unable to connect to FCM. %#", error);
} else {
NSLog(#"Connected to FCM.");
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"registeredToFCM"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}];
}
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:
after deploying FCM cloud messaging which is the upgrading version of GCM cloud messaging as mentioned https://developers.google.com/cloud-messaging/ios/client so we moved to integrate FCM in our app using pod as mentioned https://firebase.google.com/docs/cloud-messaging/notifications i follow up every step in the tutorial here is what happening the remote notification had been received well in both state Background State and active state but the main problem that i faced is the notification does appear in the notification bar here is my code that i am using
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
float ver = [[[UIDevice currentDevice] systemVersion] floatValue];
if(ver >= 8 && ver<9)
{
if ([[UIApplication sharedApplication] respondsToSelector:#selector(registerUserNotificationSettings:)])
{
[[UIApplication sharedApplication] registerForRemoteNotifications];
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
}else if (ver >=9){
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
else{
//iOS6 and iOS7 specific code
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeAlert];
}
// ma tensa google maps
[FIRApp configure];
[self connectToFcm];
}
- (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);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.userInfo = userInfo;
localNotification.applicationIconBadgeNumber = 0;
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.fireDate = [NSDate date];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
NSLog(#"Message ID: %#", userInfo[#"gcm.message_id"]);
//
// if (application.applicationState == active) {
// <#statements#>
// }
// Pring full message.
NSLog(#"%#", userInfo);
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// [[FIRMessaging messaging] disconnect];
}
- (void)connectToFcm {
[[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Unable to connect to FCM. %#", error);
} else {
NSLog(#"Connected to FCM.");
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"registeredToFCM"];
[[NSUserDefaults standardUserDefaults] synchronize];
// i used the method since not all the time app register for fcm so when
//the complete launching and did not register //
//for fcm the app request to register fro fcm again//
}
}];
}
here some link that i searched for to solve my problem before moving here Notifications are not getting in iOS 9.2 , FCM background notifications not working in iOS, and Push notifications are not working in iOS 9 but i could not solve my issue
Forgot to tell you that the phone is ringing and vibrating when the notification had been received.
hope any one help Happy Coding !!
If you want the notification to show up you have to set "priority":"high". Like so:
"to":"TOKEN ID",
"notification" : {
"body" : "test"
},
"priority": "high"
}