React Native Android 应用程序在收到 FCM 通知时崩溃

React Native Android App crashes when receiving FCM notification

我有一个 React 本机应用程序,我正在尝试使用 react-native-push-notification 包和 firebase 云消息传递来实现推送通知。事实证明,当我收到通知时,应用程序就停止工作了。 RemotePushController 功能似乎可以正常工作,应用程序一启动,我就会获得带有令牌的控制台日志。我已经尝试了几种方法,但没有任何效果。

[] [

我能够通过更改 android/build.gradle 处的 googlePlayServicesVersion 和 firebaseMessagingVersion 的版本来解决问题,如下图所示。我都设置为“+”。

对于Android,无需在AndroidManifest.xml中设置任何内容。 在顶层 build.gradle 具有以下配置应该就足够了。注意版本号上的“+”。

buildscript {
    ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 16
        compileSdkVersion = 28
        targetSdkVersion = 28
        googlePlayServicesVersion = "16.+"
        androidMapsUtilsVersion = "0.5+"
        firebaseVersion = "+"
        firebaseMessagingVersion = "+"
}

这是我为 FCM 创建的挂钩。

import React, { useEffect } from 'react'
import { Alert } from 'react-native'
import messaging from '@react-native-firebase/messaging'
import { useNavigation } from '@react-navigation/native'
import { useAsyncStorage } from '@react-native-community/async-storage'

const useFirebaseCloudMessaging = () => {
  const navigation = useNavigation()
  const { getItem: getFcmToken, setItem: saveFcmToken } = useAsyncStorage('fcmToken')

  const [fcmToken, setFcmToken] = React.useState(null)
  const [initialRoute, setInitialRoute] = React.useState('Home')

  const getToken = async () => {
    const token = await getFcmToken()

    if (!token) {
      // Get the device token
      messaging()
        .getToken()
        .then(token => {
          setFcmToken(token)
          saveFcmToken(token)
        })
    }
  }

  const requestUserPermission = async () => {
    const authStatus = await messaging().requestPermission()
    const enabled =
      authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
      authStatus === messaging.AuthorizationStatus.PROVISIONAL

    if (enabled) {
      console.log('Authorization status:', authStatus)
    }
  }

  useEffect(() => {
    // If using other push notification providers (ie Amazon SNS, etc)
    // you may need to get the APNs token instead for iOS:
    // if(Platform.OS == 'ios') { messaging().getAPNSToken().then(token => { return saveTokenToDatabase(token); }); }

    // Listen to whether the token changes
    return messaging().onTokenRefresh(token => {
      saveFcmToken(token)
    })
  }, [])

  useEffect(() => {
    const unsubscribe = messaging().onMessage(async remoteMessage => {
      Alert.alert('A new FCM message arrived!', JSON.stringify(remoteMessage))
    })

    return unsubscribe
  }, [])

  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"
        }
      })
  }, [])

  return {
    fcmToken,
    getToken,
    requestUserPermission
  }
}

export default useFirebaseCloudMessaging

在顶级 App 组件中使用钩子

import React, { useEffect } from 'react'

import Root from './App'
import useFirebaseCloudMessaging from './FirebaseCloudMessaging'

const App = () => {
  const {
    getToken,
    requestUserPermission
  } = useFirebaseCloudMessaging()

  useEffect(() => {
    requestUserPermission()
    getToken()
  }, [])

  return <Root />
}

export default App