How to configure Firebase Messaging with latest version in Flutter? - firebase

I was using the below line of code for firebase messaging configuration for flutter noticification configuration , but now after integrating to the latest version of the firebase messaging it is giving me error
CODE LINE
messaging.configure(onMessage: (Map<String, dynamic> message){}
ERROR in DART Analysis
error: The method 'configure' isn't defined for the type 'FirebaseMessaging'.

FirebaseMessaging.configure() is removed by firebase team:
Reason:
The previous implementation of configure() caused unintended side effects if called multiple times (either to register a different handler or remove handlers). This change allows developers to be more explicit about registering handlers and removing them without affecting others via Streams.
Use FirebaseMessaging.onMessage method to get messages
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
});
Use FirebaseMessaging.onMessageOpenedApp as a replacement for onLaunch and onResume handlers.
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('A new onMessageOpenedApp event was published!');
Navigator.pushNamed(context, '/message',
arguments: MessageArguments(message, true));
});

Please check following example.
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_messaging/firebase_messaging/example/lib/main.dart
#override
void initState() {
super.initState();
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage message) {
if (message != null) {
Navigator.pushNamed(context, '/message',
arguments: MessageArguments(message, true));
}
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
if (notification != null && android != null) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channel.description,
// TODO add a proper drawable resource to android, for now using
// one that already exists in example app.
icon: 'launch_background',
),
));
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('A new onMessageOpenedApp event was published!');
Navigator.pushNamed(context, '/message',
arguments: MessageArguments(message, true));
});
}

Building on Jitesh's answer, for me implementation of getInitialMessage is needed to make the navigation works when the app is terminated (replacement for onLaunch)
// workaround for onLaunch: When the app is completely closed (not in the background) and opened directly from the push notification
FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage message) {
print('getInitialMessage data: ${message.data}');
_serialiseAndNavigate(message);
});
// onMessage: When the app is open and it receives a push notification
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print("onMessage data: ${message.data}");
});
// replacement for onResume: When the app is in the background and opened directly from the push notification.
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('onMessageOpenedApp data: ${message.data}');
_serialiseAndNavigate(message);
});

Updated One:
FirebaseMessagingService is important to get started in the beginning of app. And for that sake, you need to follow this:
Declare this function first :
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
debugPrint("Firebase Messaging firebase is initialized");
await Firebase.initializeApp();
}
And call this function in the main(){} of app:
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
And then you will be able to use these functions:
FirebaseMessaging.onMessage method to get messages
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
});
FirebaseMessaging.onMessageOpenedApp as a replacement for onLaunch and onResume handlers.
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('A new onMessageOpenedApp event was published!');
Navigator.pushNamed(context, '/message',
arguments: MessageArguments(message, true));
});

Event handling:
Event handling has been reworked to provide a more intuitive API for developers. Foreground-based events can now be accessed via Streams:
FirebaseMessaging.onMessage Returns a Stream called when an incoming FCM payload is received whilst the Flutter instance is in the foreground, containing a [RemoteMessage].
FirebaseMessaging.onMessageOpenedApp Returns a [Stream] that is called when a user presses a notification displayed via FCM. This replaces the previous onLaunch and onResume handlers.
FirebaseMessaging.onBackgroundMessage() Sets a background message handler to trigger when the app is in the background or terminated.
IosNotificationSettings:

Related

Local Notifications Plugin showing notification twice

I want to play a custom notification sound only when app is in background or terminated state and if i implement onBackgroundMessage i am getting two notifications one automatic (default sound) and another manual(with custom sound)
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
await Firebase.initializeApp();
print('Handling a background message ${message.messageId}');
if (message.notification != null) {
print(message.notification.title);
print(message.notification.body);
flutterLocalNotificationsPlugin.show(
message.notification.hashCode,
message.notification.title,
message.notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channel.description,
playSound: true,
importance: Importance.max,
priority: Priority.high,
sound: RawResourceAndroidNotificationSound('sound'),
),
iOS: IOSNotificationDetails()
));
}
// Create a notification for this
}

How to open my app from background and navigate to a page on receiving a notification message in flutter?

I need to open the app automatically on receiving a notification message. Is it possible in flutter?
Below is the code for handling the background messages and it works.
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print('Handling a background message ${message.messageId}');
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
......
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp()
)
);
What I need is I have a separate page that needs to popup when that particular function is executed (When the app is in background). Can anyone help me out with this! Thanks in advance
await _firebaseMessaging.subscribeToTopic('topic name');
_firebaseMessaging.configure
(
// The onMessage function triggers when the notification is
received while we are running the app.
onMessage: (message) async
{
setState(()
{
messageTitle = message["notification"]["title"];
messageDescription = message["notification"]["description"];
notificationAlert = "New Notification Alert";
});
},
// The onResume function triggers when we receive the notification alert in the device notification bar and opens the app through the push notification itself. In this case, the app can be running in the background or not running at all.
onResume: (message) async
{
print("ON RESUME");
setState(()
{
messageTitle = message["data"]["title"];
messageDescription = message["notification"]["description"];
notificationAlert = "Application opened from Notification";
});
},
onLaunch: (Map<String, dynamic> message) async // Called when app is terminated
{
print("onLaunch: $message");
var data = message["data"];
print(data);
// Navigator.pushNamed(context, "details");
}
);
In this code the onResume function will help you run the app from background so you can code inside onResume and navigate to your specified screen.

Flutter- How can i handle (onPause/OnResume, onStart and OnTerminate) funactionality on flutter using firebase cloud messeging and notifications?

firebase_messaging: ^9.0.0
flutter sdk 2.0.1
I am getting the message notification only when the app is running on background but not for terminate or on process app.
And getting the message A background message could not be handled in Dart as no onBackgroundMessage handler has been registered.
How to handle three functionality (app is running already, app is running on backgroud, app is terminated) into app using the latest version of cloud messegning library?
Here is the code that i have tried to implement.
#override
void initState() {
super.initState();
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage message) {
print('I am called 1');
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
print('I am called 2');
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('I am called 3');
});
}

How to show a push-notification when the application is open(foreground), when OnMessage is triggered?

Im use Flutter and Firebase Messaging.
I im configure Firebase like in example: firebaseMessaging.configure(
onMessage: ...
onLaunch: ...
onResume: ...
)
But i wanna see push-notification even when app is open.
Roughly speaking onMessage should work like onResume. How can i do this?
onMessage: (Map<String, dynamic> message) async {
showNotification(message);
print('on message $message');
}
showNotification(Map<String, dynamic> msg) async {
var android = new AndroidNotificationDetails(
'your channel id',//channel id
"your channel name",//channel name
"your channel description",//channel desc todo set all this right
icon: 'mipmap/launcher_icon'//add your icon here
);
var iOS = new IOSNotificationDetails();
var platform = new NotificationDetails(android, iOS);
await flutterLocalNotificationsPlugin
.show(0, msg['notification']['title'], msg['notification']['body'], platform);
}
I used flutter_local_notifications: ^1.2.2 to show local notification foreground.
Additionally, if you are implementing for IOS don't forget to ask for notification permission.

In Flutter, how do we use Firebase Messaging onBackgroundMessage to create a notification, using flutter_local_notifications?

We are working on an encrypted chat application where we use Firebase Messaging for data notifications. Some client-side logic needs to be done upon receiving a data notification, before showing an actual notification to the user. For example, a phone number will have to be translated to a local contact name. This translation is done by lookup with a map that is already available globally.
The data notifications are received just fine and the onBackgroundMessage callback is called as well. However, it seems impossible to access any kind of state from the onBackgroundMessage function. For example, printing the phone number of the logged in user returns null.
Printing this same global variable from the onMessage callback works just fine.
Running flutter_local_notifications from onMessage works fine, but again, does not work at all from onBackgroundMessage as 'no implementation could be found for the method .show()'. At the moment, it claims that flutterLocalNotificationsPlugin is null, which it isn't really.
It seems to us that onBackgroundMessage has no access to anything the app provides, as soon as the app is backgrounded. Something has to be done to make some of the scope/context available to the background process. For now, that would mainly be the flutter_local_notifications plugin in its entirety, as well as the local contacts list to translate phone number to name.
Has anyone got any idea how to do this?
Here is some of the code:
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
final _chatRepository = ChatRepository();
Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message) async {
if(message.containsKey('data')) {
await _showNotification(message);
return Future<void>.value();
}
}
Future _showNotification(message) async {
List<String> numbers = [];
numbers.add(message['data']['sender']);
var name = await _chatRepository.translatePhoneNumbersToChatName(numbers);
var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
'channel id', 'channel name', 'channel description',
importance: Importance.Max, priority: Priority.High);
var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
var platformChannelSpecifics = new NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
name,
message['data']['body'],
platformChannelSpecifics,
payload: message['data']['body'],
);
}
class NotificationHandler {
final FirebaseMessaging fcm = FirebaseMessaging();
StreamSubscription iosSubscription;
String deviceToken = "";
Future<void> initialize() async {
flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
var initializationSettingsAndroid =
new AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOS = new IOSInitializationSettings(onDidReceiveLocalNotification: onDidReceiveLocalNotification);
var initializationSettings = new InitializationSettings(initializationSettingsAndroid, initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings, onSelectNotification: onClickNotification);
fcm.configure(
onMessage: (Map<String, dynamic> message) async {
if(message.containsKey('data')) {
print(message);
_showNotification(message);
}
},
onBackgroundMessage: Platform.isIOS
? null
: backgroundMessageHandler,
onLaunch: (Map<String, dynamic> message) async {
if(message.containsKey('data')) {
print(message);
_showNotification(message);
}
},
onResume: (Map<String, dynamic> message) async {
if(message.containsKey('data')) {
print(message);
_showNotification(message);
}
},
);
_updateDeviceToken();
}
.
.
.
Of course, the initialize above is called early on in the application lifecycle.
class NotificationHandler {
static final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); // make it a static field of the class
// ...
}
Future _showNotification(message) async {
// ...
await NotificationHandler.flutterLocalNotificationsPlugin.show( // access it
// ...
);
}
Hope this works for you.
This plugin explains it all better than I could, but it just so happens that the background is a completely different isolate/context and thus it has no access to any plugins if they use an old (pre Flutter 12) API.
https://pub.dev/packages/android_alarm_manager#flutter-android-embedding-v1
Embedding v1 requires you to register any plugins that you want to access from the background. Doing this makes it flutter_local_notifications work properly.
Unfortunately, FCM docs are heavily lacking.

Resources