不显示一个屏幕的通知 React Native

Do not show notification for one screen React Native

我编写了一个聊天应用程序,我想阻止在某些屏幕上显示推送通知,例如当 2 个用户在同一个房间聊天时,通知不会显示给这 2 个用户,但当有人离开时聊天屏幕离开的用户会收到推送通知,但留在聊天屏幕中的用户不会收到通知。我是 React Native 和 Expo Notification 服务的新手,我不知道该怎么做?

注意:我可以检测到我在哪个屏幕上。但我不知道如何隐藏(例如,我们可以认为 2 个用户 A 和 B,以及 2 个聊天室 X 和 Y 如果用户 A 和用户 B 在房间 X 中相互交谈,那么这两个用户不应该收到推送通知,但是当 A 离开房间而 B 仍在 X 房间时,只有用户 A 应该收到推送通知,而用户 B 不会收到通知)收到的特定屏幕的推送通知。

用于尝试的代码工作正常但抛出很多相同的通知并且直到应用程序崩溃才停止:

  const notificationListener = useRef();
  useEffect(() => {
    notificationListener.current = Notifications.addNotificationReceivedListener(
      (notification) => {
        // This is how you can get the data from the received notification
        const {
          room_id,
          message_text,
          type,
        } = notification.request.content.data;

        // If we receive a push notification which is not a new message,
        // we don't want to display a foreground push notification
        // if (type !== "NEW_MESSAGE") {
     
        //   return;
        // }
        if (room_id === 123) {
          console.log("trial");
          return;
        }

        Notifications.scheduleNotificationAsync({
          trigger: null,
          content: {
            title: "A new message",
            body: message_text,
          },
        });
      }
    );

    return () => {
      // Unsubscribe when component unmmounts
      Notifications.removeNotificationSubscription(
        notificationListener.current
      );
    };
  }, []);

根据 Expo push notification docsNotifications.addNotificationReceivedListener 侦听器可用于您的情况。您可以在聊天室屏幕内订阅此侦听器,并在组件卸载时取消订阅。此外,如果收到的通知针对的是用户当前所在的聊天室屏幕,您还可以检查订阅内部。这是一个例子:

我假设您收到了一个推送通知,其中有效负载中包含以下数据:

{
  room_id: 1,
  type: "NEW_MESSAGE"
}

您的聊天室屏幕可能如下所示:

import * as Notifications from 'expo-notifications';

const ChatRoomScreen = ({ roomId }) => {
  useEffect(() => {
    // This listener is fired whenever a notification is received while the app is foregrounded
    notificationListener.current = Notifications.addNotificationReceivedListener((notification) => {
      // This is how you can get the data from the received notification
      const { room_id, message_text, type } = notification?.request?.content?.data ?? {};

      // If we receive a push notification which is not a new message,
      // we don't want to display a foreground push notification
      if (type !== 'NEW_MESSAGE') {
        return;
      }

      // If the user is currently on this screen and the
      // room_id from the push notification is the same as on this screen (in other words the roomId prop),
      // we don't want to display a foreground push notification
      if (room_id === roomId) {
        return;
      }

      // Display a foreground notification here, since the push notification is targeting another chat room
      Notifications.scheduleNotificationAsync({
        // We're setting the trigger to null since we want the notification to be presented immediately
        trigger: null,
        content: {
          title: 'A new message',
          body: message_text,
        },
      });
    });

    return () => {
      // Unsubscribe when component unmmounts
      Notifications.removeNotificationSubscription(notificationListener.current);
    };
  }, [roomId]);
};

另一种方法是,您可以在全局状态中拥有当前聊天室 ID,然后在 handleNotification 回调中,您可以检查通知中收到的聊天室 ID 是否与全局状态中的那个。如果是,则不显示通知。您可以将 Notifications.setNotificationHandler 更新为如下内容:

Notifications.setNotificationHandler({
  handleNotification: (n) => {
    const { room_id } = n?.request?.content?.data ?? {};
    // Get the room id from your global state, maybe from redux or similar
    const showNotification = room_id !== globalState.roomId;

    return new Promise((resolve) =>
      resolve({
        shouldShowAlert: showNotification,
        shouldPlaySound: false,
        shouldSetBadge: false,
      }),
    );
  },
});