[Flutter] Integration Of Push/Local Notifications In ANDROID

As most of us are aware of the notifications we receive day in and day out when using apps like Gmail, Whatsapp, Teams, Slack and others on your smart phones. In order to implement such kind of notifications in your custom build App you can follow the below steps

Step-1

Install plugin (firebase_messaging : ^7.0.3) in pubspec.yaml

[Note: Firebase_messaging is a plugin in  Flutter app that can receive and process push notifications as well as data messages in Android and iOS.]
 

To integrate your plugin into the Android part of your app:

1. Create a project in  Firebase Console  for your Android app.

2. Download the google-services.json file from the Firebase and place it inside your project.

3. Add dependencies
:dependencies{
//Example existing classpath
classpath ‘com.android.tools.build:gradle:3.5.3’ 
//Add the google-services classpath
classpath ‘com.google.gms:google-services:4.3.2’
}

4. Add the apply plugin to the [project]/android/app/build.gradle.file
// ADD THIS AT THE BOTTOM
apply plugin: ‘com.google.gms.google-services’

5. Optional, but recommended – If you want to be notified in your app (via onResume  and onLaunch, see below) when the user clicks on a notification in the system tray, include the following intent-filter within the < activity >  tag of your android/app/src/main/AndroidManifest.xml:
< intent-filter >
< action
android:name=”FLUTTER_NOTIFICATION_CLICK” / >
< category
android:name=”android.intent.category.DEFAULT” / >
< /intent-filter >

By default background messaging is not enabled. To handle messages in the background:

5.a. Add the com.google.firebase:firebase-messaging dependency in your app-level build.gradle file that is typically located at < app-name > /android/app/build.gradle.
dependencies {

// …

implementation 
‘com.google.firebase:firebasemessaging < latest_version>’
}

< app-name >/android/app/src/main/java/MainActivity

if your file(above path) is in java then proceed below step 5.b else if your file is in kotlin follow step 5.c.

5.b. Add an Application.java class to your app in the same directory as your MainActivity.java. This is typically found in  < app-name >/android/app/src/main/java/< app-organization-path >.

packageio.flutter.plugins.firebasemessagingexample;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService;

public class Application extends FlutterApplication implements PluginRegistrantCallback {
@Override
public void onCreate () {
super.onCreate();
FlutterFirebaseMessagingService.setPluginRegistrant(this);
}
@Override
public voidregisterWith(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
}


5.c.

package com.example.projectName;
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
class Application : FlutterApplication(), PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
FlutterFirebaseMessagingService.setPluginRegistrant(this);
}
override fun registerWith(registry: PluginRegistry?)
{
io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin.registerWith(registry?.registrarFor(“io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin”));
}
}

5.d. In Application.java, make sure to change packageio.flutter.plugins.firebasemessagingexample; to your package’s identifier. Your package’s identifier should be something like com.domain.myapplication.

package com.domain.myapplication;

5.e. Set name property of application in AndroidManifest.xml. This is typically found in < app-name >/android/app/src/main/.

< application android:name=”.Application” … > 

5.f. Define a TOP-LEVEL or STATIC function to handle background messages

Future < dynamic >myBackgroundMessageHandler(Map< String,dynamic > message)
async {
if (message.containsKey(‘data’)) {
// Handle data message
final dynamic data = message[‘data’];
} if (message.containsKey(‘notification’)) {
// Handle notification message
final dynamic notification = message[‘notification’];
}
// Or do other work.
}

Step-2

Install plugin (flutter_local_notifications: ^2.0.0+1) in pubspec.yaml

This plugin helps to show messages as a pop-up notification

  1. Notification icons should be added as a drawable resource. By default, the flutter icon is shown in the popup, if you wish to change then add a custom icon to  < app-name >/android/app/src/main/res/drawable/.

Scheduled notifications

If your application needs the ability to schedule notifications then you need to request permissions to be notified when the phone has been booted as scheduled notifications use the AlarmManager API to determine when notifications should be displayed. However, they are cleared when a phone has been turned off. Requesting permission requires adding the following to the manifest (i.e. your application’s AndroidManifest.xml file)

< uses-permission
android:name=”android.permission.RECEIVE_BOOT_COMPLETED”/ >

The following is also needed to ensure notifications remain scheduled upon a reboot and after an application is updated.

< receiver android:name=”com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver”>
< intent-filter >
< action
   android:name=”android.intent.action.BOOT_COMPLETED”/ >
< action
   android:name=”android.intent.action.MY_PACKAGE_REPLACED”/ >
< /intent-filter >
< /receiver >

Developers will also need to add the following so that plugin can handle displaying scheduled notifications.

< receiver     android:name=”com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver” / >

If the vibration pattern of an Android notification will be customized then add the following

< uses-permission
   android:name=”android.permission.VIBRATE” / >

Fullscreen intent notifications

If your application needs the ability to schedule full-screen intent notifications, add the following to the manifest (i.e. your application’s AndroidManifest.xml file)

< uses-permission
   android:name=”android.permission.USE_FULL_SCREEN_INTENT” / >

You’ll also need to add the next attributes to the activity you’re opening, usually, the class that extends FlutterActivity. These make sure the screen turns on and shows when the device is locked.

< activity
android:showWhenLocked=”true”
android:turnScreenOn=”true” >

2.Initialisation

The first step is to create a new instance of the plugin class and then initialize it with the settings to use for each platform.

The below code works for both android and ios.

FlutterLocalNotificationsPlugin
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
const AndroidInitializationSettings
initializationSettingsAndroid = AndroidInitializationSettings(‘app_icon’);
final IOSInitializationSettings
initializationSettingsIOS = IOSInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveLocalNotification);
final MacOSInitializationSettings
initializationSettingsMacOS =MacOSInitializationSettings();
final InitializationSettings initializationSettings = InitializationSettings(
       android: initializationSettingsAndroid,
       iOS: initializationSettingsIOS,
       macOS: initializationSettingsMacOS);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: selectNotification);

3.selectNotification that should fire when a notification has been tapped on via the onselectNotification callback. Specifying this callback is entirely optional but here it will trigger navigation to another page and display the payload associated with the notification.

Future selectNotification(String payload) async {
if (payload != null) {
   debugPrint(‘notification payload: $payload’);
}
await Navigator.push(
context,
MaterialPageRoute< void >(builder: (context) => SecondScreen(payload)),
);
}

Then call the requestPermissions method with desired permissions at the appropriate point in your application.

final bool result = await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);

Below is the full code for initialization of flutter local notification for both android and ios.

class NotificationPlugin {
FlutterLocalNotificationsPlugin
flutterLocalNotificationsPlugin;
final BehaviorSubject< ReceivedNotification >
didReceiveLocalNotificationSubject =
BehaviorSubject< ReceivedNotification >();
var initializationSettings;
NotificationPlugin._() {
init();
}
init() {
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
if (Platform.isIOS){
_requestIosPermission();
}
initializePlatformSpecifics();
}
initializePlatformSpecifics() {
var initializationSettingsAndroid =
AndroidInitializationSettings(‘notification’);
var initializationSettingsIos = IOSInitializationSettings(
       requestAlertPermission: true,
       requestBadgePermission: true,
      requestSoundPermission: false,
onDidReceiveLocalNotification: (id, title, body, payload) async {
ReceivedNotification receivedNotification = ReceivedNotification(
id: id, title: title, body: body, payload : payload ); didReceiveLocalNotificationSubject.add(receivedNotification);
},
);
initializationSettings = InitializationSettings(
initializationSettingsAndroid,initializationSettingsIos);
}
_requestIosPermission() {
flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}
setListenerForLowerVersions(Function
onNotificationInLowerVersions) { didReceiveLocalNotificationSubject.listen((receivedNotification) { onNotificationInLowerVersions(receivedNotification);
});
}
setOnNotificationClick(Function onNotificationClick)
async {

await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: (String payload) async {
onNotificationClick(payload);
});
}
Future < void >showNotification(data) async {
var androidChannelSpecifics = AndroidNotificationDetails(
‘fcm_default_channel’, ‘CHANNEL_NAME’, ‘CHANNEL_DESCRIPTION’,
importance: Importance.Max,
priority: Priority.High,
playSound: true,
timeoutAfter: 5000);
var iosChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics =NotificationDetails(androidChannelSpecifics,iosChannelSpecifics); 
await flutterLocalNotificationsPlugin.show(0, ‘Title’,
‘body’, platformChannelSpecifics,
payload: ‘Test Payload’);
}
}
NotificationPlugin notificationPlugin = NotificationPlugin._();
class ReceivedNotification {
final int id;
final String title;
final String body;
final String payload;
ReceivedNotification({
@required this.id,
@required this.title,
@required this.body,
@required this.payload,
});
}

Place below code in landing page in order to work in resume/background/foreground
 
class LandingPage extends StatefulWidget {
_Home createState() => _Home();
}
class _Home extends State< LandingPage > {
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
@overridevoid initState() {
_messages = List< Message >();
_configureFirebaseListeners();
 notificationPlugin
.setListenerForLowerVersions(onNotificationInLowerVersions);
notificationPlugin.setOnNotificationClick(onNotificationClick);
}
getNotifications(type) {
Navigator.of(context).push(new MaterialPageRoute(
builder: (BuildContext context) =>
NotificationList(details: notificationsList)));
}
static Future < dynamic >myBackgroundMessageHandler(
Map< String,dynamic> message) async {
if (message.containsKey(‘data’)) {
// write your code
}
if (message.containsKey(‘notification’)) {
// write your code
}
// Or do other work.
}
_configureFirebaseListeners() {
_firebaseMessaging.requestNotificationPermissions(
const IosNotificationSettings(
         sound: true,
         badge: true,
         alert: true),
);
_firebaseMessaging.configure(
onMessage: (Map< String,dynamic > message) async {
print(‘onMessage: $message’);
await notificationPlugin.showNotification(message);
this.getNotifications(‘onMessage’);
}
onBackgroundMessage: myBackgroundMessageHandler,
onLaunch: (Map message) async {
print(‘onLaunch: $message’);
await this.getNotifications(‘launch’);
}
onResume: (Map< String,dynamic >message) async {
print(‘onResume: $message’);
await this.getNotifications(‘resume’);
}
onNotificationInLowerVersions(ReceivedNotification receivedNotification) {}
onNotificationClick(String payload) async {
// write your code
}
}
}


 

Leave A Comment

Your email address will not be published. Required fields are marked *