I want to navigate to a specific page via beamer from a notification click.
In my main.dart I initialze my app and fcm. The class 'PushNotificationReceiver' should handle the notification logic.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await PushNotificationReceiver.instance.initialize();
runApp(MultiProvider(providers: [
// Some of my providers
], builder: (context, _) => MyApp()));
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
PushNotificationReceiver.instance.registerNotifications((route) => {
context.beamToNamed(route)
});
}
@override
Widget build(BuildContext context) {
return Consumer<ThemeProvider>(builder: (context, themeProvider, child) {
return MaterialApp.router(
routeInformationParser: BeamerParser(),
routerDelegate: _beamerDelegate,
backButtonDispatcher: BeamerBackButtonDispatcher(delegate: _beamerDelegate),
);
}
}
}
I implemented the functions to receive and show local notifications but to simplify it I only paste the code for the click (removed null checks as well).
class PushNotificationReceiver {
static PushNotificationReceiver _instance;
void Function(String route) navigateFunction;
static PushNotificationReceiver get instance {
if (_instance == null) {
_instance = new PushNotificationReceiver();
}
return _instance;
}
Future<void> initialize() async {
await Firebase.initializeApp();
}
void registerNotifications(void Function(String route) navigateFunction) {
this.navigateFunction = navigateFunction;
// Called the other functions to receive notifications, but excluded them for simplicity.
FirebaseMessaging.onMessageOpenedApp.listen((message) {
this.navigateFunction("/MyPage/${message.data["id"]}");
});
}
}
When I click on the notification I get the following error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: 'package:beamer/src/beamer.dart': Failed assertion: line 40 pos 14: 'BeamerProvider.of(context) != null': There was no Router nor BeamerProvider in current context. If using MaterialApp.builder, wrap the MaterialApp.router in BeamerProvider to which you pass the same routerDelegate as to MaterialApp.router.
I tried it first without a function that I pass in and a GlobalKey in the main.dart with the same result. Any suggestions?
Found the solution. My first approach of a global key works if I wrap my MaterialApp.router in a Beamerprovider (like the error message suggested).
final GlobalKey myGlobalKey = GlobalKey();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await PushNotificationReceiver.instance.initialize();
runApp(MultiProvider(providers: [
// Some of my providers
], builder: (context, _) => MyApp()));
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
PushNotificationReceiver.instance.registerNotifications();
}
@override
Widget build(BuildContext context) {
return Consumer<ThemeProvider>(builder: (context, themeProvider, child) {
return BeamerProvider(
key: myGlobalKey,
routerDelegate: _beamerDelegate,
child: MaterialApp.router(
routeInformationParser: BeamerParser(),
routerDelegate: _beamerDelegate,
backButtonDispatcher: BeamerBackButtonDispatcher(
delegate: _beamerDelegate
)
)
);
}
}
}
That leads to my push notification receiver:
class PushNotificationReceiver {
static PushNotificationReceiver _instance;
static PushNotificationReceiver get instance {
if (_instance == null) {
_instance = new PushNotificationReceiver();
}
return _instance;
}
Future<void> initialize() async {
await Firebase.initializeApp();
}
void registerNotifications(void Function() {
// Called the other functions to receive notifications, but excluded them for simplicity.
FirebaseMessaging.onMessageOpenedApp.listen((message) {
myGlobalKey.currentContext.beamToNamed("/MyPage/${message.data["id"]}");
});
}
}
I hope this will help some others too.