推送通知操作按钮不显示 - 背景和终止状态 - React Native

Posted

技术标签:

【中文标题】推送通知操作按钮不显示 - 背景和终止状态 - React Native【英文标题】:Push Notification Action Button Not Displaying - Background and Kill State - React Native 【发布时间】:2021-09-19 11:03:52 【问题描述】:

我已经使用 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);

【问题讨论】:

嘿,你完成了吗?您能否分享一个要点或上述文件的内容。我需要处理类似的问题 @VinayN 很遗憾没有找到任何解决方案 【参考方案1】:

尝试在 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,
  
);

【讨论】:

以上是关于推送通知操作按钮不显示 - 背景和终止状态 - React Native的主要内容,如果未能解决你的问题,请参考以下文章

当应用程序处于终止状态时,iOS 静默推送通知不会收到

如果设备收到来自 fcm 的推送通知,如何向处于终止状态的 android 应用程序显示/通信/广播消息

在 iOS 上为远程推送通知的通知操作调用 Web 服务

在显示推送通知弹出窗口时禁用点击主页按钮

如果应用程序终止,则未收到 iOS FCM 推送通知

在静音模式下播放声音,应用程序终止状态