Flutter:本地通知插件,当用户点击通知时导航到特定屏幕
Flutter: local notification plugin, navigate to specific screen when the user tap the notification
我正在使用本地通知插件并且一切正常,除了当我点击 notification.i 想要在用户点击通知时导航到特定屏幕
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());}
}
但上下文总是空的,给我一个例外
NoSuchMethodError: The method 'ancestorStateOfType' was called on null
.
编辑
我尝试按照@Günter Zöchbauer 的建议使用 navigatorKey 并将其传递给 material 应用程序,但它给了我另一个例外
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(),),
);
}
}
提醒页面
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());}
}
}
编辑 2
而不是使用
await Navigator.push(
MyApp.navigatorKey.currentState.context,
new MaterialPageRoute(
builder: (context) => CommitmentPage(model)));}
catch(e){print(e.toString());}
我用过
await MyApp.navigatorKey.currentState.push(MaterialPageRoute(builder: (context) => CommitmentPage(model)));
它运行良好,但是当我在关闭应用程序后点击通知时,它会将我带到主页而不是所需的页面!
我认为 navigatorKey 还没有初始化!
将 navigatorKey
传递给 MaterialApp
并使用此键获取上下文。此上下文包含一个 Navigator
,您可以使用它切换到您想要的任何页面。
https://docs.flutter.io/flutter/material/MaterialApp/navigatorKey.html
根据您所做的最新更改,您被带到主页,这更多是因为您在应用程序中进一步实例化和初始化了几个页面的插件。考虑到应用程序被杀死,插件也会被杀死。您应该考虑在您的应用程序启动时更接近初始化插件,例如大约在创建应用程序或创建第一页时,具体取决于您想要的行为。在这个问题 https://github.com/MaikuB/flutter_local_notifications/issues/99 中,另一位开发人员已经能够更改应用程序被终止时显示的第一页,但这可能与您希望发生的情况不同。
1. FMC 有效载荷
{
"notification": {
"body": "Hey, someone book your product",
"title": "production booking"
},
"priority" : "high",
"data": {
"action" : "BOOKING" //to identify the action
},
"to": "deviceFCMId"
}
2。在localnotification.show方法
中设置负载数据
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。在 MyApp class
中创建一个 navigatorKey
class _MyAppState extends State<MyApp> {
final GlobalKey<NavigatorState> navigatorKey =
GlobalKey(debugLabel: "Main Navigator"); //
}
4.在您的 MaterialApp
上设置 navigatorkey
@override
Widget build(BuildContext context) {
//this change the status bar color to white
return MaterialApp(
navigatorKey: navigatorKey,
....
5.在 initState 上,初始化 localnotificationPlugin 并声明 onSelectNotification 方法
@override
void initState() {
super.initState();
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
}
Future<dynamic> onSelectNotification(payload) async {
// implement the navigation logic
}
6.导航逻辑示例
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,
);
}
}
我正在使用本地通知插件并且一切正常,除了当我点击 notification.i 想要在用户点击通知时导航到特定屏幕
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());}
}
但上下文总是空的,给我一个例外
NoSuchMethodError: The method 'ancestorStateOfType' was called on null
.
编辑
我尝试按照@Günter Zöchbauer 的建议使用 navigatorKey 并将其传递给 material 应用程序,但它给了我另一个例外
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(),),
);
}
}
提醒页面
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());}
}
}
编辑 2 而不是使用
await Navigator.push(
MyApp.navigatorKey.currentState.context,
new MaterialPageRoute(
builder: (context) => CommitmentPage(model)));}
catch(e){print(e.toString());}
我用过
await MyApp.navigatorKey.currentState.push(MaterialPageRoute(builder: (context) => CommitmentPage(model)));
它运行良好,但是当我在关闭应用程序后点击通知时,它会将我带到主页而不是所需的页面! 我认为 navigatorKey 还没有初始化!
将 navigatorKey
传递给 MaterialApp
并使用此键获取上下文。此上下文包含一个 Navigator
,您可以使用它切换到您想要的任何页面。
https://docs.flutter.io/flutter/material/MaterialApp/navigatorKey.html
根据您所做的最新更改,您被带到主页,这更多是因为您在应用程序中进一步实例化和初始化了几个页面的插件。考虑到应用程序被杀死,插件也会被杀死。您应该考虑在您的应用程序启动时更接近初始化插件,例如大约在创建应用程序或创建第一页时,具体取决于您想要的行为。在这个问题 https://github.com/MaikuB/flutter_local_notifications/issues/99 中,另一位开发人员已经能够更改应用程序被终止时显示的第一页,但这可能与您希望发生的情况不同。
1. FMC 有效载荷
{
"notification": {
"body": "Hey, someone book your product",
"title": "production booking"
},
"priority" : "high",
"data": {
"action" : "BOOKING" //to identify the action
},
"to": "deviceFCMId"
}
2。在localnotification.show方法
中设置负载数据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。在 MyApp class
中创建一个 navigatorKeyclass _MyAppState extends State<MyApp> {
final GlobalKey<NavigatorState> navigatorKey =
GlobalKey(debugLabel: "Main Navigator"); //
}
4.在您的 MaterialApp
上设置 navigatorkey@override
Widget build(BuildContext context) {
//this change the status bar color to white
return MaterialApp(
navigatorKey: navigatorKey,
....
5.在 initState 上,初始化 localnotificationPlugin 并声明 onSelectNotification 方法
@override
void initState() {
super.initState();
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
}
Future<dynamic> onSelectNotification(payload) async {
// implement the navigation logic
}
6.导航逻辑示例
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,
);
}
}