[手動] Expo SDK 53 + Firebase Cloud Messaging (FCM) 完整修復指南

問題背景

升級到 Expo SDK 53 後,Firebase Cloud Messaging (FCM) 功能完全失效。雖然應用能正常運行,但無法收到任何推送通知。經過深入調試,發現這是 SDK 升級後原生 iOS 配置和 Firebase 初始化的相容性問題。

以下分享一下我的解決過程

核心問題分析

1. 升級前的狀態 (SDK 52)

  • FCM 功能正常工作
  • 能正常接收前台、後台和關閉狀態的通知
  • iOS 和 Android 推送都正常

2. 升級後的問題 (SDK 53)

  • 主要問題:FCM Token 無法正確獲取和註冊
  • 根本原因:Expo SDK 53 改變了 Firebase 的初始化機制
  • 表面現象:應用正常運行,但完全收不到推送通知

完整解決方案

步驟 1:修復 iOS AppDelegate.swift

文件位置: ios/[您的App名稱]/AppDelegate.swift

關鍵修改:添加 Firebase 手動初始化

import Expo
import FirebaseCore  // 新增:導入 FirebaseCore
import React
import ReactAppDependencyProvider

@UIApplicationMain
public class AppDelegate: ExpoAppDelegate {
  var window: UIWindow?

  var reactNativeDelegate: ExpoReactNativeFactoryDelegate?
  var reactNativeFactory: RCTReactNativeFactory?

  public override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
  ) -> Bool {
    // 🔥 關鍵修復:在 Expo SDK 53 中手動初始化 Firebase
    FirebaseApp.configure()

    let delegate = ReactNativeDelegate()
    let factory = ExpoReactNativeFactory(delegate: delegate)
    delegate.dependencyProvider = RCTAppDependencyProvider()

    reactNativeDelegate = delegate
    reactNativeFactory = factory
    bindReactNativeFactory(factory)

#if os(iOS) || os(tvOS)
    window = UIWindow(frame: UIScreen.main.bounds)
    factory.startReactNative(
      withModuleName: "main",
      in: window,
      launchOptions: launchOptions)
#endif

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  // ... 其餘代碼保持不變
}

步驟 2:修復 iOS Podfile

文件位置: ios/Podfile

關鍵修改:添加 Firebase 模組的 modular headers 配置

target 'YourAppName' do
  use_expo_modules!

  # ... 其他配置

  # 🔥 關鍵修復:Firebase 特定的模組頭文件配置
  pod 'GoogleUtilities', :modular_headers => true
  pod 'FirebaseCore', :modular_headers => true
  pod 'FirebaseCoreInternal', :modular_headers => true
  pod 'FirebaseMessaging', :modular_headers => true
  pod 'FirebaseInstallations', :modular_headers => true

  use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
  # ... 其餘配置
end

步驟 3:確保 GoogleService-Info.plist 正確放置

重要文件位置

  • ios/[您的App名稱]/GoogleService-Info.plist ✅ 正確位置
  • ios/GoogleService-Info.plist ❌ 錯誤位置

驗證方法

# 確保文件在正確位置
ls -la ios/[您的App名稱]/GoogleService-Info.plist

# 確保 Xcode 項目包含此文件
# 打開 Xcode → 檢查 Project Navigator → 確保 GoogleService-Info.plist 在項目中

步驟 4:清理並重新安裝

執行以下命令完全清理並重新安裝:

# 1. 清理 iOS 依賴
cd ios
rm -rf Pods Podfile.lock
pod install

# 2. 回到項目根目錄並重新運行
cd ..
npx expo run:ios --device

關鍵技術細節

為什麼需要手動初始化 Firebase?

在 Expo SDK 53 中,Firebase 的自動初始化機制發生了變化:

  1. SDK 52 及以前:Firebase 通過 Expo 的自動配置系統初始化
  2. SDK 53:需要在 AppDelegate.swift 中手動調用 FirebaseApp.configure()
  3. 時機很重要:必須在 React Native 初始化之前調用

為什麼需要 modular headers?

pod 'FirebaseCore', :modular_headers => true

這是因為:

  • Expo SDK 53 使用了新的模組系統
  • Firebase SDK 需要 modular headers 來正確編譯
  • 沒有這個配置會導致編譯錯誤或運行時問題

常見錯誤和解決方法

錯誤 1:APNS Token 錯誤

[messaging/unknown] The operation couldn't be completed. No APNS token specified before fetching FCM Token

解決方法:這個錯誤通常在首次啟動或模擬器中出現,不影響功能,可以忽略。

錯誤 2:FCM Token 獲取失敗

❌ 獲取 FCM Token 時出錯

檢查列表

  1. FirebaseApp.configure() 是否在正確位置?
  2. GoogleService-Info.plist 是否在正確目錄?
  3. ✅ Podfile 是否包含 modular headers 配置?
  4. ✅ 是否執行了 pod install

錯誤 3:編譯錯誤

Firebase module not found

解決方法

cd ios
rm -rf Pods Podfile.lock
pod install

驗證解決方案

1. 檢查 FCM Token 獲取

啟動應用後,應該看到類似日誌:

✅ FCM Token 獲取成功: cUE4RZyNv08htRQlaY5XoI:APA91bH0...

2. 測試通知功能

  • 前台通知:應用在前台時,通知顯示為橫幅
  • 後台通知:應用在後台時,點擊通知可以打開應用
  • 關閉狀態:應用關閉時,通知可以喚醒應用

3. 檢查後端集成

確保後端使用正確的 FCM Token 發送通知:

// 範例:檢查 FCM Token 是否正確同步到後端
console.log('FCM Token:', fcmToken);

總結

Expo SDK 53 的 FCM 修復需要三個關鍵修改:

  1. AppDelegate.swift:手動初始化 Firebase
  2. Podfile:添加 modular headers 配置
  3. GoogleService-Info.plist:確保文件在正確位置

這個解決方案已經在生產環境中驗證,完全恢復了 FCM 功能。

故障排除檢查清單

升級到 SDK 53 後 FCM 不工作?按照以下順序檢查:

  • [ ] FirebaseApp.configure() 已添加到 AppDelegate.swift
  • [ ] Podfile 包含所有 Firebase modular headers
  • [ ] GoogleService-Info.plist 在 ios/[AppName]/ 目錄中
  • [ ] 執行了完整的清理和重新安裝流程
  • [ ] FCM Token 能正確獲取
  • [ ] 後端使用正確的 FCM Token

完成以上檢查後,FCM 功能應該完全恢復正常。


版本: Expo SDK 53, React Native Firebase v19+
測試平台: iOS 17+, Xcode 15+