在颤动中从 FCM 回调导航到特定屏幕

Posted

技术标签:

【中文标题】在颤动中从 FCM 回调导航到特定屏幕【英文标题】:Navigating to particular screen from FCM callback in flutter 【发布时间】:2021-03-28 20:15:45 【问题描述】:

下面是我的推送通知管理器。我想在收到通知时导航到特定屏幕(当应用程序同时来自后台/前台时)。请让我知道我做错了什么?

提前致谢

class PushNotificationsManager 
PushNotificationsManager._();
factory PushNotificationsManager() => _instance;
static final PushNotificationsManager _instance =
PushNotificationsManager._();

final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
bool _initialized = false;

Future<void> init() async 
if (!_initialized) 
  // For ios request permission first.
  _firebaseMessaging.requestNotificationPermissions();
  _firebaseMessaging.configure();

  // For testing purposes print the Firebase Messaging token
  String token = await _firebaseMessaging.getToken();
  print("FirebaseMessaging token****: $token");

  _initialized = true;

  _firebaseMessaging.configure(
    onMessage: (Map<String, dynamic> message) async 
      print("onMessage: $message");
      print("FirebaseMessaging token: $token");
      print('hi');
      try 
        Navigator.pushAndRemoveUntil(
            navigatorKey.currentContext,
            MaterialPageRoute(
              builder: (context) => ChangeNotifierProvider(
                create: (context) => CategoryListViewModel(),
                child: CategoryListPage(),
              ),
            ),
            (Route<dynamic> route) => false);
       catch (e) 
        print("Exeeee:::" + e.toString());
      

      print("found");
    ,
    onLaunch: (Map<String, dynamic> message) async 
      print("onLaunch: $message");
    ,
    onResume: (Map<String, dynamic> message) async 
      print("onResume: $message");
    ,
  );

【问题讨论】:

您需要在 onlaunch 中写入点击次数。 @hasan 当我进一步检查时,我看到上下文为空。如何获取全局上下文。我在主 dart 文件中添加了全局键并使用仍然为空。 【参考方案1】:

flutter_local_notifications 3.0.2 库可用于在应用程序处于前台时添加通知。这提供了一个选项,可以在点击导航library link时导航到特定页面

添加一个全局键来保持状态,并在收到消息时使用它来获取当前上下文。

 final GlobalKey<NavigatorState> navigatorKey =
  new GlobalKey<NavigatorState>();

使用如下键。

child: MaterialApp(
    navigatorKey: navigatorKey,

在下面声明firebase的初始化

FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();

并在初始化状态下添加以下代码

@override
void initState() 
super.initState();

_firebaseMessaging.requestNotificationPermissions();
_firebaseMessaging.configure();

var initializationSettingsandroid =
    AndroidInitializationSettings('mipmap/ic_launcher');
var initializationSettingsIOs = IOSInitializationSettings();
var initSetttings = InitializationSettings(
    android: initializationSettingsAndroid, iOS: initializationSettingsIOs);

flutterLocalNotificationsPlugin.initialize(initSetttings,
    onSelectNotification: onSelectNotification);

// For testing purposes print the Firebase Messaging to

_firebaseMessaging.configure(
  onMessage: (Map<String, dynamic> message) async 
    print("onMessage@@@: $message");
    String token = await _firebaseMessaging.getToken();
    print("FirebaseMessaging token****: $token");
    try 
      showNotification();
     catch (e) 
      print("Exeeee:::" + e.toString());
    
  ,
  onLaunch: (Map<String, dynamic> message) async 
    PushNotificationsManager.navigationHandler(
        navigatorKey.currentContext, "Test");
  ,
  onResume: (Map<String, dynamic> message) async 
    PushNotificationsManager.navigationHandler(
        navigatorKey.currentContext, "Test");
  ,
);

其他两种方法用于在应用程序处于前台时,点击导航时显示通知

  Future onSelectNotification(String payload) 
try 
  PushNotificationsManager.navigationHandler(
      navigatorKey.currentContext, "Test");
 catch (e) 
  print("Navigation:::" + e.toString());



showNotification() async 
var android = AndroidNotificationDetails('id', 'channel ', 'description',
    priority: Priority.high, importance: Importance.max);
var ios = IOSNotificationDetails();
var platform = new NotificationDetails(android: android, iOS: ios);
try 
  await flutterLocalNotificationsPlugin.show(
      0, 'Flutter devs', 'Flutter Local Notification Demo', platform,
      payload: 'Welcome to the Local Notification demo');
 catch (e) 
  print("Platform Exee:::" + e.toString());


可以在 PushNotificationsManager.navigationHandler() 中编写自己的自定义导航代码。

【讨论】:

【参考方案2】:

你所做的是正确的,但只是一半。如果您希望它在应用程序打开/后台/关闭时工作,您还必须在所有其他条件下收到通知时进行处理。但是,为了导航,您需要上下文但没有它。您可以使用全局键执行此操作或阅读本指南here,以便在没有上下文的情况下轻松导航。

如下使用 get_it 包设置导航服务

locator.registerLazySingleton(() => NavigationService());

像这样在 PushNotification Manager 中获取服务实例

  final NavigationService _navigationService = locator<NavigationService>();

然后像这样使用它导航到您想要的屏幕

 _navigationService.navigateTo(CreatePostViewRoute);

Here 是他们的推送通知处理指南 超级简单,开箱即用

【讨论】:

请检查我的答案导航键是否在全球范围内使用。我正在从导航键获取当前上下文。 可能意味着当您尝试使用它进行导航时该键为空。你能显示你声明密钥的代码吗?

以上是关于在颤动中从 FCM 回调导航到特定屏幕的主要内容,如果未能解决你的问题,请参考以下文章

单击通知时导航到特定屏幕?

如何在颤动中从导航器堆栈中弹出最后三个路由

如何在颤动中从另一个屏幕进行更改

如何在颤动中从类(小部件外部)打开屏幕

如何在颤动的主页中导航屏幕?

如何在颤动中弹出到特定屏幕