Reputation: 234
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
},
);
}
Upvotes: 5
Views: 2244
Reputation: 147
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.
Upvotes: 2