'Flutter local notification onSelectNotification can not open a new page when a local notification is clicked

I want my flutter app to open a page when a local notification is clicked. I've defined the following codes in the event listener:

Navigator.push(
   Ccontext,
   MaterialPageRoute(builder: (context) => PendingOrders()),
 );
debugPrint('notification payload: ' + payload);

The event listener is executed successfully and printed the debugPrint's parameter when a local notification is called but it can not open the PendingOrders route.

Here is the full code in the main.dart

  class _MyAppState extends State<MyApp> {
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
@override
void initState() {
  super.initState();

  var android = AndroidInitializationSettings('mipmap/ic_launcher');
  var ios =  IOSInitializationSettings();
  var platform = InitializationSettings(android, ios);
  flutterLocalNotificationsPlugin.initialize(platform,onSelectNotification: onSelectNotification);

  _firebaseMessaging.subscribeToTopic('order-created');
  _firebaseMessaging.configure(
    onMessage: (Map<String, dynamic> message) async {
      print("onMessage: $message");
      showNotification(message);
    },
    onLaunch: (Map<String, dynamic> message) async {
      print("onLaunch: $message");
      print("Hafijur");
    },
    onResume: (Map<String, dynamic> message) async {
      print("onResume: ${message['notification']['data']['click_action']}");
    },
  );
  _firebaseMessaging.requestNotificationPermissions(
      const IosNotificationSettings(sound: true, badge: true, alert: true));
}

showNotification(Map<String, dynamic> msg) async {
  var android = new AndroidNotificationDetails(
    'sdffds dsffds',
    "CHANNLE NAME",
    "channelDescription",
  );
  var iOS = new IOSNotificationDetails();
  var platform = new NotificationDetails(android, iOS);
  await flutterLocalNotificationsPlugin.show(
      0, "New order arrived", "Hey, hurry up! you have a order to deliver", platform,payload: "order created");
}
 Future onSelectNotification(String payload) async {
  this.build(context);
   Navigator.push(
     context,
     MaterialPageRoute(builder: (context) => PendingOrders()),
   );
   if (payload != null) {
    debugPrint('notification payload: ' + payload);
  }
}

@override
Widget build(BuildContext context) {
  return MaterialApp(
    title: 'Flutter Demo',
    theme: Constants.lightTheme,
    debugShowCheckedModeBanner: false,
    routes: {
      "/": (context) => MainScreen(),
      "/login": (context) => LoginPage(),
      "/dashboard": (context) => Dashboard(),
      "/all_orders": (context) => AllOrders(),
      "/pending_orders": (context) => PendingOrders(),
      "/delivered_orders": (context) => DeliveredOrders(),
      "/order": (context) => Order(),
    },
  );
}
}


Solution 1:[1]

To receive payload when app was closed after open with tapping on notification then you have to use getNotificationAppLaunchDetails method

final NotificationAppLaunchDetails? notificationAppLaunchDetails =
await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
String? payload = notificationAppLaunchDetails!.payload;

put this code in main after notification initialization lines

use onSelectNotification will be triggered only if the app is already open when tapping notification.

but if the app is already closed and you want to run it after tapping notification with handling the payload value then you have to use getNotificationAppLaunchDetails

code will be something like following:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  var initializationSettingsAndroid =
      AndroidInitializationSettings('@mipmap/ic_launcher');
  var initializationSettingsIOs = IOSInitializationSettings();
  var initSetttings = InitializationSettings(
      android: initializationSettingsAndroid, iOS: initializationSettingsIOs);
  var cnf = await flutterLocalNotificationsPlugin.initialize(initSetttings,
      onSelectNotification: onSelectNotification);
  final NotificationAppLaunchDetails? notificationAppLaunchDetails =
      await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();

  print('payload=');
  String? payload= notificationAppLaunchDetails!.payload;
  print(payload);

    runApp(
         MaterialApp(        
          home: payload== 'page1' ? Page1() : MainPage()
         )
       ); 
}

Solution 2:[2]

I had a similar issue but this fixed my problem

    _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) {
        displayNotification(message);
        return;
      },
      onResume: (Map<String, dynamic> message) {
        _navigateToItemDetail(message);
        return;
      },
      onLaunch: (Map<String, dynamic> message) {
        _navigateToItemDetail(message);
        return;
      },
    );
void _navigateToItemDetail(Map<String, dynamic> message) async {
    Navigator.popUntil(context, (Route<dynamic> route) => route is PageRoute);
    await Navigator.of(context).push(PageRouteBuilder(
        opaque: false, pageBuilder: (context, _, __) => NewPage();

  }

Solution 3:[3]

flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
var initializationSettingsAndroid =
          const AndroidInitializationSettings('@drawable/icon_menu_car_no');
      var initializationSettingsIOs = const IOSInitializationSettings();
      var initSettings = InitializationSettings(
          android: initializationSettingsAndroid,
          iOS: initializationSettingsIOs);
      flutterLocalNotificationsPlugin?.initialize(initSettings,
          onSelectNotification: (payload) {
           switch(payload){
               case "A":
                 //route  to some where 
                break;

           }
      });

FirebaseMessaging.onMessage.listen((message) async {
       showNotification(message);
});
void showNotification(RemoteMessage message) {
    RemoteNotification? notification = message.notification;
    AndroidNotification? android = message.notification?.android;
    if (notification != null && android != null && !kIsWeb) {
      var messageData = FirebaseMessageObject.fromJson(message.data);
      flutterLocalNotificationsPlugin?.show(
          notification.hashCode,
          notification.title,
          notification.body,
          NotificationDetails(
            android: AndroidNotificationDetails(
              channel!.id,
              channel!.name,
              channelDescription: channel!.description,
              icon: 'icon_menu_car_no',
            ),
          ),
          payload: messageData.functionID);
    }
  }
class FirebaseMessageObject{
  late String functionID;

  static FirebaseMessageObject fromJson(Map<String,dynamic> data){
    FirebaseMessageObject object =  FirebaseMessageObject();
    object.functionID = data['functionID'];
    return object;
  }

}

?FCM Request

{
    "to": "your fcm token ",
    "notification": {
         "body": "I am body ",
         "title": "I am title ",
         "sound": "default"
    },
    "data":{
            "functionID":"A"
    },
    "priority": "high"
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Soham Sil
Solution 3 Kai