Show FCM notification thoughout the app when the app is open (Flutter)

1,497

Wrap your MaterialApp in a wrapper class ... lets call that FCMWrapper.

class FCMWrapper extends StatefulWidget {
  final Widget child;

  const FCMWrapper({Key key, this.child}) : super(key: key);

  @override
  _FCMWrapperState createState() => _FCMWrapperState();
}

class _FCMWrapperState extends State<FCMWrapper> {
  @override
  Widget build(BuildContext context) {
    return Consumer<YourObservable>(
      builder: (context, yourObservable, _) {
        if (yourObservable != null && yourObservable.isNotEmpty) {
          Future(
            () => navigatorKey.currentState.push(
              PushNotificationRoute(
                  child: YourViewOnNotification(),
              )),
            ),
          );
        }
        return widget.child;
      },
    );
  }
}

I have stored my data in an observable from a separate class. So when I receive a notification I update my observable. Since we are consuming on that observable the PushNotificationRoute would be called.

PushNotificationRoute is simply a class which extends ModalRoute.

class PushNotificationRoute extends ModalRoute {
  final Widget child;

  PushNotificationRoute({this.child});

  ... //Override other methods to your requirement

  //This is important
  @override
  Widget buildPage(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation) {
    return SafeArea(
      child: Builder(builder: (BuildContext context) {
        return child;
      }),
    );
  }

  ...
  @override
  Duration get transitionDuration => Duration(milliseconds: 200);
}

Now in main.dart declare a global key like

var navigatorKey = GlobalKey<NavigatorState>();

and wrap your MaterialApp like

...

FCMWrapper(
          child: MaterialApp(
            navigatorKey: navigatorKey,
            title: 'Your App',

...

So now every time a notification comes in your observable should update and push a modal route which would be shown over anywhere in the app.

Share:
1,497
That Guy
Author by

That Guy

Well versed in Flutter, NodeJs, ExpressJs and GraphQL.

Updated on December 23, 2022

Comments

  • That Guy
    That Guy over 1 year

    I'm using FCM to send push notifications to my device right now and it's working perfectly. However when the app is open, I only get the onResume to be executed when I'm in that particular page. I want to display the notification on the top regardless of which page(or class) the user is on. Basically I want the notifications to be displayed globally (Show popup). Any help would be appreciated. Here is the code from the page that displays the notifications.

    if (Platform.isIOS) {
         iosSubscription = _fcm.onIosSettingsRegistered.listen((data) {
        _saveDeviceToken();
       });
    
      _fcm.requestNotificationPermissions(IosNotificationSettings());
    } else {
      _saveDeviceToken();
    }
    
    _fcm.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("onMessage: $message");
        var temp = message['notification'];
        setState(() {
          title.add(temp['title']);
          body.add(temp['body']);
        });
       
        showDialog(
          context: context,
          builder: (context) => AlertDialog(
            content: ListTile(
              title: Text(message['notification']['title']),
              subtitle: Text(message['notification']['body']),
            ),
            actions: <Widget>[
              FlatButton(
                color: const Color(0xFF650572),
                child: Text('Ok'),
                onPressed: () => Navigator.of(context).pop(),
              ),
            ],
          ),
        );
      },
      onLaunch: (Map<String, dynamic> message) async {
        print("onLaunch: $message");
        Navigator.push(
            context, MaterialPageRoute(builder: (context) => MessageHandler()));
        // TODO optional
      },
      onResume: (Map<String, dynamic> message) async {
        print("onResume: $message");
        Navigator.push(context,
            MaterialPageRoute(builder: (context) => MessageHandler()));
        // TODO optional
      },
    );
    

    }

  • Roxx
    Roxx over 3 years
    Wow this is awesome. couple of things i want to know. Can you please tell me in which file you have added these codes or any sample code. I am also facing issue. I am not able to show the alert on message or on resume. Also facing issue while decoding the message.
  • That Guy
    That Guy over 3 years
    Honestly, this seemed like a hassle, I just ended up using the local_notifications package.
  • Roxx
    Roxx over 3 years
    @ThatGuy I am even struggling with local_notifications package. It is giving me hard time. You must have seen my question. it is still not working.