Firebase Integration — Backend for Flutter Apps
Add authentication, real-time databases, file storage, and push notifications to your Flutter apps with Firebase.
Firebase Overview
Firebase is Google's app development platform that provides a comprehensive suite of backend services. For Flutter developers, it eliminates the need to build and maintain a custom backend.
🔧 Firebase Services for Flutter
- Authentication — Email/password, Google, Apple, phone sign-in
- Cloud Firestore — Real-time NoSQL database
- Cloud Storage — File uploads (images, videos, documents)
- Cloud Messaging (FCM) — Push notifications
- Analytics — User behavior tracking
- Crashlytics — Crash reporting
Setup
pubspec.yaml
dependencies:
firebase_core: ^3.1.0
firebase_auth: ^5.1.0
cloud_firestore: ^5.0.0
firebase_storage: ^12.0.0
firebase_messaging: ^15.0.0
firebase_analytics: ^11.0.0
firebase_crashlytics: ^4.0.0
main.dart
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());
}
💡 CLI Setup Use the FlutterFire CLI for automatic configuration:
dart pub global activate flutterfire_cli && flutterfire configure
Authentication
Firebase Auth provides multiple sign-in methods with minimal code.
auth_service.dart
import 'package:firebase_auth/firebase_auth.dart';
class AuthService {
final _auth = FirebaseAuth.instance;
Stream<User?> get authStateChanges => _auth.authStateChanges();
User? get currentUser => _auth.currentUser;
Future<UserCredential> register({
required String email,
required String password,
}) async {
return _auth.createUserWithEmailAndPassword(
email: email, password: password,
);
}
Future<UserCredential> signIn({
required String email,
required String password,
}) async {
return _auth.signInWithEmailAndPassword(
email: email, password: password,
);
}
Future<UserCredential?> signInWithGoogle() async {
final googleUser = await GoogleSignIn().signIn();
if (googleUser == null) return null;
final googleAuth = await googleUser.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
return _auth.signInWithCredential(credential);
}
Future<void> signOut() async {
await GoogleSignIn().signOut();
await _auth.signOut();
}
}
Auth Gate Widget
auth_gate.dart
class AuthGate extends StreamBuilder<User?> {
AuthGate({super.key})
: super(
stream: AuthService().authStateChanges,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const SplashScreen();
}
if (snapshot.hasData) {
return const HomeScreen();
}
return const LoginScreen();
},
);
}
Cloud Firestore
Firestore is a real-time NoSQL database with offline support built into the Flutter SDK.
Data Model
projects (collection)
└── projectId (document)
├── title: "My App"
├── createdAt: Timestamp
└── members (subcollection)
└── memberId (document)
├── role: "admin"
└── joinedAt: Timestamp
CRUD Operations
firestore_service.dart
import 'package:cloud_firestore/cloud_firestore.dart';
class FirestoreService {
final _db = FirebaseFirestore.instance;
Future<void> createProject(Project project) async {
await _db.collection('projects').add(project.toMap());
}
Future<Project?> getProject(String id) async {
final doc = await _db.collection('projects').doc(id).get();
if (!doc.exists) return null;
return Project.fromMap(doc.data()!);
}
Stream<List<Project>> watchProjects() {
return _db.collection('projects')
.orderBy('createdAt', descending: true)
.snapshots()
.map((snapshot) => snapshot.docs
.map((doc) => Project.fromMap(doc.data()))
.toList());
}
Future<void> updateProject(String id, Map<String, dynamic> data) async {
await _db.collection('projects').doc(id).update(data);
}
Future<void> deleteProject(String id) async {
await _db.collection('projects').doc(id).delete();
}
Future<List<Project>> searchProjects({
required String query,
int limit = 20,
}) async {
final snapshot = await _db.collection('projects')
.where('title', isGreaterThanOrEqualTo: query)
.where('title', isLessThanOrEqualTo: '$query\uf8ff')
.limit(limit).get();
return snapshot.docs
.map((doc) => Project.fromMap(doc.data()))
.toList();
}
}
⚠️ Firestore Pricing
Firestore charges per read, write, and delete operation. Use
.snapshots() for real-time data and .get() for one-time reads. Minimize unnecessary reads by using efficient queries and pagination.
Cloud Storage
Firebase Cloud Storage is designed for user-generated content like images, videos, and documents.
storage_service.dart
import 'dart:io';
import 'package:firebase_storage/firebase_storage.dart';
class StorageService {
final _storage = FirebaseStorage.instance;
Future<String> uploadFile({
required File file,
required String path,
void function(double progress)? onProgress,
}) async {
final ref = _storage.ref().child(path);
final uploadTask = ref.putFile(file);
if (onProgress != null) {
uploadTask.snapshotEvents.listen((event) {
onProgress(event.bytesTransferred / event.totalBytes);
});
}
await uploadTask;
return await ref.getDownloadURL();
}
Future<void> deleteFile(String path) async {
await _storage.ref().child(path).delete();
}
}
Cloud Messaging (FCM)
Firebase Cloud Messaging enables push notifications and data messaging to your users' devices.
notification_service.dart
import 'package:firebase_messaging/firebase_messaging.dart';
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(
RemoteMessage message,
) async {
await Firebase.initializeApp();
}
class NotificationService {
final _messaging = FirebaseMessaging.instance;
Future<void> initialize() async {
final settings = await _messaging.requestPermission(
alert: true, badge: true, sound: true,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
final token = await _messaging.getToken();
FirebaseMessaging.onMessage.listen((message) {
_showLocalNotification(message);
});
FirebaseMessaging.onMessageOpenedApp.listen((message) {
_handleNotificationTap(message);
});
await _messaging.subscribeToTopic('announcements');
}
}
}
Analytics & Crashlytics
Custom Events
import 'package:firebase_analytics/firebase_analytics.dart';
final analytics = FirebaseAnalytics.instance;
await analytics.logEvent(
name: 'tutorial_completed',
parameters: {
'tutorial_name': 'flutter_basics',
'duration_seconds': 300,
},
);
Crashlytics
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
try {
// risky operation
} catch (e, stackTrace) {
await FirebaseCrashlytics.instance.recordError(
e, stackTrace,
reason: 'Failed to load user profile',
);
}
await FirebaseCrashlytics.instance.setCustomKey('user_type', 'premium');
Firestore Security Rules
Protect your data with server-side security rules. Never rely on client-side validation alone.
firestore.rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if request.auth != null;
allow write: if request.auth.uid == userId;
}
match /projects/{projectId} {
allow read: if isMember(projectId);
allow create: if request.auth != null;
allow update, delete: if isOwner(projectId);
}
function isMember(projectId) {
return get(/databases/$(database)/documents/projects/$(projectId))
.data.members.hasAny([request.auth.uid]);
}
function isOwner(projectId) {
return get(/databases/$(database)/documents/projects/$(projectId))
.data.ownerId == request.auth.uid;
}
}
}
⚠️ Security Rules are Critical
Misconfigured rules can expose all user data. Test your rules with the Firestore Rules Playground before deploying.
Summary
- Firebase Auth — Quick sign-in with email, Google, Apple, and phone
- Cloud Firestore — Real-time NoSQL database with offline support
- Cloud Storage — File uploads with progress tracking
- FCM — Push notifications and topic messaging
- Analytics & Crashlytics — Track usage and monitor crashes
- Security Rules — Server-side data protection
🚀 Next Step Continue to AI Introduction to learn about integrating AI into Flutter apps.