flutter: If app delegate swizzling is disabled, remote notifications received by UIApplicationDelegate need to be forwarded to FIRAuth's

2,566

Best Available Solution AppDelegate.swift:

import UIKit
import Flutter
import FirebaseAuth
import FirebaseMessaging

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [. 
UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().delegate = self
    }

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: 
launchOptions)
}

// https://firebase.google.com/docs/auth/ios/phone-auth#appendix:-using-phone-sign-in-without-swizzling
// https://firebase.google.com/docs/cloud-messaging/ios/client#token-swizzle-disabled
override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    // Pass device token to auth
    Auth.auth().setAPNSToken(deviceToken, type: .unknown)

    // Pass device token to messaging
    Messaging.messaging().apnsToken = deviceToken

    return super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
}

// https://firebase.google.com/docs/auth/ios/phone-auth#appendix:-using-phone-sign-in-without-swizzling
// https://firebase.google.com/docs/cloud-messaging/ios/receive#handle-swizzle
override func application(_ application: UIApplication,
                          didReceiveRemoteNotification notification: [AnyHashable : Any],
                          fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    // Handle the message for firebase auth phone verification
    if Auth.auth().canHandleNotification(notification) {
        completionHandler(.noData)
        return
    }

    // Handle it for firebase messaging analytics
    if ((notification["gcm.message_id"]) != nil) {
        Messaging.messaging().appDidReceiveMessage(notification)
    }

    return super.application(application, didReceiveRemoteNotification: notification, fetchCompletionHandler: completionHandler)
}

// https://firebase.google.com/docs/auth/ios/phone-auth#appendix:-using-phone-sign-in-without-swizzling
override func application(_ application: UIApplication, open url: URL,
                          options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
    // Handle auth reCAPTCHA when silent push notifications aren't available
    if Auth.auth().canHandle(url) {
        return true
    }

    return super.application(application, open: url, options: options)
   }
}
Share:
2,566
Enzo Lizama
Author by

Enzo Lizama

Student of software engineering at UPC , passionate about Android technologies, C ++ for ACM-ICPC competencies and web development. @HackSpacePeru Kotlin lover Passionate HackSpacer

Updated on December 12, 2022

Comments

  • Enzo Lizama
    Enzo Lizama over 1 year

    When i want to use sms auth with firebase the app fails only on iOS

    The APN certificate is alredy configured on firebase and FirebaseAppDelegateProxyEnabled is NO in Info.plist. The error is occuring during the verifyPhoneNumber method.

    Here is the flutter doctor

    Doctor summary (to see all details, run flutter doctor -v):
    [✓] Flutter (Channel unknown, v1.7.0, on Mac OS X 10.14.5 18F132, locale en-PE)
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    [✓] Xcode - develop for iOS and macOS (Xcode 10.2.1)
    [✓] iOS tools - develop for iOS devices
    [✓] Android Studio (version 3.4)
    [!] IntelliJ IDEA Ultimate Edition (version 2019.1)
        ✗ Flutter plugin not installed; this adds Flutter specific functionality.
        ✗ Dart plugin not installed; this adds Dart specific functionality.
    [✓] VS Code (version 1.36.1)
    [✓] Connected device (1 available)
    

    Here is my code

    void sendSms(String fullNumber) {
        FirebaseAuth.instance.verifyPhoneNumber(
          phoneNumber: fullNumber,
          timeout: Duration(minutes: 1),
          verificationCompleted: (AuthCredential phoneAuthCredential) async {
            _smsController?.add('loading');
            FirebaseUser firebaseUser = await FirebaseAuth.instance
                .signInWithCredential(phoneAuthCredential);
            _verifyUser(firebaseUser);
          },
          verificationFailed: (err) {
            print(err.message);
            print(err.code);
            _smsController?.add('UNKNOWN_ERROR');
          },
          codeSent: (verificationId, [forceResendingToken]) {
            _verificationId = verificationId;
            _smsController?.add('code_sent');
          },
          codeAutoRetrievalTimeout: (verificationId) {},
        );
      }
    

    And the error messages:

    flutter: If app delegate swizzling is disabled, remote notifications received by UIApplicationDelegate need to be forwarded to FIRAuth's canHandleNotificaton: method.

    flutter: verifyPhoneNumberError

  • Aamir
    Aamir about 2 years
    Can you explain a bit more about what is being changed here?
  • Purushotam Kumar
    Purushotam Kumar almost 2 years
    Make sure to add these imports ``` import FirebaseAuth import FirebaseMessaging ```