1
votes

I'm trying to add Firebase SDK to my app. On Android side it's all good and works as expected. On iOS side it works that way I can make it receive messages via FCM, but cannot get APNs token at all. Sounds like easy problem/mistake?

Firebase iOS SDK 5.17 and Firebase C++ SDK 5.5.0 are added and compiled in. I included following frameworks:

firebase.framework
firebase_instance_id.framework
firebase_messaging.framework
FirebaseCore.framework
FirebaseInstanceID.framework
FirebaseMessaging.framework
GoogleUtilities.framework
Protobuf.framework

info.plist contains:

<key>FirebaseAppDelegateProxyEnabled</key>
<false/>

Yes, I need to disable method swizzling coz I need APNs token.

Now in didRegisterForRemoteNotificationsWithDeviceToken:

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
[FIRMessaging messaging].APNSToken = deviceToken;

Of course Xcode project is all fine: provision profile is active, Target -> Background Modes -> Remote notifications -> Enabled, Target -> Push notifications -> ON. GoogleService-Info.plist is added to project.

What's wrong? When Firebase SDK added and method swizzling disabled, didRegisterForRemoteNotificationsWithDeviceToken and didFailToRegisterForRemoteNotificationsWithError are never ever called. I tried to call:

[[UIApplication sharedApplication] registerForRemoteNotifications]

but no luck. Tried

requestAuthorizationWithOptions

and

if(granted) {
    [[UIApplication sharedApplication] registerForRemoteNotifications]

still nothing.

I missed something but I think it's either too simple or too difficult to find for me. Wasted two days to find but still no idea.

UPDATE: I reproduced a problem in empty Objective-C project. It occurs when both Firebase iOS SDK and Firebase C++ SDK are implemented. If I remove Firebase C++ SDK frameworks, I can get my token again. Now when I can't get token I get "ERROR: Attempting to complete future before FCM initialized." in log.

Reproduce steps:

  1. Create Xcode project as usual. In my case it's a Game. Using Objective-C, Metal.
  2. On Capabilities->Background Modes->ON and Background Modes->Remote Notifications->Checked.
  3. Capabilities->Push Notifications->ON. Xcode shows enabled and no problems.
  4. On Firebase Console, created new app; added iOS app, bundle ID->download GoogleService-Info.plist and added to app.
  5. I don't use Cocoa Pods, so add following SDKs to iOS project: firebase.framework, firebase_instance_id.framework, firebase_messaging.framework, FirebaseCore.framework, FirebaseInstanceID.framework, FirebaseMessaging.framework, GoogleUtilities.framework, Protobuf.framework. These are frameworks from Firebase iOS SDK 5.17 and Firebase C++ SDK 5.5.0.
  6. Add UserNotifications.framework to project as Optional.
  7. Set iOS Deployment target to 9.0.
  8. Login to Apple Developer and create authentication key, and register it to Firebase console.
  9. In AppDelegate.m:

    import "FirebaseCore/FIRApp.h"

    import "FirebaseMessaging/FIRMessaging.h"

    import

    @interface AppDelegate () //<-added UNUserNotificationCenterDelegate

    • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [FIRApp configure]; if ([UNUserNotificationCenter class] != nil) { [UNUserNotificationCenter currentNotificationCenter].delegate = self; UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge; [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) { printf("requestAuthorizationWithOptions granted=%d", granted); }]; } else { UIUserNotificationType allNotificationTypes = (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge); UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil]; [application registerUserNotificationSettings:settings]; } [application registerForRemoteNotifications];
  10. Add methods to AppDelegate:

    • (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [FIRMessaging messaging].APNSToken = deviceToken; printf("didRegisterForRemoteNotificationsWithDeviceToken called!"); }

    • (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { printf("didFailToRegisterForRemoteNotificationsWithError"); }

  11. In Info.plist add FirebaseAppDelegateProxyEnabled , type Boolean , set value to NO.
  12. Add -ObjC to target -> Other Linker Flags
  13. Add FirebaseImplement.cpp with hpp header to project. cpp contains only include hpp line.
  14. Run app. Log: 2019-02-26 14:56:37.695107+0900 fcmtest2[821:126237] [DYMTLInitPlatform] platform initialization successful 2019-02-26 14:56:37.734503+0900 fcmtest2[821:126088] FIID: Loading UIApplication FIRIID category 2019-02-26 14:56:37.791910+0900 fcmtest2[821:126088] FCM: Loading UIApplication FIRFCM category 2019-02-26 14:56:37.971120+0900 fcmtest2[821:126088] Setting up iOS 10 message delegate. 2019-02-26 14:56:37.987322+0900 fcmtest2[821:126233] 5.17.0 - [Firebase/Core][I-COR000022] Firebase Analytics is not available. To add it, include Firebase/Core in the Podfile or add FirebaseAnalytics.framework to the Link Build Phase 2019-02-26 14:56:38.106397+0900 fcmtest2[821:126088] Metal GPU Frame Capture Enabled 2019-02-26 14:56:38.109046+0900 fcmtest2[821:126088] Metal API Validation Enabled 2019-02-26 14:56:38.522326+0900 fcmtest2[821:126088] ERROR: Attempting to complete future before FCM initialized. requestAuthorizationWithOptions granted=1
  15. And neither didRegisterForRemoteNotificationsWithDeviceToken nor didFailToRegisterForRemoteNotificationsWithError are called.
2

2 Answers

1
votes

I have faced same issue. Please below code to get FCM Token.

UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in
    DispatchQueue.main.async {
        self.getFCMToken()
    }
}

extension AppDelegate{
    fileprivate func getFCMToken() {
        InstanceID.instanceID().instanceID(handler: { (result, error) in
            if error == nil {
                print("FCM Token HS: \(result!.token)")
            }
        })
    }
}

Note:[FIRMessaging messaging].APNSToken will take some time to generate FCM Token.

0
votes

I think I got it. Firebase C++ SDK does not support "method swizzling". Only Firebase iOS SDK does. When included C++ SDK I got many link errors, so I added iOS SDK as well. When C++ SDK frameworks are included my app build does some weird things like unexpected build errors. I think if I need method swizzling to be disabled, there is no way to do it when using C++ SDK. iOS SDK works mostly for me, so I think it's time to remove that C++ wrapper and call FCM API via Objective-C.