Push notifications are a vital feature for modern mobile applications, enabling real-time communication and engagement with users. In Flutter, implementing push notifications can significantly enhance user experience by delivering timely updates, reminders, and personalized content. This blog post explores how to implement push notifications in Flutter applications using Firebase Cloud Messaging (FCM), the most common and reliable service for push notifications.
What are Push Notifications?
Push notifications are messages sent from a server to a mobile device. These notifications appear outside of the application UI, allowing developers to communicate with users even when the app is not actively running. Push notifications can be used for a variety of purposes, including:
- Updates and Alerts: Notify users about new content, events, or updates.
- Reminders: Set reminders for tasks, appointments, or deadlines.
- Promotions and Offers: Inform users about special deals, promotions, or discounts.
- Social Interactions: Notify users about new followers, likes, or comments.
Why Use Firebase Cloud Messaging (FCM)?
Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that allows you to reliably deliver messages at no cost. It supports both Android and iOS platforms, making it an ideal choice for Flutter developers targeting multiple platforms.
Steps to Implement Push Notifications in Flutter
Follow these steps to implement push notifications in your Flutter application using FCM:
Step 1: Set Up Firebase Project
- Go to the Firebase Console and create a new project or select an existing one.
- Follow the setup instructions for both Android and iOS, including adding the
google-services.jsonfile to your Android project and configuring your iOS project with the necessary certificates.
Step 2: Add Firebase to Your Flutter Project
- Add the
firebase_coreandfirebase_messagingdependencies to yourpubspec.yamlfile:
dependencies:
flutter:
sdk: flutter
firebase_core: ^2.15.0
firebase_messaging: ^14.6.0
- Run
flutter pub getto install the dependencies.
Step 3: Initialize Firebase
In your main.dart file, initialize Firebase:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Push Notifications',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Push Notifications'),
),
body: Center(
child: Text('Push Notification Demo'),
),
);
}
}
Step 4: Request Notification Permissions
In your Flutter app, request notification permissions from the user:
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
@override
void initState() {
super.initState();
requestNotificationPermissions();
}
void requestNotificationPermissions() async {
FirebaseMessaging messaging = FirebaseMessaging.instance;
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
print('User granted permission');
} else if (settings.authorizationStatus == AuthorizationStatus.provisional) {
print('User granted provisional permission');
} else {
print('User declined or has not accepted permission');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Push Notifications'),
),
body: Center(
child: Text('Push Notification Demo'),
),
);
}
}
Step 5: Get the Device Token
Retrieve the FCM token for the device:
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
class _MyHomePageState extends State {
@override
void initState() {
super.initState();
requestNotificationPermissions();
getFCMToken();
}
void requestNotificationPermissions() async {
// ... (previous code)
}
void getFCMToken() async {
FirebaseMessaging messaging = FirebaseMessaging.instance;
String? token = await messaging.getToken();
print('FCM Token: $token');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Push Notifications'),
),
body: Center(
child: Text('Push Notification Demo'),
),
);
}
}
Step 6: Handle Incoming Messages
Handle incoming messages while the app is in the foreground and background:
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// Create a flutter local notifications plugin
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print("Handling a background message: ${message.messageId}");
// Show local notification
showNotification(message);
}
void showNotification(RemoteMessage message) async {
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'your_channel_id',
'your_channel_name',
channelDescription: 'your_channel_description',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker',
);
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
message.notification?.title,
message.notification?.body,
platformChannelSpecifics,
payload: 'item x',
);
}
class _MyHomePageState extends State {
@override
void initState() {
super.initState();
// Initialize local notifications
var initializationSettingsAndroid =
const AndroidInitializationSettings('@mipmap/ic_launcher');
var initializationSettings =
InitializationSettings(android: initializationSettingsAndroid);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
requestNotificationPermissions();
getFCMToken();
// Handle background messages
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
// Handle foreground messages
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Got a message whilst in the foreground!');
print('Message data: ${message.data}');
if (message.notification != null) {
print('Message also contained a notification: ${message.notification}');
showNotification(message); // Show notification when app is in foreground
}
});
}
// ... (previous code)
}
Install the flutter_local_notifications package:
dependencies:
flutter_local_notifications: ^16.3.2
Step 7: Send Test Notifications
- In the Firebase Console, go to Cloud Messaging.
- Click on “Send your first message”.
- Enter the notification title and text.
- Send the notification to the FCM token you retrieved in Step 5.
Best Practices for Push Notifications
- User Opt-In: Always request permission from the user before sending notifications.
- Relevance: Ensure notifications are relevant and valuable to the user.
- Frequency: Avoid overwhelming users with too many notifications.
- Personalization: Personalize notifications to increase engagement.
- Localization: Localize notifications to support multiple languages.
- Analytics: Track notification delivery and engagement metrics to optimize performance.
Conclusion
Implementing push notifications in Flutter applications can significantly improve user engagement and deliver real-time value. By following the steps outlined in this blog post and adhering to best practices, you can effectively integrate Firebase Cloud Messaging (FCM) into your Flutter apps and enhance the user experience. With properly implemented push notifications, your Flutter applications will stand out and keep users informed and connected.