Complete Tutorial: Integrating Firebase with Flutter
This tutorial provides a step-by-step guide to setting up Firebase in a Flutter application, including configuration and implementation of Firebase Authentication, Firestore, and Firebase Cloud Messaging (FCM).
Prerequisites
- Flutter SDK: Ensure Flutter is installed and set up. Run
flutter doctor
to verify. - Firebase Account: Create an account at Firebase Console.
- IDE: Use VS Code, Android Studio, or IntelliJ IDEA with Flutter and Dart plugins.
- Basic Flutter Knowledge: Familiarity with Flutter widgets and Dart programming.
Step 1: Create a Flutter Project
Open your terminal or command prompt.
Run the following command to create a new Flutter project:
flutter create firebase_flutter_app
Navigate to the project directory:
cd firebase_flutter_app
Step 2: Create a Firebase Project
- Go to the Firebase Console.
- Click Add project, enter a project name (e.g.,
FirebaseFlutterApp
), and follow the prompts to create the project. - Once created, you’ll be directed to the project overview page.
Step 3: Add Firebase to Your Flutter App
Firebase provides a CLI tool and plugins to integrate with Flutter. Follow these steps to configure Firebase for both Android and iOS.
3.1 Install Firebase CLI
Install Node.js if not already installed (download from nodejs.org).
Install the Firebase CLI globally using npm:
npm install -g firebase-tools
Log in to Firebase:
firebase login
This opens a browser to authenticate your Google account.
3.2 Add Firebase to Flutter
Add Firebase to Your Flutter Project:
- In the Firebase Console, click Add app > Flutter icon.
- Follow the instructions provided. Firebase will generate configuration files for Android and iOS.
- Download the
google-services.json
(for Android) andGoogleService-Info.plist
(for iOS) files as instructed.
Configure Android:
Place the
google-services.json
file in theandroid/app
directory of your Flutter project.Update
android/build.gradle
(project-level) to include the Google Services plugin:buildscript { dependencies { classpath 'com.google.gms:google-services:4.4.2' } }
Update
android/app/build.gradle
(app-level) to apply the plugin:apply plugin: 'com.google.gms.google-services'
Configure iOS:
- Place the
GoogleService-Info.plist
file in theios/Runner
directory. - Open
ios/Runner.xcworkspace
in Xcode. - Drag the
GoogleService-Info.plist
file into the Runner project in Xcode. - Ensure the file is added to the Runner target.
- Place the
Install FlutterFire CLI:
Install the FlutterFire CLI to streamline Firebase setup:
dart pub global activate flutterfire_cli
Run the FlutterFire configure command in your project directory:
flutterfire configure Add Windows Path to configure fluttefire under environment variable
For Windows:- Search for "Edit the system environment variables" in the Windows search bar and open it.
- Click "Environment Variables."
- Under "System variables" (or "User variables"), find and select the "Path" variable, then click "Edit."
- Click "New" and add the path to the Pub cache bin, e.g.:
text
C:\Users\<YourUsername>\AppData\Local\Pub\Cache\bin
- Select your Firebase project from the list.
- This generates a
firebase_options.dart
file in thelib
directory with platform-specific Firebase configurations.
Step 4: Add Firebase Dependencies to Flutter
Open
pubspec.yaml
and add the required Firebase plugins. For this tutorial, we’ll use Authentication, Firestore, and Cloud Messaging:dependencies: flutter: sdk: flutter firebase_core: ^3.6.0 firebase_auth: ^5.3.1 cloud_firestore: ^5.4.4 firebase_messaging: ^15.1.3
Run
flutter pub get
to install the dependencies.
Step 5: Initialize Firebase in Your Flutter App
Create a
firebase_options.dart
file (if not already generated by FlutterFire CLI) in thelib
directory or use the one generated.Update
main.dart
to initialize Firebase:import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'firebase_options.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Firebase Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: const MyHomePage(), ); } } class MyHomePage extends StatelessWidget { const MyHomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Firebase Flutter')), body: const Center(child: Text('Firebase Initialized!')), ); } }
Run the app to ensure Firebase initializes correctly:
flutter run
Step 6: Implement Firebase Authentication
Firebase Authentication allows users to sign in with email/password, Google, or other providers. Here, we’ll implement email/password authentication.
Create an Auth Service: Create a file
lib/services/auth_service.dart
:import 'package:firebase_auth/firebase_auth.dart'; class AuthService { final FirebaseAuth _auth = FirebaseAuth.instance; // Sign up with email and password Future<User?> signUp(String email, String password) async { try { UserCredential userCredential = await _auth.createUserWithEmailAndPassword( email: email, password: password, ); return userCredential.user; } catch (e) { print(e); return null; } } // Sign in with email and password Future<User?> signIn(String email, String password) async { try { UserCredential userCredential = await _auth.signInWithEmailAndPassword( email: email, password: password, ); return userCredential.user; } catch (e) { print(e); return null; } } // Sign out Future<void> signOut() async { await _auth.signOut(); } // Get current user User? get currentUser => _auth.currentUser; }
Create a Sign-In/Sign-Up UI: Update
lib/main.dart
to include a simple authentication UI:import 'package:flutter/material.dart'; import 'services/auth_service.dart'; class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { final AuthService _auth = AuthService(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); String _status = ''; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Firebase Auth')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _emailController, decoration: const InputDecoration(labelText: 'Email'), ), TextField( controller: _passwordController, decoration: const InputDecoration(labelText: 'Password'), obscureText: true, ), const SizedBox(height: 20), ElevatedButton( onPressed: () async { final user = await _auth.signUp( _emailController.text, _passwordController.text, ); setState(() { _status = user != null ? 'Signed up!' : 'Sign-up failed'; }); }, child: const Text('Sign Up'), ), ElevatedButton( onPressed: () async { final user = await _auth.signIn( _emailController.text, _passwordController.text, ); setState(() { _status = user != null ? 'Signed in!' : 'Sign-in failed'; }); }, child: const Text('Sign In'), ), ElevatedButton( onPressed: () async { await _auth.signOut(); setState(() { _status = 'Signed out'; }); }, child: const Text('Sign Out'), ), const SizedBox(height: 20), Text(_status), ], ), ), ); } }
Test Authentication:
- Run the app and test sign-up, sign-in, and sign-out.
- Ensure Firebase Authentication is enabled in the Firebase Console under Authentication > Sign-in method > Enable Email/Password.
Step 7: Implement Firestore Database
Firestore is a NoSQL database for storing and syncing data. We’ll create a simple app to add and display user data.
Enable Firestore:
- In the Firebase Console, go to Firestore Database > Create database.
- Choose Start in test mode for simplicity and click Next > Enable.
Create a Firestore Service: Create
lib/services/firestore_service.dart
:import 'package:cloud_firestore/cloud_firestore.dart'; class FirestoreService { final CollectionReference users = FirebaseFirestore.instance.collection('users'); // Add user data Future<void> addUser(String uid, String name, String email) async { await users.doc(uid).set({ 'name': name, 'email': email, 'createdAt': FieldValue.serverTimestamp(), }); } // Get user data Stream<DocumentSnapshot> getUser(String uid) { return users.doc(uid).snapshots(); } }
Update UI to Use Firestore: Update
lib/main.dart
to include Firestore functionality:import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import 'services/auth_service.dart'; import 'services/firestore_service.dart'; class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { final AuthService _auth = AuthService(); final FirestoreService _firestore = FirestoreService(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); final _nameController = TextEditingController(); String _status = ''; @override Widget build(BuildContext context) { final user = _auth.currentUser; return Scaffold( appBar: AppBar(title: const Text('Firebase Firestore')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _nameController, decoration: const InputDecoration(labelText: 'Name'), ), TextField( controller: _emailController, decoration: const InputDecoration(labelText: 'Email'), ), TextField( controller: _passwordController, decoration: const InputDecoration(labelText: 'Password'), obscureText: true, ), const SizedBox(height: 20), ElevatedButton( onPressed: () async { final user = await _auth.signUp( _emailController.text, _passwordController.text, ); if (user != null) { await _firestore.addUser( user.uid, _nameController.text, _emailController.text, ); setState(() { _status = 'Signed up and data saved!'; }); } else { setState(() { _status = 'Sign-up failed'; }); } }, child: const Text('Sign Up'), ), const SizedBox(height: 20), if (user != null) StreamBuilder<DocumentSnapshot>( stream: _firestore.getUser(user.uid), builder: (context, snapshot) { if (snapshot.hasData && snapshot.data!.exists) { final data = snapshot.data!.data() as Map<String, dynamic>; return Text( 'Name: ${data['name']}\nEmail: ${data['email']}', ); } return const Text('No user data'); }, ), ], ), ), ); } }
Test Firestore:
- Sign up with a name, email, and password.
- Check the Firebase Console to see the data stored in the
users
collection. - Verify that the UI displays the user’s data in real-time.
Step 8: Implement Firebase Cloud Messaging (FCM)
FCM allows you to send push notifications to your app users.
Enable FCM:
- In the Firebase Console, go to Cloud Messaging > Enable the API if prompted.
- Add your app’s APNs Authentication Key or APNs Certificate for iOS in Project Settings > Cloud Messaging.
Configure FCM in Flutter:
Ensure the
firebase_messaging
dependency is added inpubspec.yaml
.Update
android/app/build.gradle
to include notification permissions:defaultConfig { multiDexEnabled true }
Request Notification Permissions: Update
lib/main.dart
to handle FCM:import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'firebase_options.dart'; Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp(); print('Background message: ${message.messageId}'); } void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); // Request permission for notifications final messaging = FirebaseMessaging.instance; await messaging.requestPermission( alert: true, badge: true, sound: true, ); // Get FCM token final fcmToken = await messaging.getToken(); print('FCM Token: $fcmToken'); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Firebase Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: const MyHomePage(), ); } } class MyHomePage extends StatelessWidget { const MyHomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Firebase FCM')), body: const Center(child: Text('FCM Configured!')), ); } }
Test FCM:
- Run the app and check the console for the FCM token.
- In the Firebase Console, go to Cloud Messaging > Send your first message.
- Enter the FCM token or target your app and send a test notification.
- Verify that the notification appears on your device.
Step 9: Run and Debug
Ensure your device or emulator is connected.
Run the app:
flutter run
Debug common issues:
- Firebase not initialized: Ensure
Firebase.initializeApp
is called before using any Firebase service. - Missing configuration files: Verify
google-services.json
andGoogleService-Info.plist
are correctly placed. - Permission issues: Check notification and Firestore rules in the Firebase Console.
- Firebase not initialized: Ensure
POST Answer of Questions and ASK to Doubt