Integration of Push Notifications in ANDROID using Firebase Messaging and Flutter Local Notifications using Flutter

12-02-2019    Hari Kondlapudi    Views 46

firebase_messaging, with this plugin your Flutter app can receive and process push notifications as well as data messages on Android and iOS

Step-1

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

To integrate your plugin into the Android part of your app, follow these steps:

1: Using the Firebase Console add an Android app to your project: Follow the assistant, download the generated google-services.json file and place it inside android/app.

2: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'
}

3:Add the apply plugin to the [project]/android/app/build.gradle.file

// ADD THIS AT THE BOTTOM
apply plugin: 'com.google.gms.google-services'

4:(optional, but recommended) If 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:

1.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 2 else if your file is in kotlin follow step 3.

2.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);
}
}


3.

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"));
}
}

4.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. Set name property of application in AndroidManifest.xml. This is typically found in < app-name >/android/app/src/main/.

< application android:name=".Application" ... > 

6.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 {
// wite your code
}
}
}


 

Add Comments

Submit Comments

More Blogs


What is Trade Finance Transaction?

Blockchain Technology In Trade Finance Transactions

Hari Kondlapudi        Views 376
block-chain-transform-your-business

BLOCKCHAIN TO TRANSFORM YOUR BUSINESS

Hari Kondlapudi        Views 345
block-chain-transform-your-business

LOCALIZATION WITH REACT

Hari Kondlapudi        Views 69

Contact Us

Address:

Do Systems Inc,
433 Plaza Real, Suite 275
Boca Raton, FL 33432 

Email: sales@dosystems.com
 
Copyright © Do Systems Inc. All rights reserved.