我正在构建一个带有 Firebase 推送通知的 Flutter 应用程序。
收到消息时,我希望应用程序显示带有文本的弹出模式。
当应用程序位于前台时,会显示弹出模式 - 这有效
当应用程序处于后台并且移动设备收到消息时,它会出现在系统托盘中,用户单击它,应用程序将打开,并找到初始消息并在弹出模式中显示给用户 - 例如。 FirebaseMessaging.onMessageOpenedApp 函数 - 这有效。
当应用程序在后台时,手机收到通知(并且firebase侦听器正在工作,因为它使用debugPrint输出消息数据来测试),它出现在系统托盘中,但用户选择不单击消息 - 当应用程序返回前台时,消息将被忽略 - 这是一个问题。
“FirebaseMessaging.onBackgroundMessage”函数需要放置在顶层(任何类之外)。因此,当应用程序再次置于前台时,如何将应用程序在后台时可能收到的消息中的消息数据推送到我的应用程序类中以显示消息内容?我正在使用“AppLifecycleState”来检测应用程序何时返回前台,但我无法获取消息数据,因为它是在顶层而不是在类中接收的。
请参阅下面的代码(请参阅最后几行以了解我所坚持的部分)...
//TOP LEVEL-----
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
if (message.messageId!="") {
debugPrint("Have received a background message! Will have to grab the message from here somehow if the user didn't interact with the system tray message link");
}
}
Future<void> main() async {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(MyApp());
}
//APP CLASS-----
class MyAppextends StatefulWidget {
State<MyApp> createState() => _MyAppState();
}
//APP STATE CLASS
class _MyAppState extends State<MyApp> with WidgetsBindingObserver{
@override
void initState() {
super.initState();
_initiateNotificationForegroundListener();
_initiateInteractedMessage();
}
// This variable will tell you whether the application is in foreground or not.
bool _isInForeground = true;
//Initiate Foreground Notification Listener (works)
void _initiateNotificationForegroundListener() {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
_handleNotificationInstruction(message);
});
}
//Initiate Background/Closed Notification Listener if user clicks the message in the system try (works)
Future<void> _initiateInteractedMessage() async {
RemoteMessage? message = await FirebaseMessaging.instance.getInitialMessage();
if (message != null) {
_handleNotificationInstruction(message);
}
// When app is in background (Stream listener)
FirebaseMessaging.onMessageOpenedApp
.listen(_handleNotificationInstruction);
}
void _handleNotificationInstruction(RemoteMessage message) {
//Create popup to display message info (works)
}
//Detect when an app moves in to the foreground
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
_isInForeground = state == AppLifecycleState.resumed;
if(_isInForeground){
/** HELP!!!
/* How can I check what message might have been received while app was in the background?? ie. the top-level _firebaseMessagingBackgroundHandler function??
**/
}
}
我也面临这个问题,这很烦人,但多亏了这个thread,我找到了解决方案。 FCM 的文件指出:
收到后,会生成一个隔离(仅限 Android,iOS/macOS 不支持) 需要一个单独的隔离)允许您即使在以下情况下也可以处理消息 您的应用程序未运行。
一个重要的注意事项是,每个隔离都有自己的内存,因此前台中的 SharedPreferences 将与后台中的不同。您可以在应用恢复时通过调用 SharedPreferences.reload() 来“同步”数据。
将消息保存到持久存储,并在应用程序启动时检查存储是否有待处理的消息。
我的应用程序也遇到了同样的问题。即使我的应用程序已经暂停并恢复,但远程消息仍然发送到 _firebaseMessagingBackgroundHandler。
我尝试使用 SharedPreference.reload() 并且它有效。但是它有延迟时间来安排计时器来检查 SharePreference 中是否有新的远程消息,并且我的应用程序需要在收到远程消息后立即响应,然后我找到一种将后台远程消息发送到前台的方法。
我使用 flutter_broadcasts (https://pub.dev/packages/flutter_broadcasts) 从 _firebaseMessagingBackgroundHandler 发送 sendBroadcast 消息并在前台监听。它运行完美。
希望能帮到你!