Implementing Push Notifications
1. Setting Up Firebase Cloud Messaging
| Step | Description | Details |
|---|---|---|
| 1. Create Firebase Project | Set up a new Firebase project in the Firebase Console | Go to Firebase Console and create a new project or select an existing one. |
| 2. Add Flutter App to Project | Register your Flutter app with Firebase | Follow the Firebase setup wizard to add your Flutter app and download the configuration file (e.g., google-services.json for Android, GoogleService-Info.plist for iOS). |
| 3. Add Dependencies | Include Firebase Messaging in your pubspec.yaml | Add the following to pubspec.yaml:firebase_messaging: ^15.0.0 |
| 4. Configure Platform-Specific Files | Update Android and iOS configuration files | For Android, update android/app/src/main/AndroidManifest.xml to include permission and service declarations. For iOS, update ios/Runner/Info.plist to enable push notifications. |
| 5. Initialize Firebase | Initialize Firebase in your Flutter app | In main.dart, ensure Firebase is initialized before using messaging features. |
Example: Initializing Firebase in Flutter
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
Note: Ensure that you have enabled Firebase Cloud Messaging in the Firebase Console under the "Cloud Messaging" section.
2. Requesting Notification Permissions
| Permission | Description | Platform Support | Notes |
|---|---|---|---|
| notification_permissions | Allows app to request permission for displaying notifications | iOS / Android | Required before sending any push notifications |
Example: Requesting Notification Permissions (iOS)
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> requestIOSPermission() async {
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}
Example: Requesting Notification Permissions (Android)
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> requestAndroidPermission() async {
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}
Note: On Android 13+, you must explicitly request notification permissions at runtime using
requestPermissions.
Warning: If notification permissions are not granted, the app will not be able to display local or push notifications.
3. Getting FCM Token
| Property | Description | Notes |
|---|---|---|
| FirebaseMessaging.getToken() | Retrieves the FCM token for the device | Must be called after FirebaseApp is initialized |
Example: Getting FCM Token
import 'package:firebase_messaging/firebase_messaging.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await FirebaseApp.initializeApp();
String? token = await FirebaseMessaging.getToken();
print('FCM Token: $token');
}
Note: The token may be null if the device is not registered with FCM or if there's an error during registration.
4. Handling Foreground Messages
| Property | Description | Example |
|---|---|---|
| onMessage | Callback when a message is received while the app is in the foreground | |
| onMessageOpenedApp | Callback when a notification is tapped while the app is in the foreground | |
Example: Handling Foreground Messages
import 'package:firebase_messaging/firebase_messaging.dart';
void main() {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Received foreground message: ${message.notification?.title}');
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('Notification tapped in foreground: ${message.notification?.title}');
});
}
Note: Foreground messages are only received when the app is in the foreground. Use
onMessage to handle messages while the app is running.
5. Handling Background Messages
| Property | Description | Values |
|---|---|---|
| onBackgroundMessage | Callback function for handling messages when the app is in the background | Future<void> Function(RemoteMessage message) |
Example: Setting up background message handling
import 'package:firebase_messaging/firebase_messaging.dart';
Future<void> backgroundMessageHandler(RemoteMessage message) async {
print('Handling background message: ${message.data}');
}
void main() {
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
runApp(MyApp());
}
Note: Ensure that the background message handler is registered before initializing Firebase in your app.
Warning: Background message handling requires platform-specific setup (e.g., AndroidManifest.xml for Android).
Key Points
- Use
FirebaseMessaging.onBackgroundMessageto register a handler for background messages - Handler must be a top-level function or static method
- Background handler runs in a separate isolate on Android
- Ensure proper permissions and platform configuration
6. Handling Notification Taps
| Property | Description | Usage |
|---|---|---|
| onSelectNotification | Callback when a notification is tapped | onSelectNotification: (String payload) => print(payload) |
| onSelectPushNotification | Callback for handling notification tap in background | onSelectPushNotification: (Map<String, dynamic> notification) => handleNotification(notification) |
Example: Handling Notification Tap
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
Future<void> init() async {
const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
final InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
}
Future<void> onSelectNotification(String payload) async {
print("Notification tapped: $payload");
}
Note: Ensure
onSelectNotification is set during plugin initialization to handle foreground taps.
Warning: Background notification handling requires platform-specific setup (e.g., Android
NotificationChannel, iOS UNUserNotificationCenter).
7. Using Local Notifications
| Property | Description | Example |
|---|---|---|
| title | Title of the notification | "New Message" |
| body | Body text of the notification | "You have a new message from John." |
| id | Unique identifier for the notification | 12345 |
| sound | Sound to play when notification is shown | "default" |
| icon | Icon to display in the notification | "ic_notification" |
Example: Schedule a Local Notification
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('app_icon');
final InitializationSettings initializationSettings =
InitializationSettings(android: initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
Future showNotification() async {
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel',
'High Importance Notifications',
importance: Importance.high,
);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
const NotificationDetails notificationDetails = NotificationDetails(
android: AndroidNotificationDetails(
'channel_id',
'channel_name',
channelDescription: 'Channel Description',
icon: 'app_icon',
),
);
await flutterLocalNotificationsPlugin.show(
0,
'New Message',
'You have a new message from John.',
notificationDetails,
);
}
Note: Ensure that you have added the necessary permissions in your AndroidManifest.xml and iOS configuration files for local notifications to work properly.
8. Scheduling Notifications
| Property | Description | Values |
|---|---|---|
| schedule | Schedule for notification | DateTime or TimeOfDay |
| repeating | Repeat interval | false, daily, weekly, monthly |
| id | Unique identifier for notification | String |
Example: Schedule a notification
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
void scheduleNotification() {
var scheduledDate = DateTime.now().add(Duration(minutes: 5));
var notificationDetails = NotificationDetails(
android: AndroidNotificationDetails(
'channel_id',
'channel_name',
channelDescription: 'channel_description',
),
);
flutterLocalNotificationsPlugin.schedule(
0,
'Scheduled Notification',
'This notification was scheduled',
scheduledDate,
notificationDetails,
);
}
Note: Ensure
flutter_local_notifications is added to your dependencies.
9. Creating Notification Channels
| Property | Description | Values |
|---|---|---|
| id | Unique identifier for the channel | "channel_id" |
| name | User-visible name of the channel | "Push Notifications" |
| description | Short description of the channel's purpose | "Used for push notifications from the app" |
| importance | Importance level affecting how notifications are displayed | 1-5 (1 = lowest, 5 = highest) |
| sound | Sound to play when notification is received | "default" or path to sound file |
| showBadge | Whether to display a badge on the app icon | true or false |
| lightColor | Color of the LED light (Android O+) | #FF0000 (RGB hex) |
| vibrationPattern | Custom vibration pattern (Android O+) | [500, 200, 500] (array of longs) |
Example: Creating a Notification Channel in Flutter
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher');
final InitializationSettings initializationSettings =
InitializationSettings(android: initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
const AndroidChannel channel = AndroidChannel(
id: 'high_importance_channel',
name: 'High Importance Notifications',
description:
'This channel is used for important notifications.',
importance: Importance.high,
);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
}
Note: Notification channels are only supported on Android 8.0 (API level 26) and above.
10. Customizing Notification Appearance
| Property | Description | Values |
|---|---|---|
| title | Title of the notification | String |
| body | Main content of the notification | String |
| icon | Icon to display in the notification | String (path to asset) |
| sound | Sound to play when notification is received | String (path to sound file) |
| badge | Badge to display on app icon | String (path to asset) |
| channelId | Channel ID to send notification to | String |
Example: Custom Notification
final NotificationDetails notificationDetails = NotificationDetails(
android: AndroidNotificationDetails(
'custom_channel_id',
'Custom Channel',
channelDescription: 'Channel for custom notifications',
icon: 'notification_icon',
sound: 'notification_sound',
badge: 'notification_badge',
),
iOS: IOSNotificationDetails(
sound: 'notification_sound.aiff',
),
);