在 Flutter 上单击背景通知时如何导航?
Posted
技术标签:
【中文标题】在 Flutter 上单击背景通知时如何导航?【英文标题】:how to navigate when click background notification on 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`
main.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 是的,我将有效负载添加到此处
我也有同样的问题,还没找到解决办法
您找到解决方案了吗?我也面临同样的问题。
【参考方案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
),
));
);
【讨论】:
以上是关于在 Flutter 上单击背景通知时如何导航?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Flutter 中的通知导航到应用程序中的特定 MaterialPageRoute
Flutter MaterialPageRoute 导航到黑色背景的屏幕时如何解决?
Flutter - 从 FCM 收到通知时自动运行应用程序(无需单击它)