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.
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 .
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.
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.
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.
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:
com.example.app
.
Now we're done with flutter fire installation and configurations, and next, we need to initialize it.
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());
}
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
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.
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.
firebase.json
file.
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();
}
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).
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.
In this very short series, we moved on to connect our app to the Firebase project. Let's retrace our steps, we:
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.