問題背景
升級到 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 的自動初始化機制發生了變化:
- SDK 52 及以前:Firebase 通過 Expo 的自動配置系統初始化
- SDK 53:需要在
AppDelegate.swift
中手動調用FirebaseApp.configure()
- 時機很重要:必須在 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 時出錯
檢查列表:
- ✅
FirebaseApp.configure()
是否在正確位置? - ✅
GoogleService-Info.plist
是否在正確目錄? - ✅ Podfile 是否包含 modular headers 配置?
- ✅ 是否執行了
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 修復需要三個關鍵修改:
- AppDelegate.swift:手動初始化 Firebase
- Podfile:添加 modular headers 配置
- 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+