You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理React Native WebView内嵌Web应用的Firebase通知问题

问题原因

React Native WebView并非标准浏览器环境,FCM Web SDK依赖的Push API、Service Worker等Web核心API在WebView中未实现,直接使用Web版FCM SDK会触发不兼容报错。

解决方案

推荐通过React Native原生层处理FCM通知,这是最稳定可靠的方案,具体步骤如下:

步骤1:React Native端集成原生FCM SDK

  1. 安装依赖:npm install @react-native-firebase/app @react-native-firebase/messaging
  2. 按照Firebase官方文档完成iOS和Android的原生FCM环境配置(添加Google服务文件、配置通知权限等)

步骤2:React Native端与WebView通信传递令牌

修改WebView组件,获取原生FCM令牌并通过postMessage传给Web应用:

import React, { useEffect, useState, useRef } from 'react';
import { WebView } from 'react-native-webview';
import messaging from '@react-native-firebase/messaging';

const AppWebView = () => {
  const [fcmToken, setFcmToken] = useState('');
  const webViewRef = useRef(null);

  useEffect(() => {
    async function fetchToken() {
      const authStatus = await messaging.requestPermission();
      if (authStatus === messaging.AuthorizationStatus.AUTHORIZED) {
        const token = await messaging.getToken();
        setFcmToken(token);
      }
    }
    fetchToken();
  }, []);

  const handleWebMessage = (event) => {
    if (event.nativeEvent.data === 'GET_FCM_TOKEN') {
      webViewRef.current?.postMessage(JSON.stringify({
        type: 'FCM_TOKEN',
        token: fcmToken
      }));
    }
  };

  return (
    <WebView
      ref={webViewRef}
      source={{ uri: '你的Web应用HTTPS地址' }}
      onMessage={handleWebMessage}
      injectedJavaScript={`window.ReactNativeWebView.postMessage('GET_FCM_TOKEN');`}
      allowUniversalAccessFromFileURLs={true}
    />
  );
};

export default AppWebView;

步骤3:Web应用适配双环境

修改Web应用代码,判断当前环境是浏览器还是WebView,分别处理FCM令牌:

import { useEffect } from 'react';
import firebase from 'firebase/app';
import 'firebase/messaging';
import axios from 'axios';

const firebaseConfig = {
  apiKey: "AIzaSyC9K1X3mSSw2d9RTVqBwBRy7ECtmkzJ4to",
  authDomain: "brotherize-654cf.firebaseapp.com",
  projectId: "brotherize-654cf",
  storageBucket: "brotherize-654cf.appspot.com",
  messagingSenderId: "612370118030",
  appId: "1:612370118030:web:5a6bf0d77545330b2560df",
  measurementId: "G-4YSQ78M7VP",
};

let currentFcmToken = null;

// 判断是否处于React Native WebView中
const isWebViewEnv = () => typeof window.ReactNativeWebView !== 'undefined';

useEffect(() => {
  if (isWebViewEnv()) {
    // 监听来自原生的令牌消息
    window.addEventListener('message', (event) => {
      try {
        const data = JSON.parse(event.data);
        if (data.type === 'FCM_TOKEN' && data.token) {
          currentFcmToken = data.token;
          saveTokenToLocalStorage(currentFcmToken);
          saveTokenToDb(currentFcmToken);
        }
      } catch (e) {
        console.error('解析WebView消息失败:', e);
      }
    });
  } else {
    // 浏览器环境下用Web版FCM SDK
    firebase.initializeApp(firebaseConfig);
    const messaging = firebase.messaging();
    requestNotificationPermission(messaging);
  }
}, []);

export const requestNotificationPermission = async (messaging) => {
  try {
    const permission = await Notification.requestPermission();
    if (permission === 'granted') {
      console.log('通知权限已获取');
      getDeviceToken(messaging);
    } else {
      console.log('通知权限被拒绝');
    }
  } catch (error) {
    console.error('请求通知权限失败:', error);
  }
};

const getDeviceToken = async (messaging) => {
  try {
    currentFcmToken = await messaging.getToken({
      vapidKey: process.env.NEXT_PUBLIC_SERVER_KEY,
    });
    if (currentFcmToken) {
      console.log('设备令牌:', currentFcmToken);
      saveTokenToLocalStorage(currentFcmToken);
      saveTokenToDb(currentFcmToken);
    } else {
      console.log('无可用注册令牌');
    }
  } catch (error) {
    console.error('获取设备令牌失败:', error);
  }
};

const saveTokenToLocalStorage = (token) => {
  localStorage.setItem('device_token', JSON.stringify(token));
  console.log('令牌已保存到本地存储');
};

const saveTokenToDb = async (token) => {
  try {
    await axios.post('/v1/user/token', { deviceToken: token });
    console.log('令牌已保存到数据库');
  } catch (error) {
    console.error('保存令牌到数据库失败:', error);
  }
};

不推荐的替代方案

如果坚持在WebView中使用Web版FCM,可尝试使用支持完整浏览器API的第三方WebView(如react-native-webview-chromium),但这类方案兼容性差、配置复杂,且无法保证在所有设备上正常工作,不建议用于生产环境。

内容的提问来源于stack exchange,提问作者Kamran Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 18:32:37