(β)Log

Flutter: New gradle config

Published on
Authors

If we use the latest Flutter version (3.19.2) and have an old project which is not created from Flutter version 3.19.2 we will get this warning when we try to run your app on Android.

You are applying Flutter's app_plugin_loader Gradle plugin imperatively using the apply script method, which is deprecated and will be removed in a future release. Migrate to applying Gradle plugins with the declarative plugins block: https://flutter.dev/go/flutter-gradle-plugin-apply

To remove that warning we can follow the steps in the official documentation from Flutter. But another issue after we migrate to the new implementation.

We will get this issue when we try to run our app.

E/flutter ( 8069): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: [core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()
E/flutter ( 8069): #0      MethodChannelFirebase.app (package:firebase_core_platform_interface/src/method_channel/method_channel_firebase.dart:193:5)
E/flutter ( 8069): #1      Firebase.app (package:firebase_core/src/firebase.dart:56:41)
E/flutter ( 8069): #2      FirebaseCrashlytics.instance (package:firebase_crashlytics/src/firebase_crashlytics.dart:33:55)
E/flutter ( 8069): #3      main.<anonymous closure> (package:flutter_auth_app/main.dart:28:27)
E/flutter ( 8069): #4      _RootZone.runBinary (dart:async/zone.dart:1666:54)
E/flutter ( 8069): #5      runZonedGuarded.<anonymous closure> (dart:async/zone.dart:1776:18)
E/flutter ( 8069): #6      _Zone._processUncaughtError (dart:async/zone.dart:1081:14)
E/flutter ( 8069): #7      _CustomZone.handleUncaughtError (dart:async/zone.dart:1285:5)
E/flutter ( 8069): #8      Future._propagateToListeners (dart:async/future_impl.dart:752:16)
E/flutter ( 8069): #9      Future._completeError (dart:async/future_impl.dart:651:5)
E/flutter ( 8069): <asynchronous suspension>
E/flutter ( 8069):

That would happen if our current project did not use flutterfire_cli when we set up the Firebase on our project.

Add Firebase Options

As we can see, the error message is No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp() even though we already added the google-services.json in our project. To fix that, we can create a class DefaultFirebaseOptions to handle FirebaseOptions based on the Platform. But we need to manage FirebaseOptions to support multiple environments like in my previous article.

There is the sample for the DefaultFirebaseOptions class


import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
    show defaultTargetPlatform, kIsWeb, TargetPlatform;


class DefaultFirebaseOptions {
  static FirebaseOptions get currentPlatform {
    if (kIsWeb) {
      throw UnsupportedError(
        'DefaultFirebaseOptionsStg have not been configured for web - '
        'you can reconfigure this by running the FlutterFire CLI again.',
      );
    }
    switch (defaultTargetPlatform) {
      case TargetPlatform.android:
        return android;
      case TargetPlatform.iOS:
        return ios;
      default:
        throw UnsupportedError(
          'DefaultFirebaseOptionsStg are not supported for this platform.',
        );
    }
  }

  static const FirebaseOptions android = FirebaseOptions(
    apiKey: String.fromEnvironment("ANDROID_API_KEY"),
    appId: String.fromEnvironment("ANDROID_APP_ID"),
    messagingSenderId: String.fromEnvironment("ANDROID_SENDER_ID"),
    projectId: String.fromEnvironment("ANDROID_PROJECT_ID"),
    storageBucket: String.fromEnvironment("ANDROID_STORAGE_BUCKET"),
  );

  static const FirebaseOptions ios = FirebaseOptions(
    apiKey: String.fromEnvironment("IOS_API_KEY"),
    appId: String.fromEnvironment("IOS_APP_ID"),
    messagingSenderId: String.fromEnvironment("IOS_SENDER_ID"),
    projectId: String.fromEnvironment("IOS_PROJECT_ID"),
    storageBucket: String.fromEnvironment("IOS_STORAGE_BUCKET"),
    androidClientId: String.fromEnvironment("IOS_ANDROID_CLIENT_ID"),
    iosClientId: String.fromEnvironment("IOS_IOS_CLIENT_ID"),
    iosBundleId: String.fromEnvironment("IOS_BUNDLE_ID"),
  );
}

We can see, that all variables are defined using dart-define. so the next step is mapping the FirebaseOptions with our existing Firebase Project.

Mapping FirebaseOptions on Android

We can fill the FirebaseOptions data using data from google-services.json

FirebaseOptionsgoogle-services.json
apiKeycurrent_key
appIdmobilesdk_app_id (make sure to see the package_name is correct with your existing project)
messagingSenderIdproject_number
projectIdproject_id
storageBucketstorage_bucket

Mapping FirebaseOptions on iOS

We can fill the FirebaseOptions data using data from GoogleService-Info.plist

FirebaseOptionsgoogle-services.json
apiKeyAPI_KEY
appIdGOOGLE_APP_ID
messagingSenderIdGCM_SENDER_ID
projectIdPROJECT_ID
storageBucketSTORAGE_BUCKET
androidClientIdANDROID_CLIENT_ID
iosClientIdCLIENT_ID
iosBundleIdBUNDLE_ID

After we mapped our existing Firebase project in Android (google-services.json) and iOS (GoolgeService-Info.plist) we need to update the Firebase Initialization

from :

await Firebase.initializeApp()

to :

await Firebase.initializeApp(
  options: DefaultFirebaseOptions.currentPlatform,
);

and we can run our project normally.

Or you can see my PR on GitHub

Feel free if you have any questions.