应用程序终止时未获取有效负载数据,Flutter FCM 和 LPN

Gra*_*gus 8 firebase flutter firebase-cloud-messaging flutter-notification flutter-local-notification

我正在通过FCM和LocalPushNotifications设置推送通知,我能够在应用程序的前台状态和后台设置它。在应用程序的终止状态下,我确实收到了通知,但是当我按下它时,即使应用程序的前台和后台状态工作正常并将用户导航到终止状态下的通知屏幕,也不会发生任何操作,应用程序只是打开,并且不会导航到通知屏幕,仅打开应用程序的主屏幕。由于设备未连接,我看不到控制台日志中的错误,但是当我从模拟器启动应用程序时,这就是我启动时得到的内容:

I/flutter ( 3829): Got a message whilst in the terminated state!
I/flutter ( 3829): Message data: null
Run Code Online (Sandbox Code Playgroud)

这在pushNotifications()方法内部调用FirebaseMessaging.instance.getInitialMessage().then()...

这是里面带有注释的代码:

处理推送通知的逻辑:

Future<void> pushNotifications() async {
  await Firebase.initializeApp();
  RemoteMessage initialMessage =
      await FirebaseMessaging.instance.getInitialMessage();

  if (initialMessage != null) {
    _handleMessage(initialMessage);
  }
/// THIS IS NOT WORKING, IT OPENS THE APP BUT DOESN'T NAVIGATE TO THE DESIRED SCREEN
  ///gives you the message on which user taps
  ///and it opened the app from terminated state
  FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage message) {
    LocalNotificationService.display(message);
    print('Got a message whilst in the terminated state!');
    print('Message data: ${message.data}');
    if (message != null) {  
      print('terminated state');
    }
  });

  ///forground work
  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    LocalNotificationService.display(message);
    print('Got a message whilst in the foreground!');
    print('Message data: ${message.data}');
  });


///EVEN THOUGH IT IS SUPPOSED TO WORK LIKE THIS, I ONLY MANAGED TO MAKE IT WORK WITH BACKGROUND HANDLER, THIS METHOD NEVER TRIGGERS
  ///When the app is in background but opened and user taps
  ///on the notification
  FirebaseMessaging.onMessageOpenedApp.listen((message) {
    print('Got a message whilst in the background!');
    print('Message data: ${message.data}');
    _handleMessage(message);
    LocalNotificationService.display(message);
  });
}


///THIS HANDLES THE NOTIFICATIONS WHEN THE APP IS IN THE BACKGROUND
Future<void> _handleMessage(RemoteMessage message) async {
  await Firebase.initializeApp();
  if (message.data != null) {
    print('message handler');
    LocalNotificationService.display(message);/// ALL OF THESE CALLED FROM THE LocalNotificationService CLASS BELOW
  }
}
///MAIN METHOD, WHERE I INITIALIZE FIREBASE AND THE METHODES ABOVE(pushNotifications()), HANDLE THE MESSAGES WITH onBackgroundMessage(_handleMessage),
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  pushNotifications();
  var initializationSettingsAndroid =
      AndroidInitializationSettings("@mipmap/ic_launcher");
  var initializationSettingsIOS = IOSInitializationSettings(
      requestAlertPermission: true,
      requestBadgePermission: true,
      requestSoundPermission: true,
      );
  await Firebase.initializeApp();
  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: true,
    sound: true,
  );
  FirebaseMessaging.onBackgroundMessage(_handleMessage);
  runApp(MyApp());
}

Run Code Online (Sandbox Code Playgroud)

我的本地通知服务类:

class LocalNotificationService {
  static final FlutterLocalNotificationsPlugin _notificationsPlugin =
      FlutterLocalNotificationsPlugin();

  static void initialize(BuildContext context) {
    final InitializationSettings initializationSettings =
        InitializationSettings(
            android: AndroidInitializationSettings("@mipmap/ic_launcher"));
    _notificationsPlugin.initialize(initializationSettings,
        onSelectNotification: (String payloadData) async {
     
      if (payloadData!= null) {
        
          Navigator.pushNamed(context, NotificationsScreen.id);
      }
    });
  }

  static void display(RemoteMessage message) async {
    try {
      final id = DateTime.now().millisecondsSinceEpoch ~/ 1000;

      final NotificationDetails notificationDetails = NotificationDetails(
          android: AndroidNotificationDetails(
        "push notifications",
        "push notifications",
        "push notifications",
        importance: Importance.max,
        priority: Priority.high,
      ));

      await _notificationsPlugin.show(
        id,
        'push notifications',
        'You have received a new push notification!',
        notificationDetails,
        payload: message.data['default'], // THIS IS NULL WHEN IN TERMINATED STATE OF APP
      );

    } on Exception catch (e) {
      print('exception: ' + e.toString());
    }
  }
}

Run Code Online (Sandbox Code Playgroud)

正如我所说,前台和后台状态都在工作并且对应于正确的屏幕,但终止的应用程序状态根本不对应,但它确实显示通知并在点击应用程序时打开应用程序。

我错过了什么吗?我主要是按照文档和自己的一些东西进行操作,但它仍然无法按预期工作。

感谢任何形式的帮助,提前致谢!

Mar*_*ark 5

我一直没能完全解决你所描述的问题,这非常令人沮丧。

这是我到目前为止所想到的,我将把它放在这里,因为它可能会对您有所帮助:

有 3 种类型的消息:data、notification和mixed。

如果您使用纯数据负载

  • 该消息基本上是无声的。
  • onMessage当应用程序处于前台时确实响应数据通知
  • onMessageOpenedApp在任何场景下都不会触发数据消息
  • onBackgroundMessage用于在终止状态或后台状态下使用本地通知显示消息
  • 由您(使用本地通知包)来处理他们的点击,使用onSelectNotification
    await flutterLocalNotificationsPlugin.initialize(initializationSettings,
        onSelectNotification: selectNotification
    );
Run Code Online (Sandbox Code Playgroud)
  • 你不能onSelectNotification在所有这些场景中使用(据我所知***这对我来说是一个绊脚石)

如果您使用纯通知或混合有效负载

  • 当应用程序处于后台(但不是前台)时,FCM 包将为您显示通知

  • onMessage当应用程序前台时响应数据

  • onMessageOpenedApp在后台状态下单击通知时将触发(但不适用于终止状态)

  • onBackgroundMessage将触发,但与上面不同的是,您不应该使用它来显示通知,因为这将强制发出双重通知(一个由 FCM 包处理,另一个由您手动完成)

  • 当应用程序处于后台时,点击由程序包处理,但当应用程序处于前台时,则由您处理。*** 可能也终止了,但还不确定。

正如我所提到的,我已经列出了迄今为止我所了解的一些事实。这非常棘手且令人沮丧。极大地减慢了我的速度是,当使用混合有效负载(我一直在使用的)时,虽然终止通知要么根本不来,要么按照自己的节奏来(发送后几个小时)。

如果您在这个问题上取得进展,请告诉我,我认为我们处于同一条船上......