访问 BuildContext 以从推送通知服务进行导航 (Flutter)
我正在努力了解如何在颤动中选择通知时从推送通知类进行导航。我需要访问 BuildContext 或以某种方式找到一种方法来告诉我的应用程序在没有它的情况下进行导航。
我的代码如下所示:
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await PushNotificationService().setupInteractedMessage();
runApp(const MyApp());
}
Future awaitDeepLink() async {
StreamSubscription _sub;
try {
await getInitialLink();
_sub = uriLinkStream.listen((Uri uri) {
runApp(MyApp(uri: uri));
}, onError: (err) {
});
} on PlatformException {
print("PlatformException");
} on Exception {
print('Exception thrown');
}
}
class MyApp extends StatelessWidget {
final Uri uri;
static final FirebaseAnalytics analytics = FirebaseAnalytics.instance;
const MyApp({Key key, this.uri}) : super(key: key);
@override
Widget build(BuildContext context) {
return OverlaySupport(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus &&
currentFocus.focusedChild != null) {
FocusManager.instance.primaryFocus.unfocus();
}
},
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: buildThemeData(),
home: CheckAuth(uri: uri),
),
),
);
}
}
PushNotificationService.dart
class PushNotificationService {
Future<void> setupInteractedMessage() async {
RemoteMessage initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
String token = await FirebaseMessaging.instance.getToken();
var storage = const FlutterSecureStorage();
storage.write(key: "fcm_token", value: token);
if (initialMessage != null) {
print(initialMessage.data['type']);
}
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print("message opened app:" + message.toString());
});
await enableIOSNotifications();
await registerNotificationListeners();
}
registerNotificationListeners() async {
AndroidNotificationChannel channel = androidNotificationChannel();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
var androidSettings =
const AndroidInitializationSettings('@mipmap/ic_launcher');
var iOSSettings = const IOSInitializationSettings(
requestSoundPermission: false,
requestBadgePermission: false,
requestAlertPermission: false,
);
var initSettings = InitializationSettings(
android: androidSettings,
iOS: iOSSettings,
);
flutterLocalNotificationsPlugin.initialize(
initSettings,
onSelectNotification: onSelectNotification,
);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification.android;
if (notification != null && android != null) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
icon: android.smallIcon,
playSound: true,
),
),
payload: json.encode(message.data),
);
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
print("onMessageOpenedApp: $message");
if (message.data != null) {
print(message.data);
}
});
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
}
Future onSelectNotification(String payload) async {
Map data = json.decode(payload);
if (data['type'] == 'message') {
// NEED TO ACCESS CONTEXT HERE
// Navigator.push(
// navigatorKey.currentState.context,
// CupertinoPageRoute(
// builder: (navigatorKey.currentState.context) => MessagesScreen(
// conversationId: data['conversation_id'],
// userId: data['user_id'],
// name: data['name'],
// avatar: data['avatar'],
// projectName: data['project_name'],
// projectId: data['project_id'],
// plus: data['plus'],
// ),
// ),
// );
}
}
Future<void> _firebaseMessagingBackgroundHandler(
RemoteMessage message) async {
print("onBackgroundMessage: $message");
}
enableIOSNotifications() async {
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
androidNotificationChannel() => const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
importance: Importance.max,
);
}
正如您在 onSelectNotification() 函数中看到的,我正在尝试导航,但不知道如何进行。
我对 dart/flutter 很陌生,所以任何指导将不胜感激。
I am struggling to understand how to navigate from a Push Notification class on selecting a notification in flutter. I need access to the BuildContext or somehow figure out a way to tell my app to navigate without this.
My code looks like below:
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await PushNotificationService().setupInteractedMessage();
runApp(const MyApp());
}
Future awaitDeepLink() async {
StreamSubscription _sub;
try {
await getInitialLink();
_sub = uriLinkStream.listen((Uri uri) {
runApp(MyApp(uri: uri));
}, onError: (err) {
});
} on PlatformException {
print("PlatformException");
} on Exception {
print('Exception thrown');
}
}
class MyApp extends StatelessWidget {
final Uri uri;
static final FirebaseAnalytics analytics = FirebaseAnalytics.instance;
const MyApp({Key key, this.uri}) : super(key: key);
@override
Widget build(BuildContext context) {
return OverlaySupport(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus &&
currentFocus.focusedChild != null) {
FocusManager.instance.primaryFocus.unfocus();
}
},
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: buildThemeData(),
home: CheckAuth(uri: uri),
),
),
);
}
}
PushNotificationService.dart
class PushNotificationService {
Future<void> setupInteractedMessage() async {
RemoteMessage initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
String token = await FirebaseMessaging.instance.getToken();
var storage = const FlutterSecureStorage();
storage.write(key: "fcm_token", value: token);
if (initialMessage != null) {
print(initialMessage.data['type']);
}
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print("message opened app:" + message.toString());
});
await enableIOSNotifications();
await registerNotificationListeners();
}
registerNotificationListeners() async {
AndroidNotificationChannel channel = androidNotificationChannel();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
var androidSettings =
const AndroidInitializationSettings('@mipmap/ic_launcher');
var iOSSettings = const IOSInitializationSettings(
requestSoundPermission: false,
requestBadgePermission: false,
requestAlertPermission: false,
);
var initSettings = InitializationSettings(
android: androidSettings,
iOS: iOSSettings,
);
flutterLocalNotificationsPlugin.initialize(
initSettings,
onSelectNotification: onSelectNotification,
);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification.android;
if (notification != null && android != null) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
icon: android.smallIcon,
playSound: true,
),
),
payload: json.encode(message.data),
);
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
print("onMessageOpenedApp: $message");
if (message.data != null) {
print(message.data);
}
});
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
}
Future onSelectNotification(String payload) async {
Map data = json.decode(payload);
if (data['type'] == 'message') {
// NEED TO ACCESS CONTEXT HERE
// Navigator.push(
// navigatorKey.currentState.context,
// CupertinoPageRoute(
// builder: (navigatorKey.currentState.context) => MessagesScreen(
// conversationId: data['conversation_id'],
// userId: data['user_id'],
// name: data['name'],
// avatar: data['avatar'],
// projectName: data['project_name'],
// projectId: data['project_id'],
// plus: data['plus'],
// ),
// ),
// );
}
}
Future<void> _firebaseMessagingBackgroundHandler(
RemoteMessage message) async {
print("onBackgroundMessage: $message");
}
enableIOSNotifications() async {
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
androidNotificationChannel() => const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
importance: Importance.max,
);
}
As you can see in the onSelectNotification() function I am trying to navigate but do not know how.
I am quite new to dart/flutter so any guidance would be appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以为导航设置全局键:
将其传递给 MaterialApp:
推送路线:
You can set a global key for your navigation:
Pass it to MaterialApp:
Push routes:
是的,您需要
context
进行导航。在 flutter 中,最佳实践是在小部件中包含导航代码。并且您的上下文来自 Andrea Bizzotto 的 推文主题
如果您尝试将导航代码放入业务逻辑中,您将遇到困难,因为您需要一个 BuildContext 来执行此操作。
解决方案:
Yes you need
context
to navigate. In flutter its best practice to have navigation code in the widgets. and you have your contextFrom a tweet thread by Andrea Bizzotto
If you try to put your navigation code in the business logic, you'll have a hard time because you need a BuildContext to do so.
Solution:
创建一个流
,然后在此处使用它
,然后您可以在主页上的 MaterialApp 小部件下收听该流
create a stream
then use it here
and then you can listen to the stream on the home page under your MaterialApp widget
自动路线解决方案
对于使用 auto_route 包进行导航的任何人,以下是在没有上下文的情况下进行导航的步骤。
1 - 将您的 AppRouter 添加到 get_it
要在应用程序中的任何位置访问您的 AppRouter,您可以使用服务定位器注册它,例如 get_it :
2 - 在 GetIt 中访问 AppRouter
Auto Route Solution
For anyone using the auto_route package for navigation, here are the steps for navigating without context.
1 - Add your AppRouter to get_it
To access your AppRouter anywhere in your app, you can register it with a service locator like get_it:
2 - Access the AppRouter in GetIt