M.Ali
M.Ali

Reputation: 10235

Flutter: local notification plugin, navigate to specific screen when the user tap the notification

I`m using local notification plugin and everything works fine except that when i tap on the notification.i want to navigate to specific screen when the user tap the notification

Future onSelectNotification(String payload) async {
    //convert payload json to notification model object
    try{
    Map notificationModelMap = jsonDecode(payload);
    NotificationModel model = NotificationModel.fromJson(notificationModelMap);

    await Navigator.push(
        context,// it`s null!
        new MaterialPageRoute(
            builder: (context) => CommitmentPage(model)));}
            catch(e){print(e.toString());}
  }

but the context always null and gives me an exception NoSuchMethodError: The method 'ancestorStateOfType' was called on null.

Edit

i tried to use navigatorKey and pass it to material app as suggested by @Günter Zöchbauer but it gives me another exception

Navigator operation requested with a context that does not include a Navigator.
The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget

main.dart

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

static final navigatorKey = new GlobalKey<NavigatorState>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      navigatorKey:navigatorKey ,
      title: 'notification',
      theme: ThemeData(
        primarySwatch: Colors.purple,
      ),
      home: new RootPage(auth: new Auth(),),
    );
  }

}

ReminderPage

   class ReminderPage extends StatefulWidget {

    @override
      _ReminderPageState createState() => _ReminderPageState();

    }

class _ReminderPageState extends State<ReminderPage> {
  final flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
....

 @override
  void initState() {
    super.initState();

    _initLocalNotification();
....

  }


// this method is called when u tap on the notification
 Future onSelectNotification(String payload) async {

    //convert payload json to notification model object
    Map notificationModelMap = jsonDecode(payload);
    NotificationModel model = NotificationModel.fromJson(notificationModelMap);

    try{
   await Navigator.push(
        MyApp.navigatorKey.currentState.context,
        new MaterialPageRoute(
            builder: (context) => CommitmentPage(model)));}
            catch(e){print(e.toString());}


  }

}

Edit 2 instead of using

 await Navigator.push(
            MyApp.navigatorKey.currentState.context,
            new MaterialPageRoute(
                builder: (context) => CommitmentPage(model)));}
                catch(e){print(e.toString());}

i used

await  MyApp.navigatorKey.currentState.push(MaterialPageRoute(builder: (context) => CommitmentPage(model)));

and it worked fine, but when i tap on the notification after killing the app, it takes me to the home page not to the desired one! i think navigatorKey has not been initialized yet!

Upvotes: 19

Views: 21244

Answers (3)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657376

Pass a navigatorKey to MaterialApp and use this key to get the context. This context contains a Navigator and you can use it to switch to whatever page you want.

https://api.flutter.dev/flutter/material/MaterialApp/navigatorKey.html

Upvotes: 4

Nehemie KOFFI
Nehemie KOFFI

Reputation: 1395

1. FMC payload

{
  "notification": {
    "body": "Hey, someone book your product", 
    "title": "production booking"
  }, 
  "priority" : "high",
  "data": {
    "action" : "BOOKING" //to identify the action
  },
  "to": "deviceFCMId"
}

2. Set the payload data in localnotification.show method

showNotification(RemoteMessage message) {
  RemoteNotification notification = message.notification;
  AndroidNotification android = message.notification?.android;
  String action = message.data['action']; // get the value set in action key from FCM Json in Step1
  // local notification to show to users using the created channel.
  if (notification != null && android != null) {
    flutterLocalNotificationsPlugin.show(
        notification.hashCode,
        notification.title,
        notification.body,
        NotificationDetails(
            android: androidNotificationDetails, iOS: iOSNotificationDetails),
        payload: action // set the value of payload
    );
  }
}

3. Create a navigatorKey in MyApp class

class _MyAppState extends State<MyApp> {
  final GlobalKey<NavigatorState> navigatorKey =
      GlobalKey(debugLabel: "Main Navigator"); //
}

4. Set navigatorkey on your MaterialApp

@override
  Widget build(BuildContext context) {
    //this change the status bar color to white
    return MaterialApp(
          navigatorKey: navigatorKey,
    ....

5. on initState, init localnotificationPlugin and declare the onSelectNotification method

@override
  void initState() {
    super.initState();
    flutterLocalNotificationsPlugin.initialize(initializationSettings,
        onSelectNotification: onSelectNotification);
  }

  Future<dynamic> onSelectNotification(payload) async {
  // implement the navigation logic
  }

6. Navigation logic example

Future<dynamic> onSelectNotification(payload) async {
// navigate to booking screen if the payload equal BOOKING
if(payload == "BOOKING"){
 this.navigatorKey.currentState.pushAndRemoveUntil(
  MaterialPageRoute(builder: (context) => BookingScreen()),
   (Route<dynamic> route) => false,
   );
 }
}

Upvotes: 16

MaikuB
MaikuB

Reputation: 56

With the latest change you've done, you being taken to the home page, is more to do with the fact that you instantiate and initialise the plugin a couple of pages further in your app. considering the app got killed, the plugin would've been killed too. you should look into initialising the plugin closer to when your app starts e.g. around when the app is created or when the first page is created, depending on the behaviour you want. In this issue https://github.com/MaikuB/flutter_local_notifications/issues/99, another dev has been able to change the first page shown if the app is killed but that may different to what you want to happen.

Upvotes: 3

Related Questions