I'm developing app with iOS 10.
push notification works fine with foreground mode, but not working when it turned to background mode.
here is my appDelegate.m
#import "AppDelegate.h"
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
@import UserNotifications;
#endif
@import FirebaseInstanceID;
@import FirebaseMessaging;
// Implement UNUserNotificationCenterDelegate to receive display notification via APNS for devices
// running iOS 10 and above. Implement FIRMessagingDelegate to receive data message via FCM for
// devices running iOS 10 and above.
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
@interface AppDelegate () <UNUserNotificationCenterDelegate, FIRMessagingDelegate>
@end
#endif
// Copied from Apple's header in case it is missing in some cases (e.g. pre-Xcode 8 builds).
#ifndef NSFoundationVersionNumber_iOS_9_x_Max
#define NSFoundationVersionNumber_iOS_9_x_Max 1299
#endif
@interface AppDelegate ()
@end
@implementation AppDelegate
NSString *const kGCMMessageIDKey = @"gcm.message_id";
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Register for remote notifications. This shows a permission dialog on first run, to
// show the dialog at a more appropriate time move this registration accordingly.
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
// iOS 7.1 or earlier. Disable the deprecation warnings.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
UIRemoteNotificationType allNotificationTypes =
(UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeBadge);
[application registerForRemoteNotificationTypes:allNotificationTypes];
#pragma clang diagnostic pop
} else {
// iOS 8 or later
// [START register_for_notifications]
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].delegate = self;
// For iOS 10 data message (sent via FCM)
[FIRMessaging messaging].remoteMessageDelegate = self;
#endif
}
[[UIApplication sharedApplication] registerForRemoteNotifications];
// [END register_for_notifications]
}
// [START configure_firebase]
[FIRApp configure];
// [END configure_firebase]
// Add observer for InstanceID token refresh callback.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tokenRefreshNotification:)
name:kFIRInstanceIDTokenRefreshNotification object:nil];
// NSString *refreshedToken = [[FIRInstanceID instanceID] token];
// NSLog(@"Current Token : %@", refreshedToken);
return YES;
}
// [START receive_message]
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
// 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.
if (userInfo[kGCMMessageIDKey]) {
NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
}
// Print full message.
NSLog(@"%@", userInfo);
}
- (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.
if (userInfo[kGCMMessageIDKey]) {
NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
}
// Print full message.
NSLog(@"%@", userInfo);
completionHandler(UIBackgroundFetchResultNewData);
}
// [END receive_message]
// [START ios_10_message_handling]
// Receive displayed notifications for iOS 10 devices.
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// Handle incoming notification messages while app is in the foreground.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
// Print message ID.
NSDictionary *userInfo = notification.request.content.userInfo;
if (userInfo[kGCMMessageIDKey]) {
NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
}
// Print full message.
NSLog(@"%@", userInfo);
}
// Handle notification messages after display notification is tapped by the user.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler {
NSDictionary *userInfo = response.notification.request.content.userInfo;
if (userInfo[kGCMMessageIDKey]) {
NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
}
// Print full message.
NSLog(@"%@", userInfo);
}
#endif
// [END ios_10_message_handling]
// [START ios_10_data_message_handling]
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// Receive data message on iOS 10 devices while app is in the foreground.
- (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage {
// Print full message
NSLog(@"%@", [remoteMessage appData]);
}
#endif
// [END ios_10_data_message_handling]
// [START refresh_token]
- (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.
}
// [END refresh_token]
// [START connect_to_fcm]
- (void)connectToFcm {
[[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Unable to connect to FCM. %@", error);
} else {
NSLog(@"Connected to FCM.");
}
}];
}
// [END connect_to_fcm]
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"Unable to register for remote notifications: %@", error);
}
// This function is added here only for debugging purposes, and can be removed if swizzling is enabled.
// If swizzling is disabled then this function must be implemented so that the APNs token can be paired to
// the InstanceID token.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(@"APNs token retrieved: %@", deviceToken);
// With swizzling disabled you must set the APNs token here.
// [[FIRInstanceID instanceID] setAPNSToken:deviceToken type:FIRInstanceIDAPNSTokenTypeSandbox];
}
// [START connect_on_active]
- (void)applicationDidBecomeActive:(UIApplication *)application {
[self connectToFcm];
}
// [END connect_on_active]
// [START disconnect_from_fcm]
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[FIRMessaging messaging] disconnect];
NSLog(@"Disconnected from FCM");
int countNoti = 0;
for(NSString *notiKey in unreadList) {
NotiClass *tmpNoti = [unreadList objectForKey:notiKey];
if([tmpNoti.notiType isEqualToString:@"FUTURE"]) {
} else {
countNoti++;
}
}
[UIApplication sharedApplication].applicationIconBadgeNumber = countNoti;
}
// [END disconnect_from_fcm]
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
// Saves changes in the application's managed object context before the application terminates.
[self saveContext];
}
Hi @choitaehun could you describe how you are sending the notification? Are you using the console or the REST API?
Hello, I have exactely the same problem, using firebase console.
Any insight ?
Hi @eussam, messages sent from the console use APNs for delivery so could you confirm that you are getting the didRegisterForRemoteNotificationsWithDeviceToken callback? Also if you disabled swizzling then you need to call setApnsToken
Hi @kroikie , I am not receiving the instance id and therefore not receiving the FCM notification, Everything was working in iOS 9.3 , but on iOS 10, it is not working. I am receiving the device token as well, but instance id is not receiving.
Please see my logs:
2017-03-08 18:06:56.422:
2017-03-08 18:07:23.852:
2017-03-08 18:08:06.874:
2017-03-08 18:09:09.481:
2017-03-08 18:09:09.482:
Please guide me, if I am missing something,
I saw on the Firebase site that for iOS 10.0, use UNUserNotificationCenter instead. I have written this in my didFinishLaunchWithOptions, I have also implemented its delegate method. but still not getting the instance id.
This is my AppDelegate code...
@import UIKit;
@import Firebase;
@import FirebaseMessaging;
@import FirebaseInstanceID;
@implementation AppDelegate
@synthesize vcProvider;
//constant define...
//end...
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if([[[UIDevice currentDevice] systemVersion] floatValue]>=8.0)
{
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];
}
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
*/
//Right, that is the point
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
//register to receive notifications
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
//code for firebase...!
//For firebase....
//end code for firebase...!
//Working code for Firebase from Firebase testing app.
//[FIRApp configure];
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
UIUserNotificationType allNotificationTypes =
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
UIUserNotificationSettings *setting =
[UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:setting];
} else {
// iOS 10 or later
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
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].delegate = self;
// For iOS 10 data message (sent via FCM)
[FIRMessaging messaging].remoteMessageDelegate = self;
}
[[UIApplication sharedApplication] registerForRemoteNotifications];
[FIRApp configure];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tokenRefreshNotification:)
name:kFIRInstanceIDTokenRefreshNotification object:nil];
}
// end of my code...
return YES;
}
(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSLog(@"User Info = %@",notification.request.content.userInfo);
completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound);
}
(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
NSLog(@"User Info = %@",response.notification.request.content.userInfo);
completionHandler();
}
(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.
//saving the refreshed token to userdefaults...
if(refreshedToken){
//any code...
}
}
(void)connectToFcm {
// Won't connect since there is no token
if (![[FIRInstanceID instanceID] token]) {
return;
}
// Disconnect previous FCM connection if it exists.
[[FIRMessaging messaging] disconnect];
[[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Unable to connect to FCM. %@", error);
} else {
NSLog(@"Connected to FCM.");
}
}];
}
// With "FirebaseAppDelegateProxyEnabled": NO
(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.
if (userInfo[@"gcm.message_id"]) {
NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]);
}
// Print full message.
NSLog(@"My full data%@", userInfo);
NSString* bodyText = [userInfo valueForKey:@"alert"];
NSMutableDictionary* aps = [userInfo valueForKey:@"aps"];
NSString* bText = [aps valueForKey:@"alert"];
NSLog(@"Body Text is = ", bodyText);
[self generateLocalNotification:bText];
completionHandler(UIBackgroundFetchResultNewData);
}
//AppDelegate.m
// Receive data message on iOS 10 devices while app is in the foreground.
(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
//register to receive notifications
[[UIApplication sharedApplication] 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"]){
}
}
/*
//For interactive notification only
(void)application:(UIApplication)application didFailToRegisterForRemoteNotificationsWithError:(NSError)error
{
NSLog(@"Failed to get token, error: %@", error);
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:@"121212121212121212" forKey:PREF_DEVICE_TOKEN];
[prefs synchronize];
}
(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if (userInfo[@"gcm.message_id"]) {
NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]);
}
// Print full message.
NSLog(@"simple didReceiveRemoteNotification%@", userInfo);
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 0];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
[AGPushNoteView close];
}
}
(NSString)stringWithDeviceToken:(NSData)deviceToken
{
const char* data = [deviceToken bytes];
NSMutableString* token = [NSMutableString string];
for (int i = 0; i < [deviceToken length]; i++)
{
[token appendFormat:@"%02.2hhX", data[i]];
}
return [token copy] ;
}
(void)applicationDidEnterBackground:(UIApplication )application
{/
NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
NSDictionary * dict = [defs dictionaryRepresentation];
for (id key in dict) {
[defs removeObjectForKey:key];
}
[defs synchronize];*/
// 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.
[FBSDKAppEvents activateApp];
[self connectToFcm];
}
(void)didReceiveDeepLink:(GPPDeepLink *)deepLink
{
// An example to handle the deep link data.
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Deep-link Data"
message:[deepLink deepLinkID]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
(BOOL)application: (UIApplication *)application openURL: (NSURL *)url sourceApplication: (NSString *)sourceApplication annotation: (id)annotation
{
BOOL handled = [[FBSDKApplicationDelegate sharedInstance] application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation
];
// Add any custom logic here.
return handled;
// return [GPPURLHandler handleURL:url sourceApplication:sourceApplication annotation:annotation];
}
@end
Hi @kroikie, I have downloaded your github code and run on an the real devices, The code runs fine on iOS version 9.3 and I received the instance Id and also the FCM notification sent from its console.
Please see this : https://cloudup.com/cWsxfUR-BUO
But when I run your code on iOS version 10.0, it creates the same issue, i.e. no instance id is received, and also no notification is received.
Please see this : https://cloudup.com/ch1Js7yPNBm
kindly help me to resolve this issue, Any help will be greatly appreciated...!
Thanks in advance...!!
Hi @ahmadtbox sorry for the delay.
It seems like the iOS 10 device could be having network issues. That would be a likely reason that the default token cannot be generated. Could you confirm that the iOS 10 device has good network connectivity?
Hi @kroikie , Thanks for the response,
it may be the issue, I will confirm it.
Can you please tell me that which FCM delegate function is called when app is in background state and a remote push notification is received, I am receiving the FCM push notification when the app is in foreground and also in background.
When the app is in the foreground state, following delegate function is called,
But when the app is running in the background, This method is not get called and no other delegate method is called.
Actually, I want to show my custom notification message when a FCM push notification is received but I have not access of any delegate method when a notification is received.
Please help me to resolve this issue, I am really thankful to you for your response.
Thanks in advance...!
@ahmadtbox as per the documentation application(_:didReceiveRemoteNotification:fetchCompletionHandler:) should get called for both background & foreground remote notifications
https://developer.apple.com/reference/uikit/uiapplicationdelegate/1623013-application
Kindly check your payload structure , whether you have set the
content-available = true
priority = high
if its only Data Payload as per the FCM documentation
https://firebase.google.com/docs/cloud-messaging/concept-options
Thanks, @Sundarrajan S, I am very thankful to you...! I forgot to mention
you about it...!
Yes This was the issue, and I resolved it with your help.
Once again, Thanks...!
On Fri, Feb 3, 2017 at 1:38 PM, Sundarrajan S notifications@github.com
wrote:
@ahmadtbox https://github.com/ahmadtbox as per the documentation
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
should get called for both background & foreground remote notifications
https://developer.apple.com/reference/uikit/uiapplicationdelegate/1623013-
applicationKindly check your payload structure , whether you have set the
content-available = true
priority = highif its only Data Payload as per the FCM documentation
https://firebase.google.com/docs/cloud-messaging/concept-options—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/firebase/quickstart-ios/issues/194#issuecomment-277193130,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AVQbxOiGYvlDKMoUaP5tNZuZINFFr8J9ks5rYueHgaJpZM4LNx7G
.