Loading... Search articles

Search for articles

Sorry, but we couldn't find any matches...

But perhaps we can interest you in one of our more popular articles?
Practical guide: Flutter + Firebase + Codemagic (for iOS)

Practical guide: Flutter + Firebase + Codemagic (for iOS)

Nov 5, 2020

Use M1 Mac mini VMs by default with Codemagic🚀 Build faster

According to the latest Stack Overflow Developer Survey, Firebase is one of the most loved databases in the year 2020.

In case you are new to Firebase, it’s a cloud-based service provided by Google to enhance mobile and web app development. Firebase takes the load of managing the in-house mobile application infrastructure. It provides many useful services that make our lives easier. The most used services are:

  • Authentication
  • Cloud Firestore
  • Storage
  • Cloud Messaging
  • Crashlytics

Most mobile app developers use Firebase services for a different purpose. Firebase also provides Test Lab, which offers test devices in the cloud for automated testing. Firebase supports iOS, Android, and web apps written using native technologies, such as Swift, Kotlin, or JavaScript. On top of that, it also supports cross-platform mobile app development frameworks, such as Flutter.

Firebase has official documentation on how to configure the Firebase SDK with Flutter apps. In this post, we will provide a step-by-step guide on how to set up the Firebase SDK for Flutter apps and publish those apps securely using the Codemagic CI/CD solution.

Prerequisites

In order to follow this guide, you need the following:

  • Access to the Firebase console (usually linked with the Google account)
  • A Flutter project (in which you want to add Firebase support)
  • Completed iOS setup for the Flutter project

In this article, we will use the Fire Test app and set up Firebase plugins for the iOS version of the Flutter app. You can do a similar setup for the Android version of the Flutter app.

Firebase console: Project setup

To get started with Firebase, you need to have a Google account. Follow the steps below to create a new Firebase project:

  • Go to the Firebase console, and log in with your Google account credentials.

  • Click on Add project.

  • Enter a Project name and click on Continue.

  • We will be taking a look at Crashlytics in this article. So, keep Enable Google Analytics marked. Click on Continue.

  • If you’ve chosen to enable analytics, then you will need to connect or create a Google Analytics account. Click on Create project.

  • Wait for the Firebase project setup to complete. Now, click on Continue.

You will be taken to the dashboard of the Firebase project.

Firebase: App setup

It’s time to add our iOS app to the Firebase project. Flutter creates both the iOS and the Android version of the app. In the Flutter app source code, you can see separate directories for the ios and android app. In order to add the app to Firebase, you have to complete the platform-specific setup. There is a separate set of instructions for Flutter projects, which require fewer steps than native apps.

Let’s add the iOS version of the Flutter app to Firebase by clicking on the iOS icon on the project overview page.

You will be asked to enter a few details for the iOS app, such as the bundle ID, nickname, and App Store ID.

Only the bundle ID is mandatory. You can get the bundle ID of the iOS app from Xcode. Open the ios/ directory in Xcode, and click on Runner in the top-left corner. You can then see the bundle identifier on the General tab of your main target.

In our case, it’s com.souvikbiswas.fireTest. If you prefer using the command line, you can execute the following command by passing the scheme and project workspace of your app.

cd ios $ xcodebuild -workspace Runner.xcworkspace/ -scheme Runner -showBuildSettings | grep PRODUCT_BUNDLE_IDENTIFIER

This will print the bundle identifier of your app. Just enter the details and click on Register app.

In the next step, Firebase will ask you to download the GoogleService-Info.plist file and put it in the iOS app directory.

Open the ios folder of the project directory in Xcode by right-clicking and selecting Open in Xcode. Now, drag and drop the file that you downloaded into the Runner sub-folder. When a dialog box appears, make sure that Runner is selected in the “Add to targets” box. Then click Finish.

For an iOS app setup, Firebase will guide you through creating a Podfile, installing pods, etc. However, you don’t have to perform these steps for the Flutter iOS app setup. So, skip steps 3 and 4, and you will reach the last step. Just select Continue to console.

On the Firebase dashboard of your project, you will see that the iOS version of the Flutter app has been added to Firebase.

One more step before we start building the app: Navigate to Project settings > General, and enter your email in the Support email field.

Similarly, you can also set up the Flutter Android app by following the instructions for Android, but we won’t go into it in this tutorial.

Get FlutterFire plugins

As mentioned earlier, Firebase provides different services, like authentication, storage, crash reporting, etc. For each service, there are specific Flutter plugins, which are collectively known as FlutterFire. The plugins include platform-specific code for accessing services and APIs on each platform. As Flutter is a cross-platform mobile application development framework, these plugins can be used for both iOS and Android. You can find the list of all the available plugins on the FlutterFire page.

In order to add Firebase services, we need to get the required plugins and add them to your pubspec.yaml file. Let’s get the Firebase Core plugin and add it to the Fire Test project.

dependencies:
  firebase_core: ^0.5.2

Once you add the dependency, you can download those dependencies using the following command:

flutter package get

This command will download the Firebase Core plugin and create the .flutter-plugins file in the root of the project. This file contains the list of all plugins that are imported into the app.

Add the Crashlytics FlutterFire plugin

Let’s add the Crashlytics FlutterFire plugin to our Flutter project. This will report crashes in the Firebase dashboard.

Add this plugin to your pubspec.yaml file:

dependencies:
  firebase_crashlytics: ^0.2.3

Now, again run the following command:

flutter package get

This command will download the Crashlytics plugin. Once the plugin is downloaded, you can import it into the Flutter app and enable crash reporting for your app.

Using Firebase Crashlytics

In order to set up the “Fire Test” app for Crashlytics, we need to first set up CocoaPods and enable Crashlytics from Xcode.

  • Open the ios/ folder in Xcode, and select Runner from the project navigation.

  • Select the Build Phases tab, then click + > New Run Script Phase.

  • Add the following to the Run Script text box:

    "${PODS_ROOT}/FirebaseCrashlytics/run"
    

  • Finally, rebuild the app using:

    flutter run
    

This step is needed to run the app locally and get the Firebase Crashlytics service working.

Let’s build the app now!

Go to the main.dart file and add the following:

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
  FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fire Test',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Fire Test'),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            FlatButton(
                child: const Text('Key'),
                onPressed: () {
                  FirebaseCrashlytics.instance.setCustomKey('foo', 'bar');
                }),
            FlatButton(
                child: const Text('Log'),
                onPressed: () {
                  FirebaseCrashlytics.instance.log('Simulated crash');
                }),
            FlatButton(
                child: const Text('Crash'),
                onPressed: () {
                  FirebaseCrashlytics.instance.crash();
                }),
            FlatButton(
                child: const Text('Throw Error'),
                onPressed: () {
                  throw StateError('Uncaught error thrown by app.');
                }),
            FlatButton(
                child: const Text('Async out of bounds'),
                onPressed: () {
                  Future<void>.delayed(const Duration(seconds: 2), () {
                    final List<int> list = <int>[];
                    print(list[100]);
                  });
                }),
            FlatButton(
              child: const Text('Record Error'),
              onPressed: () {
                try {
                  throw 'error_example';
                } catch (error, stackTrace) {
                  FirebaseCrashlytics.instance.recordError(error, stackTrace);
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

This is just an example app showing the use of the Crashlytics plugin. If we run the app and click on the Crash button, it will get reported the next time the app is launched.

The Crashlytics dashboard shows three crashes because I crashed and relaunched the app for the third time.

Troubleshooting

When I ran the app for the first time and navigated to the Crashlytics dashboard, it showed me the following issue, and the crash didn’t get reported:

In order to fix this, follow the steps below:

  • Open the ios/ folder in Xcode.

  • Select your main build target.

  • Open the target’s Build Settings tab, then click All.

  • Search for Debug Information Format".

  • Set Debug Information Format to DWARF with dSYM File for all your build types.

  • Rebuild your app.

Now, if you refresh your Crashlytics dashboard page, it won’t show that issue.

We have successfully added Firebase to our Flutter app. In the next step, we will securely configure Firebase on Codemagic CI/CD.

Configure Firebase on Codemagic (encryption)

Codemagic is the official CI/CD solution for Flutter apps (and all other mobile apps). You can set up your Flutter project for continuous integration and continuous delivery within a minute and without any configuration. If you are new to Codemagic, you can read the Getting Started Guide. At this point, we have successfully configured our app with Firebase and the Firebase Crashlytics Flutter plugin. We will now have to configure the same on CI. Before proceeding, we have to consider the security aspects of our Firebase account.

In our local configuration, we have downloaded the GoogleService-Info.plist file and kept it in the ios directory of the Flutter app. This file contains sensitive data, like the API key and information about the app. This file shouldn’t be checked in to source control or exposed to the world. We have to take certain steps to secure our sensitive data.

Ignore GoogleService-Info.plist in SCM

First, we have to ignore the GoogleService-Info.plist file to avoid it being checked in to the source control manager, such as Git. You can add this file to your .gitignore:

ios/Runner/GoogleService-Info.plist

Once the file has been added to the .gitignore list, it cannot be committed to source control by mistake.

Firebase setup on Codemagic

We have not uploaded the GoogleService-Info.plist file to the version control system, but Codemagic will need that file in order to successfully generate the build artifact for iOS. So, in order to do that, we will provide the encrypted version of the file, which we have to decrypt before the build.

Follow the steps below:

  • Go to the settings of your project on Codemagic.

  • On the right-side menu, under Configuration as code section, click on Encrypt environment variables.

  • Drag and drop the GoogleService-Info.plist file there. It will generate an encrypted version of the file. Copy the encrypted string.

  • Go to the Environment variables section, add a new variable with the key FIREBASE_IOS, and enter the encrypted string as its value.

  • Enter the following for the Pre-build script:

    #!/bin/sh
    
    echo $FIREBASE_IOS | base64 --decode > $CM_BUILD_DIR/ios/Runner/GoogleService-Info.plist
    
    echo "\nListing iOS Directory to confirm the GoogleService-Info.plist is there! "
    ls ios/Runner/
    

Now, click on Start new build to build the app.

Successful build

We have seen how to integrate Firebase into Flutter apps and run the apps securely on the Codemagic CI/CD service. With environment variables, you can securely store the file on Codemagic instead of the repository.

Conclusion

Firebase provides out-of-the-box support for Flutter apps, and there are lots of FlutterFire plugins available. With the combination of Flutter, Firebase, and Codemagic, you can deploy Flutter apps securely with Firebase features enabled in the production.

Practical guide: Flutter + Firebase + Codemagic (for Android)

Some useful resources

Latest articles

Show more posts