Push notifications are a vital part of modern mobile applications, enabling developers to engage users with timely and relevant information. In Flutter, implementing push notifications involves setting up Firebase Cloud Messaging (FCM) and handling notifications appropriately on both Android and iOS platforms. This article will guide you through the process of implementing push notifications in a Flutter app, including configuration and best practices.
What are Push Notifications?
Push notifications are messages that appear on a user’s device outside of the application. They can be used to deliver updates, reminders, promotional offers, or any other kind of timely information. These notifications are ‘pushed’ from a server to the device, regardless of whether the user is currently using the app.
Why Use Push Notifications?
- User Engagement: Re-engage users who might not have used the app recently.
- Timely Updates: Provide immediate information, such as news updates or reminders.
- Marketing: Deliver promotional offers or announce new features.
- Improved User Experience: Offer helpful notifications to improve the user’s overall experience.
Implementing Push Notifications in Flutter: Step-by-Step Guide
Here’s a detailed guide on how to implement push notifications in a Flutter application:
Step 1: Set up Firebase Project
First, you’ll need to create a new project in Firebase or use an existing one:
- Go to the Firebase Console.
- Click “Add project” and follow the steps to create a new project.
Step 2: Add Firebase to Your Flutter App
- Register your apps: In the Firebase console, add both your Android and iOS apps to the project.
- Download configuration files:
- For Android, download
google-services.jsonand place it inandroid/app/directory. - For iOS, download
GoogleService-Info.plistand add it to your Xcode project.
- For Android, download
Step 3: Configure Android
- Add Firebase SDK: In your
android/build.gradle, add the following: - In your
android/app/build.gradle, apply the plugin and add Firebase dependencies:
dependencies {
classpath("com.google.gms:google-services:4.4.0") // Check for the latest version
}
apply plugin: 'com.google.gms.google-services'
dependencies {
implementation platform('com.google.firebase:firebase-bom:32.8.0') // Use the latest BOM
implementation 'com.google.firebase:firebase-messaging-ktx'
}
Step 4: Configure iOS
- Add Firebase SDK: Use CocoaPods. In your
Podfile: - Run
pod install. - Enable Push Notifications: In Xcode, go to your target settings, select “Signing & Capabilities”, and add the “Push Notifications” capability. Also, add the “Background Modes” capability and enable “Remote notifications”.
pod 'Firebase/Messaging'
Step 5: Add Flutter Firebase Messaging Package
Add the firebase_messaging package to your pubspec.yaml file:
dependencies:
firebase_core: ^2.24.2
firebase_messaging: ^14.9.10
Then run flutter pub get.
Step 6: Initialize Firebase in Flutter
Initialize Firebase in your main function:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
Step 7: Request Permission for Notifications
Request permission from the user to send notifications:
import 'package:firebase_messaging/firebase_messaging.dart';
Future 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');
}
}
Step 8: Get the Device Token
Get the device token to send targeted notifications:
Future getDeviceToken() async {
FirebaseMessaging messaging = FirebaseMessaging.instance;
return await messaging.getToken();
}
Step 9: Handle Incoming Notifications
Handle incoming notifications using listeners:
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
Future handleFirebaseMessaging() async {
// 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}');
displayNotification(message);
}
});
// Handle when app is opened from notification
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('Opened app from notification: ${message.notification}');
// Navigate to specific screen based on the notification
});
}
@pragma('vm:entry-point')
Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print("Handling a background message: ${message.messageId}");
}
Future displayNotification(RemoteMessage message) async {
//Show notification using flutter_local_notifications plugin
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
description: 'This channel is used for important notifications.', // description
importance: Importance.max,
);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'high_importance_channel',
'High Importance Notifications',
channelDescription: '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');
}
Step 10: Display Notifications using flutter_local_notifications
Add the flutter_local_notifications package to your pubspec.yaml file:
dependencies:
flutter_local_notifications: ^16.3.2
And then implement notification display as shown above in Step 9. Ensure correct initialization:
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await initializeLocalNotifications();
runApp(MyApp());
}
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
Future initializeLocalNotifications() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher');
const DarwinInitializationSettings initializationSettingsIOS =
DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
const InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onDidReceiveNotificationResponse: (NotificationResponse notificationResponse) async {
// Handle when a user taps on a notification
}
);
}
Best Practices
- Handle all notification states: Implement handlers for background, foreground, and terminated app states.
- Use specific channels for different notifications: Android requires the use of notification channels to categorize different types of notifications.
- Secure the Firebase Server Key: Store the server key securely and avoid exposing it in your client-side code.
- Test notifications on both Android and iOS: Ensure the notification behavior is consistent across platforms.
Conclusion
Implementing push notifications in a Flutter application involves several steps, from setting up a Firebase project to handling incoming messages and displaying them appropriately. By following the guidelines and code examples in this article, you can create an engaging notification system that enhances the user experience and keeps users connected to your app.