Expo 获取推送 Token 时提示 Default FirebaseApp 未初始化怎么办?
这个错误表示 Android 当前进程中没有可用的默认 FirebaseApp。先检查实际安装的 APK 是否包含正确的 Firebase 原生配置,再检查 Expo Token 获取代码。上传 FCM V1 service account key 只完成了服务端发送凭据的配置,不能证明客户端已成功初始化。
现有材料无法确定唯一根因,建议优先核对两个线索:报错中的进程名与 app.json 中的包名不同,以及 APK 是直接通过 Gradle 构建的。
先区分两种 Firebase 配置
推送接入涉及两个用途不同的 JSON 文件:
- FCM V1 service account key:上传到 Expo,用于 Expo 服务向 FCM 发送通知。
- google-services.json:用于 Android 客户端的 Firebase 配置,需要参与原生构建。
即使 Expo 控制台中的凭据完全正确,如果 APK 缺少客户端配置,仍可能出现初始化错误。Expo 的 FCM 凭据文档分别列出了这两项配置。
1. 核对实际构建的 applicationId
问题中出现了两个不同的标识:
报错中的进程名:com.guilherme_naxe.naxemobile
app.json 中的包名:com.teste123.naxemobile
如果这两个值没有经过脱敏,且应用没有设置自定义进程名,应先检查运行的是否是旧 APK,或者 Android 原生工程是否仍在使用旧配置。这个差异本身还不足以确定根因。
检查 android/app/build.gradle 中的 applicationId,同时查看 productFlavors、buildTypes 和 applicationIdSuffix 对最终应用 ID 的影响。然后确认 google-services.json 的 client 数组中存在匹配项:
client[].client_info.android_client_info.package_name
匹配目标是当前构建变体的最终 applicationId。Google Services 插件按包名选择 client,找不到匹配项时会报构建错误。Firebase 的插件说明记录了这一处理规则。
APK 成功构建仍不足以证明配置正确。还要确认插件确实参与了构建,设备运行的也是本次生成的 APK。
2. 确认 app.json 已同步到原生工程
直接运行 Gradle 时,构建的是 android 目录中的原生工程。修改 app.json 后,需要通过相应流程将配置落实到原生文件中。
如果项目使用 Expo Prebuild 管理 Android 工程,可以将配置源文件放在项目根目录,并将下列字段合并到现有 app.json 中。示例包名沿用问题中的值,实际应以目标应用 ID 为准:
{
"expo": {
"android": {
"package": "com.teste123.naxemobile",
"googleServicesFile": "./google-services.json"
},
"plugins": ["expo-notifications"]
}
}
保留已有的其他配置和 plugins 项,然后在项目根目录执行:
npx expo prebuild --platform android
执行后,检查生成的 android/app/google-services.json 和 Gradle 配置,再构建 APK。Expo Prebuild 根据应用配置和 config plugins 生成原生工程;重新生成可能影响手动修改过的原生文件,操作前应保存这些改动。Expo CNG 文档说明了这一流程。
如果项目长期手动维护 android 目录,直接核对原生配置即可,无需反复删除目录。android/app/google-services.json 是常见的文件位置,重点是构建插件是否处理了它。
3. 检查 Google Services 插件是否真正运行
还需要确认 Google Services Gradle 插件处理了 JSON 文件。该插件会读取文件,并生成 Firebase 使用的 Android 资源,例如 google_app_id 和 gcm_defaultSenderId。Firebase 插件文档说明了生成的文件和资源。
对于使用 Groovy Gradle 脚本的项目,应用模块可以通过以下语句应用插件:
apply plugin: 'com.google.gms.google-services'
如果项目使用 plugins DSL,应按现有结构声明同一插件。还要确认项目级配置能解析该插件;不要重复添加两套声明,也不要在缺少 Gradle 配置信息时随意指定插件版本。
在 android 目录中,可以先针对实际构建变体单独运行处理任务。下面以 Release 为例:
./gradlew :app:processReleaseGoogleServices --info
如果使用 Debug 或 product flavors,需要替换为对应的任务名称。
根据结果继续排查:
- 任务不存在:检查应用模块是否应用了插件,以及任务名称是否对应当前变体。
- 提示找不到配置文件:检查该变体读取的文件位置。
- 提示没有匹配的 client:核对最终 applicationId 与 JSON 中的 package_name。
- 任务成功:检查生成的资源,并确认后续构建使用同一变体。
配置修正后重新构建,例如:
./gradlew :app:assembleRelease
将新 APK 安装到设备后再测试。修改这些原生配置后,只刷新 JavaScript 无法更新已安装 APK 中的资源。
4. 不要仅凭报错就添加手动初始化
Firebase Android SDK 通常通过 FirebaseInitProvider 在应用启动时初始化。没有手写 FirebaseApp.initializeApp(Context),本身并不能说明配置缺失。FirebaseInitProvider 文档说明了它在启动时的初始化职责。
如果包名、配置处理任务和生成资源都已确认正确,但仍报同样的错误,再检查:
- 最终合并后的 AndroidManifest.xml 是否包含 com.google.firebase.provider.FirebaseInitProvider,是否被自定义合并规则移除。
- 通知注册逻辑是否在自定义进程中运行。
- Logcat 中是否有早于当前异常的 Firebase 初始化失败信息。
确认使用了需要自行管理初始化的原生流程后,再考虑显式初始化。仅添加一行调用无法替代缺失的客户端配置资源。
5. 修正 Token 读取和提交逻辑
原代码还有两处需要单独处理:应检查 projectId 是否存在;getExpoPushTokenAsync() 返回的是对象,Token 字符串位于 data 字段。如果后端 pushToken 字段接收字符串,应提交 data。Expo Notifications 文档提供了相应示例。
保留现有 import,在注册函数中可以这样调整:
export async function registerForPushNotifications(): Promise<void> {
if (!Device.isDevice) return;
if (Platform.OS === 'android') {
await Notifications.setNotificationChannelAsync('vendas', {
name: 'Vendas',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
sound: 'default',
});
}
const permissions = await Notifications.getPermissionsAsync();
let status = permissions.status;
if (status !== 'granted') {
status = (await Notifications.requestPermissionsAsync()).status;
}
if (status !== 'granted') return;
const projectId =
Constants.expoConfig?.extra?.eas?.projectId ??
Constants.easConfig?.projectId;
if (!projectId) {
throw new Error('EAS projectId is missing');
}
const { data: pushToken } =
await Notifications.getExpoPushTokenAsync({ projectId });
const authToken = await SecureStorage.getAuthToken();
if (!authToken) return;
await httpRequest('/Client/User/PushToken', {
method: 'POST',
body: { pushToken },
headers: { Authorization: `Bearer ${authToken}` },
});
}
这里的 projectId 是 EAS 项目 ID,应与 Firebase project ID 区分。上述 JavaScript 调整可以修正配置读取和请求数据;FirebaseApp 初始化报错仍需通过前面的原生配置检查解决。
排查时还应补充 expo、expo-notifications、expo-constants 的实际版本,以及 android/build.gradle、android/app/build.gradle 和对应构建日志。仅凭 React Native 0.84.1,无法判断 Expo 依赖组合是否兼容,也无法认定这是某个版本的已知缺陷。
备注:内容仅供参考。
