颤动 - 当用户在特定页面时不显示通知

我的应用程序有聊天功能。我已经实现了 Firebase 云消息传递和本地通知。

因此,当有人向我发送消息时,会显示通知(一个在 android 状态栏内)和本地通知(一个在屏幕上部,持续 3 秒)。它们会在应用程序打开、后台以及应用程序终止时显示。 (到目前为止,一切都很好)

但是当我已经在与该人的聊天页面中时,我不希望两个通知(1. fcm 通知,2. 本地通知)都显示。我不知道从哪里开始。

下面是我处理 fcm 并显示本地通知的代码。它们在 main.dart 中,主函数在返回我的根页面之前调用 initializeFCM。

Future<void> initializeFCM() async {
  await Firebase.initializeApp();

  FirebaseMessaging messaging = FirebaseMessaging.instance;

  // Firebase Messaging
  NotificationSettings settings = await messaging.requestPermission(
    alert: true,
    announcement: false,
    badge: true,
    carPlay: false,
    criticalAlert: false,
    provisional: false,
    sound: true,
  );

  if (settings.authorizationStatus == AuthorizationStatus.authorized) {
    // print('User granted permission');
  } else
  if (settings.authorizationStatus == AuthorizationStatus.provisional) {
    // print('User granted provisional permission');
  } else {
    // print('User declined or has not accepted permission');
  }

  // Get any messages which caused the application to open from
  // a terminated state.
  RemoteMessage? initialMessage = await messaging.getInitialMessage();

  if (initialMessage != null) {
    handleMessage(initialMessage);
  }

  // initialize local notification
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

  // terminated app을 local notification 눌러서 열었을 때 - payload가 정상적으로 동작하지 않음
  final NotificationAppLaunchDetails? notificationAppLaunchDetails = await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
  final didNotificationLaunchApp = notificationAppLaunchDetails?.didNotificationLaunchApp ?? false;
  if (didNotificationLaunchApp) {
    onSelectNotification(notificationAppLaunchDetails!.payload);
  }

  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    showLocalNotification(message);
  });

  FirebaseMessaging.onBackgroundMessage(showLocalNotification);

  FirebaseMessaging.onMessageOpenedApp.listen(handleMessage);
}

void handleMessage(RemoteMessage message) {
  if (message.data["screen"] == "message") {
    Navigator.push(
        navigatorKey.currentContext!,
        MaterialPageRoute(
          builder: (context) => MessageListPage(),
        )
    );
  }
}

Future<void> onSelectNotification(payload) async {
  if(payload != null) {
    Map<String, dynamic> data = json.decode(payload);

    if (data['screen'] == "message") {
      Navigator.push(
          navigatorKey.currentContext!,
          MaterialPageRoute(
            builder: (context) => MessageListPage(),
          )
      );
    }
  }
}

Future<void> showLocalNotification(RemoteMessage message) async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  RemoteNotification? notification = message.notification;
  AndroidNotification? android = message.notification?.android;
  // String screen = message.data['screen'];

  // iOS heads up notification setting
  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true, // Required to display a heads up notification
    badge: true,
    sound: true,
  );

  // android channel setting
  const AndroidNotificationChannel channel = AndroidNotificationChannel(
    'high_importance_channel', // id
    'High Importance Notifications', // title
    importance: Importance.max,
  );

  // initialize local notification
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

  await flutterLocalNotificationsPlugin.initialize(InitializationSettings(
      android: AndroidInitializationSettings('@drawable/mentea_ic_stat_name'),
      iOS: IOSInitializationSettings()),
      onSelectNotification: onSelectNotification);

  await flutterLocalNotificationsPlugin
      .resolvePlatformSpecificImplementation<
      AndroidFlutterLocalNotificationsPlugin>()
      ?.createNotificationChannel(channel);

  // If `onMessage` is triggered with a notification, construct our own
  // local notification to show to users using the created channel.
  if (notification != null && android != null) {
    // print('Message also contained a notification: ${message.notification}');
    flutterLocalNotificationsPlugin.show(
      notification.hashCode,
      notification.title,
      notification.body,
      NotificationDetails(
        android: AndroidNotificationDetails(
          'high_importance_channel', //channel.id,
          'High Importance Notifications', //channel.name,
          icon: android.smallIcon,
          color: primaryColor,
          // other properties...
        ),
      ),
      payload: json.encode(message.data)
    );
  }
}
stack overflow flutter - don't show notification when user is on certain page
原文答案

答案:

作者头像

我不知道你是否还有这个问题,但我会在这里发布我的解决方案。

碰巧当我们发送带有通知消息功能的推送通知时,如果App处于后台并完成,FCM插件会自动在设备上发送通知,我们只能通过Local Notifications或其他解决方案自定义前台通知应用程序。因此Firebase文档中针对这种情况指出的解决方案是仅将推送通知作为数据消息发送,不包括通知对象。下面我展示了示例和文档链接。

文档: https://firebase.google.com/docs/cloud-messaging/concept-options?authuser=1&hl=pt#notifications_and_data_messages

组合通知示例:

const payload = {
  notification: {
    title: '$FooCorp up 1.43% on the day',
    body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
  },
  data: {
    stock: 'GOOG',
    open: '829.62',
    close: '635.67'
  }
};

仅带有数据消息的通知示例:

const payload = {
  data: {
    score: '850',
    time: '2:45'
  }
};

仅带有通知消息的通知示例:

const payload = {
  notification: {
    title: '$FooCorp up 1.43% on the day',
    body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
  }
};

因此,您可以自定义所有形式的通知(前台、后台和终止),仅将推送通知作为数据消息通过您的后端发送。