2

Hi I'm implement FCM (Fire base cloud messaging). I have made the app to receive notification and data from FCM console. I have both my server notification and firebase notification. I want to handle 2 type of notification (from my server and from FCM) separately. I have gone through the docs and this can be achieve by swizzling the notification handler in AppDelegate

But the problem is I can only get FCM message data (IOS 10) in

-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {}

and

-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {}

The callback for FCM delegate

// The callback to handle data message received via FCM for devices running iOS 10 or above.
- (void)applicationReceivedRemoteMessage:(nonnull FIRMessagingRemoteMessage *)remoteMessage {

    // Print full message
    NSLog(@"Can get here firebase?%@", [remoteMessage appData]);
}

the above callback is never called

How can we use swizzling to sett up FCM handler message separately?

Here is my Appdelegate didfinishlaunchingwith option

    application.applicationIconBadgeNumber = 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
    }

    [[UIApplication sharedApplication] registerForRemoteNotifications];

    // [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];    

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];

    _rootViewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];


    [self.window setRootViewController:_rootViewController];
    [self.window makeKeyAndVisible];

    NSDictionary *remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    if (remoteNotification)
        [self handleRemoteNotification:remoteNotification shouldPrompt:NO];

    self.isFirstTime = true;
    self.isJustForRefresh = 0;

    return YES;

Anyone know how to make it work?

Edit: here is my observer observation function and didregisterRemoteNotification function

// [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 didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
    NSString *sanitizedDeviceToken = [[[[deviceToken description]
                                        stringByReplacingOccurrencesOfString:@"<" withString:@""]
                                       stringByReplacingOccurrencesOfString:@">" withString:@""]
                                      stringByReplacingOccurrencesOfString:@" " withString:@""];

    DLog(@"sanitized device token: %@", sanitizedDeviceToken);
    [PushNotificationManager API_registerAPNSToken:sanitizedDeviceToken
                                      onCompletion:^(BOOL success, NSError *error){}];

    [[FIRInstanceID instanceID]setAPNSToken:deviceToken type:FIRInstanceIDAPNSTokenTypeSandbox];

}

Updated: I have include this function but still not working

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
    if (userInfo[@"gcm.message_id"] != nil) {
        NSLog(@"Should get here FCM?");
        [[FIRMessaging messaging]appDidReceiveMessage:userInfo];
    }else {
        NSLog(@"test fetchCompletion handler: %@",userInfo.description);
    }

}
Lê Khánh Vinh
  • 2,591
  • 5
  • 31
  • 77

1 Answers1

0

You may take a look of this answer? Seems like you missed the line FIRMessaging.messaging().connect(){....

https://stackoverflow.com/a/40881754/1005570

and also the delegate function..

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
             fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
// 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.
print("Message ID: \(userInfo["gcm.message_id"]!)")

// Print full message.
print(userInfo)

FIRMessaging.messaging().appDidReceiveMessage(userInfo)

}

Community
  • 1
  • 1
Pang Ho Ming
  • 1,299
  • 10
  • 29
  • sorry, the code is in swift. but i think you can get it. – Pang Ho Ming Dec 01 '16 at 03:50
  • Hi update the code I already connect to FCM and can receive the notification but my question is using the method swizzling? handle FCM notification and my own server notification separately (now everything go to the willpresent and didrecieved) – Lê Khánh Vinh Dec 01 '16 at 04:33
  • And testing for IOS 10 – Lê Khánh Vinh Dec 01 '16 at 04:37
  • oh i get what you mean. So with the code you implemented above, can you receive any notification from your own server? So the problem you are encountering is 1. received notifications from two sources but cant separated them. or 2. only received notifications from FCM but not your own server. – Pang Ho Ming Dec 01 '16 at 06:00
  • Hi thanks my problem is first one. I can get the notification but cannot separate them and the FCM delegate func is never be called – Lê Khánh Vinh Dec 01 '16 at 10:44
  • right inside the didReceiveRemoteNotification:fetchCompletionHandler method.. check if userInfo["gcm.message_id"] exists, if it does, its from FCM, then call the 'FIRMessaging.messaging().appDidReceiveMessage(userInfo)'. If it doesnt, dont call the FIRMessage function, write your own one to handle the userInfo – Pang Ho Ming Dec 05 '16 at 02:06
  • Hi. I have include the function but still not working. only willpresent and didrecieve notification is called for IOS 10. never got the above function be called. Even I have enable background mode – Lê Khánh Vinh Dec 05 '16 at 05:32
  • thats kind of weird, take a look of this http://stackoverflow.com/a/40881754/1005570. I do not implement the willpresent and didrecieve notification delegate function. – Pang Ho Ming Dec 05 '16 at 06:24
  • Could u receive notification for ios10? Thought os 10 we need to implement that 2 delegate func? – Lê Khánh Vinh Dec 05 '16 at 06:41
  • Hmmm. I am running on iOS10 and can receive notifications. I implemented it last week, and its still working. Do we really need to implement it? Let me google it. – Pang Ho Ming Dec 05 '16 at 06:53
  • Basically, I just implement the functions that the official doc mentioned. https://firebase.google.com/docs/cloud-messaging/ios/receive By the way, I checked my commit history, I DID implement the 2 delegate function at first, but I removed them and then it works – Pang Ho Ming Dec 05 '16 at 06:59
  • Hmm think these 2 func needed in ios10 when we handle the userinfo from the notification – Lê Khánh Vinh Dec 05 '16 at 07:00