Deep links in react-native-firebase notifications

余生颓废 提交于 2019-12-06 13:23:16

I think you are fine with the "how firebase notification work"... cause of this, here is only an description of the Logic how you can Deeplinking into your App.

If you send a notification, add a data-field. Let's say your app has a Tab-Navigator and the sections "News","Service" and "Review". In your Push-Notification - Datafield (let's name it "jumpToScreen" you define your value:

jumpToScreen = Service

I assume you still have the Handling to recieve Notifications from Firebase implemented. So create an /lib/MessageHandler.js Class and put your business-logic inside.

import firebase from 'react-native-firebase';

/*
 * Get a string from Firebase-Messages and return the Screen to jump to
 */
const getJumpPoint = (pointer) => {
  switch (pointer) {
    case 'News':
      return 'NAV_NewsList'; // <= this are the names of your Screens
    case 'Service':
      return 'NAV_ServiceList';
    case 'Review':
      return 'NAV_ReviewDetail';
    default: return false;
  }
};

const MessageHandler = {
  /**
   *  initPushNotification  initialize Firebase Messaging
   *  @return fcmToken String
   */
  initPushNotification: async () => {
    try {
      const notificationPermission = await firebase.messaging().hasPermission();
      MessageHandler.setNotificationChannels();

      if (notificationPermission) {
        try {
          return await MessageHandler.getNotificationToken();
        } catch (error) {
          console.log(`Error: failed to get Notification-Token \n ${error}`);
        }
      }
    } catch (error) {
      console.log(`Error while checking Notification-Permission\n ${error}`);
    }
    return false;
  },
  clearBadges:  () => {
    firebase.notifications().setBadge(0);
  },
  getNotificationToken: () => firebase.messaging().getToken(),
  setNotificationChannels() {
    try {
      /* Notification-Channels is a must-have for Android >= 8 */
      const channel = new firebase.notifications.Android.Channel(
        'app-infos',
        'App Infos',
        firebase.notifications.Android.Importance.Max,
      ).setDescription('General Information');

      firebase.notifications().android.createChannel(channel);
    } catch (error) {
      console.log('Error while creating Push_Notification-Channel');
    }
  },
  requestPermission: () => {
    try {
      firebase.messaging().requestPermission();
      firebase.analytics().logEvent('pushNotification_permission', { decision: 'denied' });
    } catch (error) {
      // User has rejected permissions
      firebase.analytics().logEvent('pushNotification_permission', { decision: 'allowed' });
    }
  },
  foregroundNotificationListener: (navigation) => {
    // In-App Messages if App in Foreground
    firebase.notifications().onNotification((notification) => {
      MessageHandler.setNotificationChannels();
      navigation.navigate(getJumpPoint(notification.data.screen));
    });
  },
  backgroundNotificationListener: (navigation) => {
    // In-App Messages if App in Background
    firebase.notifications().onNotificationOpened((notificationOpen) => {
      const { notification } = notificationOpen;
      notification.android.setChannelId('app-infos');
      if (notification.data.screen !== undefined) {
        navigation.navigate(getJumpPoint(notification.data.screen));
      }
    });
  },
  appInitNotificationListener: () => {
    // In-App Messages if App in Background
    firebase.notifications().onNotificationOpend((notification) => {
      notification.android.setChannelId('app-infos');
      console.log('App-Init: Da kommt ne Message rein', notification);
      firebase.notifications().displayNotification(notification);
    });
  },
};

export default MessageHandler;

In your index.js you can connect it like this:

import MessageHandler from './lib/MessageHandler';
export default class App extends Component {
    state = {
      loading: null,
      connection: null,
      settings: null,
    };
async componentDidMount() {
    const { navigation } = this.props;
    await MessageHandler.initPushNotification();
    this.notificationForegroundListener = MessageHandler.foregroundNotificationListener(navigation);
    this.notificationBackgroundListener = MessageHandler.backgroundNotificationListener(navigation);

    this.setState({ loading: false, data });
  }

    componentWillUnmount() {
        this.notificationForegroundListener();
        this.notificationBackgroundListener();
    }
    async componentDidMount() {
      MessageHandler.requestPermission();
      AppState.addEventListener('change', this.handleAppStateChange);
      MessageHandler.clearBadges();
    }

    componentWillUnmount() {
      AppState.removeEventListener('change', this.handleAppStateChange);
    }
    handleAppStateChange = (nextAppState) => {
        if (nextAppState.match(/inactive|background/)) {
           MessageHandler.clearBadges();
        }
    ....

I hope this give you an Idea how to implement it for your needs.

My solution was to use add what information I need in the data object of the notification message object:

in functions/index.js:

  let message = {
    notification: {
      body: `new notification `
    },
    token: pushToken,
    data: {
      type: 'NEW_TRAINING',
      title: locationTitle
    }
  };

and process as follows in the app for navigation:

this.notificationOpenedListener =
      firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => {
      if (notification.data.type === 'NEW_TRAINING') {
        this.props.navigator.push({
          screen: 'newtrainingscreen',
          title: notification.data.title,
          animated: true
        });
      }

I think you don't need to use deep links nor dynamic links but just use Firebase/Notifications properly. If I were you I would add the following logic in the componentDidMount method of your parent container:

async componentDidMount() {

    // 1. Check notification permission
    const notificationsEnabled = await firebase.messaging().hasPermission();
    if (!notificationsEnabled) {
        try {
            await firebase.messaging().requestPermission(); // Request notification permission
            // At this point the user has authorized the notifications
        } catch (error) {
            // The user has NOT authorized the notifications
        }
    }

    // 2. Get the registration token for firebase notifications
    const fcmToken = await firebase.messaging().getToken();
    // Save the token

    // 3. Listen for notifications. To do that, react-native-firebase offer you some methods:
    firebase.messaging().onMessage(message => { /*  */ })

    firebase.notifications().onNotificationDisplayed(notification => { /* */ })

    firebase.messaging().onNotification(notification => { /*  */ })

    firebase.messaging().onNotificationOpened(notification => { 
        /* For instance, you could use it and do the NAVIGATION at this point
        this.props.navigation.navigate('SomeScreen');
        // Note that you can send whatever you want in the *notification* object, so you can add to the notification the route name of the screen you want to navigate to.
        */
    })

}

You can find the documentation here: https://rnfirebase.io/docs/v4.3.x/notifications/receiving-notifications

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!