paint-brush
How to Connect Firebase to Flutter SDK on Cloud and Local Emulatorby@kcl
522 reads
522 reads

How to Connect Firebase to Flutter SDK on Cloud and Local Emulator

by Khadka's Coding Lounge.August 21st, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

This is a short article on how to set up a Firebase project on Flutter. Follow the instructions from this [code lab] by Google. We'll use the [FlutterFire] package for our development. Let's create a Flutter project first and install and configure the FlutterFire package. We also install Firebase Core, Firebase Auth, Firebase Cloud Functions, and Firebase Storage packages for flutter. We need to initialize firebase now, we will do it later on after Flutter fire configurations.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - How to Connect Firebase to Flutter SDK on Cloud and Local Emulator
Khadka's Coding Lounge. HackerNoon profile picture

Intro

Hello and welcome, I am Nibesh Khadka from Khadka's Coding Lounge This is a short article on how to set up a Firebase project on Flutter. Feel free to skip through the TOC if you feel like it.


Setting Up

Before we set up firebase let's create a Flutter project first. Open the terminal and on the directory of your choice let's create a flutter project.


Note: I am using Linux OS.


flutter create flutter_firebase_connection
cd flutter_firebase_connection/

# open in vs code
code .


Create A Firebase Project

Please, create a Firebase project on the firebase console. If you have never created a Firebase project then follow the instructions from this code lab by Google.


Install Firebase CLI

We'll rely on the FlutterFire package for our development. Configuring the FlutterFire package can be done with FlutterFire CLI. But FlutterFire CLI relies on the Firebase CLI. Follow the instruction there to install and login into the firebase account. No, need to initialize firebase now, we will do it later on after FlutterFire CLI configurations.


Install Dependencies

After the firebase CLI installation, before we link our project to the firebase project, we'll install some dependencies. On your terminal:


# Root of the flutter project
# Firebase core
flutter pub add firebase_core

# Firebase Auth
flutter pub add firebase_auth

# Firebase Firestore
flutter pub add cloud_firestore

# Firebase Cloud Functions
flutter pub add cloud_functions

# Firebase Storage
flutter pub add firebase_storage


We've installed Firebase Core, Firebase Auth, Firebase Cloud Functions, and Firebase Storage packages for flutter.


Install and Configure FlutterFire CLI

Let's install and configure flutter CLI on the terminal


# Install Firebase CLI
dart pub global activate flutterfire_cli

# On the root of your project
# configur cli
flutterfire configure


During the configuration process:

  1. You'll be asked to choose the right project from the list(if there are multiple).
  2. You'll also be asked to choose apps for the project. Chose only android and ios. You can select/deselect with the space bar.
  3. You'll be asked to provide the bundle id for IOS. I just gave the same one as android: com.example.app.


Now we're done with flutter fire installation and configurations, and next, we need to initialize it.


Firebase Initialization

On the main.dart file of the project let's initialize firebase.


// Import 
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
import 'package:flutter/material.dart';

void main() async {
  //  concrete binding for applications based on the Widgets framewor
  WidgetsFlutterBinding.ensureInitialized();
// Initialize Firebase
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  runApp(const MyApp());
}


Set-Up Firebase Backend: Cloud

If you'll be writing a lot of backend code you should separate the flutter frontend and firebase backend side for both security and clean code. So, let's set up firebase separately for both cloud and emulators.


Reminder: Before we start configuration, make sure to create a Firestore database(on test mode) from the firebase console of the project you've created. Otherwise, you'll get an error during the process telling you there's no database created.


# On the root of your project
firebase init


  1. You'll be asked to choose from different Firebase products. Choose four: Firestore, Firebase Storage, Cloud Functions, and Emulators.
  2. Next, you have to choose the Firebase project or create one. Since we've already created one, chose the right project from the existing ones.
  3. Just press enter, on all the file options provided there.
  4. Select the language to use for firebase functions. I'll select JS.
  5. Select 'y' for both linter and installations.
  6. During the process, you'll be prompted to Emulators settings. Here, please select four products: Authentication, Firestore, Storage, and Functions Emulators.
  7. Just press enter to select the default ports.
  8. Enter "Y" to enable emulator UI.
  9. Press enter for the rest.


Now, we've set up all the necessities. Wait there's still more, we still haven't linked the flutter project to Firebase Emulator Suite.


Connect Firebase Emulator Suite to Flutter Project.

To connect to the emulator we once again need to make some changes to the main.dart file.


Import required dependencies if you haven't already.


import 'dart:io' show Platform; // Its required for emulator 
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:cloud_functions/cloud_functions.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';


Create a global boolean useEmulator.


// Outside of any class or methods, before main()
const bool _useEmulator = true;


Create a function that'll connect to the emulator with the required settings.


// Outside of main, preferably at the end of the file
// Settings for firebase emulator connection
Future _connectToEmulator() async {
  // Provide url to the emulator, localhost might not work on android emulator.
  final host = Platform.isAndroid ? '22.0.4.08' : 'localhost'; //#1
  // Provide port for all the local emulator prodcuts
  // #2
  const authPort = 9099;
  const firestorePort = 8080;
  const functionsPort = 5001;
  const storagePort = 9199;

  // Just to make sure we're running locally
  print("I am running on emulator");

  // Instruct all the relevant firebase products to use the firebase emulator
  // # 3
  await FirebaseAuth.instance.useAuthEmulator(host, authPort);
  FirebaseFirestore.instance.useFirestoreEmulator(host, firestorePort);
  FirebaseFunctions.instance.useFunctionsEmulator(host, functionsPort);
  FirebaseStorage.instance.useStorageEmulator(host, storagePort);
}


Let's go through the vitals.

  1. When running on an android emulator it's actually not localhost. So, it can give you errors so, check the platform and provide the right URL.
  2. Each firebase product will run on its port. So, provide the right port. You can find the port for all products in the firebase.json file.
  3. Instruct all the products to use Firebase Emulator if it's running.


Now, we need to call this function on the main() method after you initialize firebase.


// Set app to run on firebase emulator
  if (_useEmulator) {
    await _connectToEmulator();
  }


Final Code

We're all set to use the emulator now. The final form of our main.dart is:


import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
import 'dart:io' show Platform; // Its required for emulator
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:cloud_functions/cloud_functions.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';

// Outside of any class or methods, before main()
const bool _useEmulator = true;

void main() async {
  //  concrete binding for applications based on the Widgets framewor
  WidgetsFlutterBinding.ensureInitialized();
// Initialize Firebase
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
// Set app to run on firebase emulator
  if (_useEmulator) {
    await _connectToEmulator();
  }
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('App bar'),
        ),
        body: const Center(
          child: Text("Flutter Fireabse Connection App"),
        ));
  }
}

// Settings for firebase emulator connection
Future _connectToEmulator() async {
  // Provide url to the emulator, localhost might not work on android emulator.
  final host = Platform.isAndroid ? '22.0.4.08' : 'localhost'; //#1
  // Provide port for all the local emulator prodcuts
  // #2
  const authPort = 9099;
  const firestorePort = 8080;
  const functionsPort = 5001;
  const storagePort = 9199;

  // Just to make sure we're running locally
  print("I am running on emulator");

  // Instruct all the relevant firebase products to use the firebase emulator
  // # 3
  await FirebaseAuth.instance.useAuthEmulator(host, authPort);
  FirebaseFirestore.instance.useFirestoreEmulator(host, firestorePort);
  FirebaseFunctions.instance.useFunctionsEmulator(host, functionsPort);
  FirebaseStorage.instance.useStorageEmulator(host, storagePort);
}


Run the firebase emulator


// On terminal
firebase emulators:start


When you run your android emulator you should see the "I am running on emulator" message(emulator should be running).


Error: Could not start Firestore Emulator, port taken.

At some point when we accidentally forget to close the port, we'll get an error that the port is already taken. To fix that we have to kill the port.


# Provide the port that has been given in an error message like 8080
npx kill-port 8080


Now, that the active port has been terminated, you can start the emulator again, which will look like the image below.


Emulator Screen Shot.


Summary

In this very short series, we moved on to connect our app to the Firebase project. Let's retrace our steps, we:

  1. Created Firebase Project & Firestore DB.
  2. Installed Firebase CLI & FlutterFire CLI
  3. Installed Firestore, Functions, Storage, and Authentication packages.
  4. Then connected these Firebase products to the cloud Firebase project on Firebase Init.
  5. During the initialization, we also installed Firebase Emulator and did all the configuration.
  6. Wrote a simple and easy function that handles Local Emulator Connection for us.
  7. Now know how to solve the port unavailable error issue.


Blog By Khadka's Coding Lounge


Show Support

This is it, we're done with the connection. Now, you can proceed with your development. I hope everything went well for you. This is Nibesh Khadka, from Khadka's Coding Lounge. Make sure to show support by liking, sharing, commenting, and subscribing to the newsletter.





Also published here.