React Native -如何从推送通知打开路由

bfhwhh0e  于 2023-05-18  发布在  React
关注(0)|答案(4)|浏览(92)

我使用react-navigationreact-native-push-notification。如何在onNotification回调中打开某个StackNavigator's屏幕?应在以下情况下工作:

  • 应用程序关闭
  • 应用程序位于前台
  • 应用程序在后台

我现在只需要它在Android上工作。
我尝试在组件中传递一个回调函数给notification:

_handleClick() {
  PushNotification.localNotification({
    foreground: false
    userInteraction: false
    message: 'My Notification Message'
    onOpen: () => { this.props.navigation.navigate("OtherScreen") },
  })
}

PushNotification配置中触发onOpen

onNotification: function(notification) {
   notification.onOpen()
}

但是,函数似乎不能传递给通知,除非一个值是一个字符串,它被忽略,导致onOpen未定义。

b4lqfgs4

b4lqfgs41#

好吧,看来我得发布自己的解决方案:)

// src/services/push-notification.js
const PushNotification = require('react-native-push-notification')

export function setupPushNotification(handleNotification) {
  PushNotification.configure({

      onNotification: function(notification) {
        handleNotification(notification)
      },

      popInitialNotification: true,
      requestPermissions: true,
  })

  return PushNotification
}

// Some notification-scheduling component
import {setupPushNotification} from "src/services/push-notification"

class SomeComponent extends PureComponent {

  componentDidMount() {
    this.pushNotification = setupPushNotification(this._handleNotificationOpen)
  }

  _handleNotificationOpen = () => {
    const {navigate} = this.props.navigation
    navigate("SomeOtherScreen")
  }

  _handlePress = () => {
    this.pushNotification.localNotificationSchedule({
      message: 'Some message',
      date: new Date(Date.now() + (10 * 1000)), // to schedule it in 10 secs in my case
    })

  }

  render() {
    // use _handlePress function somewhere to schedule notification
  }

}
rqenqsqc

rqenqsqc2#

我在Firebase的官方网站上找到了这个解决方案,这似乎是最好的例子/样本工作。下面是示例片段和链接。希望它能帮助到其他人。

import React, { useState, useEffect } from 'react';
import messaging from '@react-native-firebase/messaging';
import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

function App() {
  const navigation = useNavigation();
  const [loading, setLoading] = useState(true);
  const [initialRoute, setInitialRoute] = useState('Home');

  useEffect(() => {
    // Assume a message-notification contains a "type" property in the data payload of the screen to open

    messaging().onNotificationOpenedApp(remoteMessage => {
      console.log(
        'Notification caused app to open from background state:',
        remoteMessage.notification,
      );
      navigation.navigate(remoteMessage.data.type);
    });

    // Check whether an initial notification is available
    messaging()
      .getInitialNotification()
      .then(remoteMessage => {
        if (remoteMessage) {
          console.log(
            'Notification caused app to open from quit state:',
            remoteMessage.notification,
          );
          setInitialRoute(remoteMessage.data.type); // e.g. "Settings"
        }
        setLoading(false);
      });
  }, []);

  if (loading) {
    return null;
  }

  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName={initialRoute}>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Settings" component={SettingsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

网址:https://rnfirebase.io/messaging/notifications#handling-interaction

nnsrf1az

nnsrf1az3#

鉴于我是如何使用传统的react-native-firebase,我想我会发布我对这个问题的解决方案,因为它与上面使用RN-firebase V6的答案之一略有不同。我的解决方案只是略有不同,此解决方案适用于react-native-firebase v5.x的通知处理:

import * as React from 'react';
import { Text, TextInput } from 'react-native';
import AppNavigation from './src/navigation';
import { Provider } from 'react-redux';
import { store, persistor } from './src/store/index.js';
import 'react-native-gesture-handler';
import firebase from 'react-native-firebase';
import { PersistGate } from 'redux-persist/integration/react';

export default class App extends React.Component {
    constructor(props) {
        super(props);
        if (firebase.apps.length === 0) {
            firebase.initializeApp({});
        }
    }

    async componentDidMount() {
        // Initialize listener for when a notification has been displayed
        this.removeNotificationDisplayedListener = firebase.notifications().onNotificationDisplayed((notification) => {
            // process notification as required... android remote notif's do not have a "channel ID".
        });

        // Initialize listener for when a notification is received
        this.removeNotificationListener = firebase.notifications().onNotification((notification) => {
            // Process notification
        });

        // Listener for notification tap if in FOREGROUND & BACKGROUND
        this.removeNotificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen) => {
            // get the action trigger by the notification being opened
            const action = notificationOpen.action;

            // get info about the opened notification
            const info = notificationOpen.notification;

            // log for testing
            console.log('ACTION => ' + action + '\nNOTIFICATION INFO => ' + JSON.stringify(info));
        });

        // Listener for notification tap if app closed
        const notificationOpen = await firebase.notifications().getInitialNotification();
        if (notificationOpen) {
            // App was opened by notification
            const action = notificationOpen.action;
            const info = notificationOpen.notification;

            // log for testing:
            console.log('ACTION => ' + action + '\nNOTIFICATION INFO => ' + JSON.stringify(info));
        }
    }

    componentWillUnmount() {
        // Invoke these functions to un-subscribe the listener
        this.removeNotificationDisplayedListener();
        this.removeNotificationListener();
        this.removeNotificationOpenedListener();
    }

    render() {
        return (
            <Provider store={store}>
                <PersistGate loading={null} persistor={persistor}>
                    <AppNavigation />
                </PersistGate>
            </Provider>
        );
    }
}
of1yzvn4

of1yzvn44#

这些信息可能对某人有用。
在我的场景中,如果用户收到通知但尚未登录,则应用程序不应将其重定向到所需的屏幕。
如果用户不在登录屏幕上,用户按下通知,我们应该重定向他们(在我的情况下是屏幕2)。
为此,我将导航参考发送到我的NotificationHelper
使用:
@react-navigation/native: 6.X
@react-native-firebase/messaging: 17.x
@notifee/react-native: 7.x
验证码:
MainScreen.tsx

import { createNavigationContainerRef } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

const MainScreen: React.FC = () => {
  const Stack = createNativeStackNavigator();
  const navigationRef = createNavigationContainerRef();
  return (
    <NavigationContainer ref={navigationRef}>
      <Stack.Navigator screenOptions={{ headerShown: false }}>
        <Stack.Screen name="Login" component={LoginScree} />
        <Stack.Screen name="Screen1" component={Screen1} />
        <Stack.Screen
          name="Screen2"
          component={Screen2}
        />
      </Stack.Navigator>
      <NotificationHelper navigationRef={navigationRef} />
    </NavigationContainer>     
  );
};

NotificationHelper.tsx

import messaging, {
  FirebaseMessagingTypes,
} from '@react-native-firebase/messaging';
import { NavigationContainerRefWithCurrent } from '@react-navigation/native';
import { FC, useCallback, useEffect } from 'react';

type PropsType = {
  navigationRef: NavigationContainerRefWithCurrent<ReactNavigation.RootParamList>;
};

const NotificationHelper: FC<PropsType> = (props: PropsType) => {
  const redirectToScreen = useCallback(
    (notification: any) => {
      if (props.navigationRef) {
        const currentRoute = props.navigationRef.getCurrentRoute()?.name;
        if (currentRoute) {
          if (currentRoute !== 'Login') {
            props.navigationRef.navigate('Screen2', {
              param1: notification.property1,
              param2: notification.property2,
            });
          }
        }
      }
    },
    [props.navigationRef],
  );

  useEffect(() => {
    const unsubscribeOpenedApp = messaging().onNotificationOpenedApp(
      async (remoteMessage) => {
        if (remoteMessage.data) {
          console.debug('User pressed notification');
          redirectToScreen(remoteMessage.data);
        }
      },
    );
    const unsubscribeForegroundOpenApp = notifee.onForegroundEvent(
      ({ type, detail }) => {
        switch (type) {
          case EventType.PRESS:
            console.debug('User pressed notification');
            if (detail.notification && detail.notification.data) {
              redirectToScreen(
                detail.notification.data,
              );
            }
            break;
        }
      },
    );
    return () => {
      unsubscribeOpenedApp();
      unsubscribeForegroundOpenApp();
    };
  }, [redirectToScreen]);

  return null;
};

export default NotificationHelper;

相关问题