Reputation: 127
I am using Firebase Cloud Messaging package for flutter. I want that whenever a user taps on the received notification, the flutter app opens and navigate to a particular screen depending on the data sent by fcm.
But I am not able to achieve desired behaviour when either app is in the background or app is closed since onResume and onLaunch handler are never called. I have tried a number of solution like creating notification channel , using package like flutter_local_notifications etc. But nothing worked for me.
Here is my FirebaseMessagingService class to handle fcm related tasks
class FirebaseMessagingService {
final FirebaseMessaging _fcm = FirebaseMessaging();
final RouterService _routerService = locator<RouterService>();
final LocalStorageService _localStorage = locator<LocalStorageService>();
Future initialise() async {
if (Platform.isIOS) {
_fcm.requestNotificationPermissions(IosNotificationSettings());
}
_fcm.configure(
onMessage: (Map<String, dynamic> message) async {
Map<String, dynamic> arguments = {};
Map<String, dynamic> data = message['data'];
if (data.containsKey('argument')) {
if (data.containsKey('value')) {
arguments[data['argument']] = data['value'];
}
}
_routerService.navigationKey.currentState
.pushReplacementNamed('${data['route']}', arguments: arguments);
},
onLaunch: (Map<String, dynamic> message) async {
Map<String, dynamic> arguments = {};
Map<String, dynamic> data = message['data'];
if (data.containsKey('argument')) {
if (data.containsKey('value')) {
arguments[data['argument']] = data['value'];
}
}
_routerService.navigationKey.currentState
.pushReplacementNamed('${data['route']}', arguments: arguments);
},
onResume: (Map<String, dynamic> message) async {
Map<String, dynamic> arguments = {};
Map<String, dynamic> data = message['data'];
if (data.containsKey('argument')) {
if (data.containsKey('value')) {
arguments[data['argument']] = data['value'];
}
}
_routerService.navigationKey.currentState
.pushReplacementNamed('${data['route']}', arguments: arguments);
},
onBackgroundMessage: _myBackgroundMessageHandler);
}
static Future<dynamic> _myBackgroundMessageHandler(
Map<String, dynamic> message) async {
final RouterService _routerService = locator<RouterService>();
if (message.containsKey('data')) {
// Handle data message
Map<String, dynamic> arguments = {};
Map<String, dynamic> data = message['data'];
if (data.containsKey('argument')) {
if (data.containsKey('value')) {
arguments[data['argument']] = data['value'];
}
}
_routerService.navigationKey.currentState
.pushReplacementNamed('${data['route']}', arguments: arguments);
}
if (message.containsKey('notification')) {
// Handle notification message
final dynamic notification = message['notification'];
}
}
}
Can anyone help me out with the issue??
Upvotes: 0
Views: 674
Reputation: 247
I found a solution for that. Firstly you have to add this code into your manifest:
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
When you have done that, you have to pass your firebase cloud messaging:
click_action => FLUTTER_NOTIFICATION_CLICK
Then you can also pass as data for example route => detailScreen
.
When you mave done that, you can call firebase messaging functions like onResume
or OnLaunch
, by checking that rout you passed in the FCM.
When you check the route you can navigate any screen with this function:
//PRIVATE METHOD TO HANDLE NAVIGATION TO SPECIFIC PAGE
void _navigateToSignalsPage(Map<String, dynamic> message) {
final MessageBean item = _itemForMessage(message);
// Clear away dialogs
// Navigator.popUntil(context, (Route<dynamic> route) => route is PageRoute);
if (!item.route.isCurrent) {
print('heey girl ${item.route}');
Navigator.push(
context, MaterialPageRoute(builder: (context) => HomePage(selectedPage: 0,)));
}
}
Upvotes: 1