【问题标题】:how to navigate when click background notification on Flutter?在 Flutter 上单击背景通知时如何导航?
【发布时间】:2020-06-20 16:11:41
【问题描述】:

点击背景 FCM通知时是否可以导航到指定路径?

我创建了一个 Top-Level 函数并将其添加到导航器路径,但它不起作用,当单击背景通知时,它只是打开应用程序

我猜我发现了一个问题

现在,我将fcm 配置从home page 更改为splash screen。 前景没有导航到页面,我认为这是因为启动画面不再可用。当我点击通知消息时,它只是打开了应用程序。

FCM 配置

onBackgroundMessage: backgroundMessageHandler

顶级函数

Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message) {
  if (message.containsKey('data')) {
    getIt<NavigationService>().navigateTo('/${message['data']['screen']}');
  }
}

有效载荷

const payload: admin.messaging.MessagingPayload = {
                notification:{
                    title: `New Enquiry`,
                    body:`${customerName} published to ${subName}`,
                    badge: '1',
                    sound: 'default'
                },
                data: {
                    click_action: `FLUTTER_NOTIFICATION_CLICK`,
                    sound: `default`,
                    status: `chat`,
                    screen: `homePage`
                  }
            }

ma​​in.dart

GetIt getIt = GetIt.instance;

void main() {
  setupLocator();
    runApp(MyApp());
}

MaterialApp

 return MaterialApp(
      navigatorKey: NavigationService().navigatorKey,
      onGenerateRoute: Router.generateRoute,
    );

NavigationService 和 setupLocator

class NavigationService {
  final GlobalKey<NavigatorState> navigatorKey =
      new GlobalKey<NavigatorState>();

  Future<dynamic> navigateTo(String routeName) {
    return navigatorKey.currentState.pushNamed(routeName);
  }
}

void setupLocator() {
  getIt.registerLazySingleton(() => NavigationService());
}

【问题讨论】:

  • 通知负载是否包含click_action 字段?
  • @HasilT 是的,我将有效负载添加到此处
  • 我也有同样的问题,还没找到解决办法
  • 您找到解决方案了吗?我也面临同样的问题。

标签: firebase flutter dart background firebase-cloud-messaging


【解决方案1】:

您可以使用此功能在应用被终止时导航并在后台接收通知

  FirebaseMessaging.instance
        .getInitialMessage()
        .then((RemoteMessage message) {
      print("FirebaseMessaging.getInitialMessage");
      if (message != null) {

        Navigator.of(context).pushNamed('/call');
      }
    });

此函数仅在应用打开并获取最后一条消息时运行一次。

您可以在此文档中阅读更多内容:https://github.com/FirebaseExtended/flutterfire/blob/62e09975f9b3d14141585e62ddab6b98e667b7cf/docs/messaging/notifications.mdx

【讨论】:

  • 我的问题是如何在 BACKGROUND MODE 下导航
  • getInitialMessage() 将在应用程序通过终止状态的通知打开时触发。它可用于通过在通知中传递数据来导航到某个页面
【解决方案2】:

要处理来自后台状态的通知,您可以使用 FirebaseMessaging 库公开的流。

FirebaseMessaging.onMessageOpenedApp.listen((remoteMessage) {
  // Handle navigation or perform any logic here
});

【讨论】:

  • OP 要求一种在背景模式下处理推送通知的方法,因此答案是正确的。您的答案使用一种方法来处理来自 TERMINATED 状态的推送通知,该方法有效,但这不是 OP 想要的。您应该更仔细地阅读问题和 cmets
【解决方案3】:

我希望你已经配置了 firebase_messaging 指定的 here 所需的本机端声明

根据您提供的有效负载:

有效载荷

const payload: admin.messaging.MessagingPayload = {
                notification:{
                    title: `New Enquiry`,
                    body:`${customerName} published to ${subName}`,
                    badge: '1',
                    sound: 'default'
                },
                data: {
                    click_action: `FLUTTER_NOTIFICATION_CLICK`,
                    sound: `default`,
                    status: `chat`,
                    screen: `homePage`
                  }
            }

让你的 onResume 像这样,onLaunch 也一样

onResume:

onResume: (Map<String, dynamic> message) {
  if(SharedClassID.toString().contains(message['data']['classID']))
  {
   
    Navigator.push(context, MaterialPageRoute(builder: (context)=>BroadcastNotification()));
    print("found");
  }
  else if(SharedClassID.toString().contains(message['data']['classID']))
  {
 
    Navigator.push(context, MaterialPageRoute(builder: (context)=>StudentHomework()));
    print("found");
  }

  else
    {
      print("not found");
    }


  //print(message['data']['classID']+" onResume");
  print('onResume: $message');
  return;
}

我可以找出它不起作用的原因,因为在有效负载中,键是 screen:'homePage' 并且我可以注意到您没有传递 classID所以发生的事情是它无法评估您添加的 if else 条件。

你更新 if/else 条件如下:

if(message['data']['screen'] == 'homePage')
  {
    //TODO: route
  
  }else if(message['data']['screen'] == 'homeWorkPage'){
    //TODO: route
  }

如果您想基于 SharedClassId 进行路由,则在有效负载和路由中传递 classId。 例如sn-p:

if(message['data']['classId'] == SharedClassId)
  {
    //TODO: route
  
  }else if(message['data']['classId'] == SharedClassId){
    //TODO: route
  }

【讨论】:

    【解决方案4】:

    在该示例中,我使用共享首选项数据(如类 ID)来检查通知数据是否包含此类 ID,然后它可以导航到特定屏幕

    void registerNotification() {
    _firebaseMessaging.requestNotificationPermissions(
      const IosNotificationSettings(sound: true, badge: true, alert: true),
    );
    
    _firebaseMessaging.configure(onMessage: (Map<String, dynamic> message) {
      print('onMessage: $message');
     // print(message['data']['classID']+" onMessage");
      if(SharedClassID.toString().contains(message['data']['classID']))
      {
       
        Navigator.push(context, MaterialPageRoute(builder: 
     (context)=>BroadcastNotification()));
        print("found");
      }
      
      else if(SharedClassID.toString().contains(message['data']['classID']) )
      {
       
        Navigator.push(context, MaterialPageRoute(builder: (context)=>MuseGalaryNew()));
        print("found");
      }
      else
      {
        print("not found");
      }
    
      return;
    }, onResume: (Map<String, dynamic> message) {
      if(SharedClassID.toString().contains(message['data']['classID']))
      {
       
        Navigator.push(context, MaterialPageRoute(builder: (context)=>BroadcastNotification()));
        print("found");
      }
      else if(SharedClassID.toString().contains(message['data']['classID']))
      {
     
        Navigator.push(context, MaterialPageRoute(builder: (context)=>StudentHomework()));
        print("found");
      }
    
      else
        {
          print("not found");
        }
    
    
      //print(message['data']['classID']+" onResume");
      print('onResume: $message');
      return;
    }, onLaunch: (Map<String, dynamic> message) {
      if(SharedClassID.toString().contains(message['data']['classID'])  )
      {
                Navigator.push(context, MaterialPageRoute(builder: (context)=>BroadcastNotification()));
        print("found");
      }
      else if(SharedClassID.toString().contains(message['data']['classID']))
      {
              Navigator.push(context, MaterialPageRoute(builder: (context)=>StudentHomework()));
        print("found");
      }
    
      else
      {
        print("not found");
      }
      return;
    });
    
    }
    

    【讨论】:

    • 不管你要打开哪个屏幕,只要知道应用程序完全关闭时如何通过导航器打开屏幕,谢谢
    • 您需要使用 _firebaseMessaging.subscribeToTopic("Your topic name") 订阅事件..在应用关闭时收到通知后,当您单击通知时它将重定向到该特定页面跨度>
    【解决方案5】:

    截至目前 2021 年 8 月的最新代码。 首先,您的项目 dart 版本和 firebase 插件版本是集成 firebase 通知的重要内容。如果您使用的是较低版本,那么您可能会遇到一些问题。对于我的颤振项目,我使用的是最新的 null 安全 Firebase 消息插件。如果您使用 Flutter 消息传递 10.0.4 或更高版本,则无需在 android manifest 文件中添加任何元数据。你可以看到complete code here。

      firebase_messaging: ^10.0.4
      firebase_core: ^1.4.0
      flutter_local_notifications: ^8.1.1
    

    如果 Flutter 应用程序关闭,则将调用以下代码。它只会被调用一次,您应该在 firebase 控制台云消息传递窗口中提供 click_action 作为“FLUTTER_NOTIFICATION_CLICK”作为自定义数据。

      // when app is closed and it will be called only once
    FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) {
     print("fireabse closed app msg");
    
      if (message != null) {
        print( " firebase msg received closed add "+message.data.toString());
        Navigator.push(context, MaterialPageRoute(builder: (context){ return product(prodid: message.data["prodid"]);}));
    
        /*  Navigator.pushNamed(context, '/message',
            arguments: MessageArguments(message, true));
      */
    
      }
    });
    

    要在状态栏上显示通知图标,请使用以下代码。

    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
          RemoteNotification? notification = message.notification;
          AndroidNotification? android = message.notification?.android;
          print(" firebase msg - "+message.data.length.toString());
          if (notification != null && android != null) {
            print("firebase msg body "+ notification.body.toString());
            flutterLocalNotificationsPlugin.show(
                notification.hashCode,
                notification.title,
                notification.body,
                NotificationDetails(
                  android: AndroidNotificationDetails(
                    channel.id,
                    channel.name,
                    channel.description,
                    // TODO add a proper drawable resource to android, for now using
                    //      one that already exists in example app.
                    icon: 'noti_icon',
                    color: Colors.red
    
                  ),
                ));
    
    
          }
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-31
      • 2021-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-25
      • 2020-05-01
      • 2023-02-07
      相关资源
      最近更新 更多