Nibesh Khadka
Posted on April 4, 2022
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 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 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:
- You'll be asked to choose the right project from the list(if there are multiple).
- You'll also be asked to choose apps for the project. Chose only android and ios. You can select/deselect with the space bar.
- 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
- You'll be asked to choose from different Firebase products. Choose four: Firestore, Firebase Storage, Cloud Functions, and Emulators.
- 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.
- Just press enter, on all the file options provided there.
- Select the language to use for firebase functions. I'll select JS.
- Select 'y' for both linter and installations.
- During the process, you'll be prompted to Emulators settings. Here, please select four products: Authentication, Firestore, Storage, and Functions Emulators.
- Just press enter to select the default ports.
- Enter "Y" to enable emulator UI.
- 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.
- 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.
- 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.
- Instruct all the products to use Firebase Emulator if it's running.
Now, we need to call this function on 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.
Summary
In this very short series, we moved on to connect our app to the Firebase project. Let's retrace our steps, we:
- Created Firebase Project & Firestore DB.
- Installed Firebase CLI & FlutterFire CLI
- Installed Firestore, Functions, Storage, and Authentication packages.
- Then connected these Firebase products to the cloud Firebase project on Firebase Init.
- During the initialization, we also installed Firebase Emulator and did all the configuration.
- Wrote a simple and easy function that handles Local Emulator Connection for us.
- Now know how to solve the port unavailable error issue.
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 future blogs.
Posted on April 4, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 22, 2024