Flutter Firebase Integration
Firebase is Google's backend platform. It gives your Flutter app a real-time database, user authentication, cloud storage, and more — without building a custom server. This topic covers setup, authentication, and Firestore database usage.
What Firebase Offers
┌─────────────────────────────────────────────────────┐ │ FIREBASE │ ├──────────────────┬──────────────────────────────────┤ │ Authentication │ Login with email, Google, phone │ │ Firestore │ Cloud NoSQL database │ │ Storage │ Upload and serve files/images │ │ Realtime DB │ Sync data instantly across users │ │ Cloud Functions │ Run server code without a server │ │ Analytics │ Track how users use your app │ └──────────────────┴──────────────────────────────────┘
Step 1 — Create a Firebase Project
- Go to console.firebase.google.com
- Click "Add Project" and give it a name
- Disable Google Analytics (optional for learning)
- Click "Create Project"
Step 2 — Connect Flutter to Firebase
The easiest method uses the Firebase CLI and FlutterFire CLI tools.
Install Firebase CLI (run once): ────────────────────────────────── npm install -g firebase-tools firebase login Install FlutterFire CLI: ────────────────────────────────── dart pub global activate flutterfire_cli Connect your Flutter app: ────────────────────────────────── flutterfire configure (Follow the prompts — select your Firebase project)
This creates a firebase_options.dart file in your project automatically.
Step 3 — Add Firebase Packages
In pubspec.yaml:
─────────────────
dependencies:
firebase_core: ^3.0.0
firebase_auth: ^5.0.0
cloud_firestore: ^5.0.0
Run: flutter pub get
Step 4 — Initialize Firebase in main.dart
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
Firebase Authentication
Email and Password Sign Up
import 'package:firebase_auth/firebase_auth.dart';
Future<void> signUp(String email, String password) async {
try {
UserCredential credential = await FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email, password: password);
print('User created: ${credential.user?.uid}');
} on FirebaseAuthException catch (e) {
if (e.code == 'email-already-in-use') {
print('This email is already registered.');
} else {
print('Error: ${e.message}');
}
}
}
Login
Future<void> login(String email, String password) async {
try {
UserCredential credential = await FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
print('Logged in as: ${credential.user?.email}');
} on FirebaseAuthException catch (e) {
print('Login failed: ${e.message}');
}
}
Logout and Check Auth State
// Logout
await FirebaseAuth.instance.signOut();
// Check if user is logged in
User? currentUser = FirebaseAuth.instance.currentUser;
if (currentUser != null) {
print('Logged in: ${currentUser.email}');
} else {
print('Not logged in');
}
// Listen to auth state changes (auto redirect)
FirebaseAuth.instance.authStateChanges().listen((User? user) {
if (user == null) {
// Go to login screen
} else {
// Go to home screen
}
});
Cloud Firestore — NoSQL Database
Firestore stores data as documents inside collections — like folders containing JSON files.
Firestore Structure:
─────────────────────────────────────────────────
Collection: users
└── Document: user123
├── name: "Ravi"
├── email: "ravi@mail.com"
└── city: "Delhi"
Collection: products
└── Document: prod456
├── name: "Running Shoes"
├── price: 2499
└── stock: 50
Add a Document
import 'package:cloud_firestore/cloud_firestore.dart';
final db = FirebaseFirestore.instance;
// Auto-generated ID
await db.collection('users').add({
'name': 'Priya',
'email': 'priya@mail.com',
'city': 'Mumbai',
'createdAt': Timestamp.now(),
});
// Custom ID (e.g. user's UID)
await db.collection('users').doc(userId).set({
'name': 'Priya',
'email': 'priya@mail.com',
});
Read a Document
DocumentSnapshot doc = await db.collection('users').doc(userId).get();
if (doc.exists) {
Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
print('Name: ${data['name']}');
}
Read a Collection (Live Stream)
// One-time fetch
QuerySnapshot snapshot = await db.collection('products').get();
for (var doc in snapshot.docs) {
print(doc['name']);
}
// Real-time listener (updates UI automatically)
db.collection('products').snapshots().listen((QuerySnapshot snapshot) {
for (var doc in snapshot.docs) {
print('${doc['name']}: ₹${doc['price']}');
}
});
Update and Delete
// Update specific fields
await db.collection('users').doc(userId).update({'city': 'Bangalore'});
// Delete a document
await db.collection('users').doc(userId).delete();
Firestore in Flutter UI with StreamBuilder
StreamBuilder<QuerySnapshot>(
stream: db.collection('products').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
final docs = snapshot.data!.docs;
return ListView.builder(
itemCount: docs.length,
itemBuilder: (context, index) {
final data = docs[index].data() as Map<String, dynamic>;
return ListTile(
title: Text(data['name']),
trailing: Text('₹${data['price']}'),
);
},
);
},
)
Firebase Security Rules
By default, Firestore is locked. Set up security rules in the Firebase Console so only authenticated users can read or write data.
// Allow read/write only to authenticated users:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
