首页 > 解决方案 > 推送通知操作按钮不显示 - 背景和终止状态 - React Native

问题描述

我已经使用 Firebase 和react-native-push-notification包实现了 firebase 推送通知。

目前,我已经根据每个推送通知的click_action实现了动作按钮。一旦应用程序处于前台,它就可以工作,并且一旦应用程序处于终止状态或后台操作按钮不显示。

我的 FCM 帮助文件

class FCMServiceHelper {
  register = (onRegister, onNotification, onOpenNotification) => {
    this.checkPermission(onRegister);
    this.createNotificationListeners(
      onRegister,
      onNotification,
      onOpenNotification,
    );
  };

  registerAppWithFCM = async () => {
    if (Platform.OS === 'ios') {
      await messaging().registerDeviceForRemoteMessages();
      await messaging().setAutoInitEnabled(true);
    }
  };

  checkPermission = (onRegister) => {
    messaging()
      .hasPermission()
      .then((enabled) => {
        if (enabled) {
          // User has permissions
          this.deleteToken()
          this.getToken(onRegister);
        } else {
          // User doesn't have permission
          this.requestPermission(onRegister);
        }
      })
      .catch((error) => {
        console.log('[FCMService] Permission rejected ', error);
      });
  };

  getToken = (onRegister) => {
    messaging()
      .getToken(undefined,'*')
      .then((fcmToken) => {
        if (fcmToken) {
          onRegister(fcmToken);
        } else {
          console.log('[FCMService] User does not have a device token');
        }
      })
      .catch((error) => {
        console.log('[FCMService] getToken rejected ', error);
      });
  };

  requestPermission = (onRegister) => {
    messaging()
      .requestPermission()
      .then(() => {
        this.deleteToken()
        this.getToken(onRegister);
      })
      .catch((error) => {
        console.log('[FCMService] Request Permission rejected ', error);
      });
  };

  deleteToken = () => {
    console.log('[FCMService] deleteToken ');
    messaging()
      .deleteToken(undefined,'*')
      .catch((error) => {
        console.log('[FCMService] Delete token error ', error);
      });
  };

  unregisterDeviceFromNotifications = () => {
    console.log('[FCMService] unreg ');
    messaging()
      .unregisterDeviceForRemoteMessages()
      .catch((error) => {
        console.log('[FCMService] Unreg device ', error);
      });
  };

  createNotificationListeners = (
    onRegister,
    onNotification,
    onOpenNotification,
  ) => {
    // When the application is running, but in the background
    messaging().onNotificationOpenedApp((remoteMessage) => {
      console.log(
        '[FCMService] onNotificationOpenedApp Notification caused app to open from background state:',
        remoteMessage,
      );
      if (remoteMessage) {
        let notification = null;
        let data = remoteMessage.data;
        let openFromKilling = {"checked" : true}
        notification = remoteMessage.notification;
        notification.data = data;
        notification.checking = openFromKilling;
        onOpenNotification(notification);
      }
    });

    // When the application is opened from a quit state.
    messaging()
      .getInitialNotification()
      .then((remoteMessage) => {
        console.log(
          '[FCMService] getInitialNotification Notification caused app to open from quit state:',
          remoteMessage,
        );

        if (remoteMessage) {
          let notification = null;
          let data = remoteMessage.data;
          let openFromKilling = {"checked" : true}
          notification = remoteMessage.notification;
          notification.data = data;
          notification.checking = openFromKilling;
          onOpenNotification(notification);
        }
      });

    // Foreground state messages
    this.messageListener = messaging().onMessage(async (remoteMessage) => {
      console.log(
        '[FCMService] A new FCM message arrived! foreground',
        remoteMessage,
      );
      if (remoteMessage) {
        let notification = null;
        let data = remoteMessage.data;

        if (Platform.OS === 'ios') {
          notification = remoteMessage.notification;
        } else {
          notification = remoteMessage.notification;
        }
        notification.data = data;
        onNotification(notification);
        // onOpenNotification(remoteMessage.data);
      }
    });
    // Triggered when have new token
    // messaging().onTokenRefresh((fcmToken) => {
    //   alert('REFRESH TOKEN');
    //   console.log('[FCMService] New token refresh: ', fcmToken);
    //   onRegister(fcmToken);
    // });
  };

  unRegister = () => {
    // if(this.messageListener){
      this.messageListener();
    // }
  };
}

我的通知处理程序文件

fcmService.registerAppWithFCM();
fcmService.register(onRegister, onNotification, onOpenNotificaion , onAction);
localNotificationService.configure(onOpenNotificaion,onAction);

function onRegister(token) {
  saveFCMToken(token);
}

if (Platform.OS == 'android') {
  localNotificationService.createChannelAndroid('wapp');
}

function onNotification(notify) {
  var RandomNumber = Math.floor(Math.random() * 100) + 1;
  let actionData = [];

  if(Platform.OS == 'android'){
    if(notify.data.click_action == 'alert_dashboard'){
      actionData = ["Update contact number"]
    }else if(notify.data.click_action == 'account_edit'){
      actionData = ["Update Email"]
    }
  }

  const options = {
    soundName: 'default',
    playSound: true,
  };
  localNotificationService.showNotification(
    RandomNumber,
    notify.title,
    Platform.OS == 'android' ? notify.body : notify.body,
    notify,
    options,
    'wapp',
    actionData
  );
}
function onAction(notification) {
  console.log ('Notification action received:');
  console.log(notification.action);
  console.log(notification);
}

通知帮助文件

class NotificationHelper {
  configure = (onOpenNotification) => {
    PushNotification.configure({
      onRegister: function (token) {
        console.log('[NotificationManager] onRegister token:', token.token);
      },

      onNotification: function (notification) {
        console.log('[NotificationManager] onNotification:', notification);

        if (Platform.OS === 'ios') {
          if (notification.data.openedInForeground) {
            notification.userInteraction = true;
          }
        }

        if (notification.userInteraction) {
          onOpenNotification(notification);
        } else {
          onNotification(notification);
        }

        if (Platform.OS === 'android') {
          notification.userInteraction = true;
        }

        // Only call callback if not from foreground
        if (Platform.OS === 'ios') {
          if (!notification.data.openedInForeground) {
            notification.finish('backgroundFetchResultNoData');
          }
        } else {
          notification.finish('backgroundFetchResultNoData');
        }
      },
      onAction: function (notification) {
        // alert(notification)
        console.log("ACTION:", notification.action);
        console.log("NOTIFICATION:", notification);
        // notification.userInteraction = true;
        // PushNotification.invokeApp(notification);
      },
    });
  };

  unregister = () => {
    PushNotification.unregister();
  };

  createChannelAndroid = (channel) => {
    PushNotification.createChannel(
      {
        channelId: channel, // (required)
        channelName: 'My channel', // (required)
        channelDescription: 'A channel to categorise your notifications', // (optional) default: undefined.
        playSound: false, // (optional) default: true
        soundName: 'default', // (optional) See `soundName` parameter of `localNotification` function
        importance: 4, // (optional) default: 4. Int value of the Android notification importance
        vibrate: true, // (optional) default: true. Creates the default vibration patten if true.
      },
      (created) => console.log(`createChannel returned '${created}'`), // (optional) callback returns whether the channel was created, false means it already existed.
    );
  };

  showNotification = (id, title, message, data = {}, options = {}, channel , testData) => {
    PushNotification.localNotification({
      /* Android Only Properties */
      ...this.buildAndroidNotification(
        id,
        title,
        message,
        data,
        options,
        channel,
        testData
      ),
      /* iOS and Android properties */
      ...this.buildIOSNotification(id, title, message, data, options),
      /* iOS and Android properties */
      title: title || '',
      message: message || '',
      playSound: options.playSound || true,
      soundName: options.soundName || 'default',
      userInteraction: true, // BOOLEAN: If the notification was opened by the user from the notification area or not
    });
  };

  buildAndroidNotification = (
    id,
    title,
    message,
    data = {},
    options = {},
    channel,
    testData
  ) => {
    console.log('TEST DATA -> ',data)
    return {
      showWhen: true,  // This is probably not needed, since default value is TRUE.
      when: new Date().getTime(),
      group: "wapp",
      groupSummary: true,
      channelId: channel,
      id: id,
      autoCancel: true,
      largeIcon: options.largeIcon || 'ic_launcher',
      smallIcon: options.smallIcon || 'ic_launcher',
      bigText: message || '',
      subText: title || '',
      vibrate: options.vibrate || true,
      vibration: options.vibration || 300,
      priority: options.priority || 'high',
      importance: options.importance || 'high', // (optional) set notification importance, default: high,
      data: data,
      actions:testData,
      // invokeApp:false,
    };
  };

  buildIOSNotification = (id, title, message, data = {}, options = {}) => {
    return {
      alertAction: options.alertAction || 'view',
      alertBody: message || '',
      category: options.category || '',
      userInfo: {
        id: id,
        item: data,
      },
    };
  };

  cancelAllLocalNotifications = () => {
    if (Platform.OS === 'ios') {
      PushNotificationIOS.removeAllDeliveredNotifications();
    } else {
      PushNotification.cancelAllLocalNotifications();
    }
  };

  removeDeliveredNotificationByID = (notificationId) => {
    console.log(
      '[LocalNotificationService] removeDeliveredNotificationByID: ',
      notificationId,
    );
    PushNotification.cancelLocalNotifications({id: `${notificationId}`});
  };
}

我的应用程序 index.js 文件

/**
 * @format
 */
import React from 'react';
import 'react-native-gesture-handler';
import { AppRegistry, LogBox, YellowBox } from 'react-native';
import App from './app/Entrypoint';
import { name as appName } from './app.json';
import { enableScreens } from 'react-native-screens';
import messaging from '@react-native-firebase/messaging';
import { backgroundGeo, checkLocationLogics } from './app/helpers/backgroundLocationTracking';
import env from 'react-native-config';

enableScreens();

messaging().setBackgroundMessageHandler(async (remoteMessage) => {
  console.log('Message handled in the background!', remoteMessage);
});

function HeadlessCheck({ isHeadless }) {
  if (isHeadless) {
    // App has been launched in the background by iOS, ignore
    return null;
  }

  return <App />;
}

AppRegistry.registerComponent(appName, () => HeadlessCheck);

标签: androidreact-nativepush-notificationfirebase-cloud-messagingreact-native-push-notification

解决方案


尝试在 setBackgroundMessageHandler 中调用 showNotification 方法,当应用程序不处于前台或终止状态时会调用该方法

messaging().setBackgroundMessageHandler(async (remoteMessage) => {
  console.log('Message handled in the background!', remoteMessage);
  const options = {
      soundName: 'default',
      playSound: true,
    };
    const {title, body, data} = remoteMessage;
    localNotificationService.showNotification(
      title,
      body,
      data,
      options,
  }
});

推荐阅读