Android集成Firebase Google登录报API key expired异常如何解决
运行时异常
应用运行抛出如下异常:
FirebaseException: An internal error has occurred. [ API key expired. Please renew the API key. ]
问题背景
Android应用开发中实现Google登录功能,登录流程生成的认证信息存储在Firebase数据库中,该功能此前可正常运行,无相关代码改动的情况下近期突然触发上述异常。
已执行的排查操作如下:
- 在GCP重新生成API密钥,重新下载
google-services.json配置文件后重建项目 - 发现路径
app\build\generated\res\google-services\debug\values下的values.xml文件中配置的API密钥为过期旧版本,尝试修改google_api_key与google_crash_reporting_api_key字段、甚至直接删除该文件,但每次重建项目后旧的过期密钥都会重新生成 - 已确认Firebase控制台中正确配置了应用的SHA-1指纹
- 已在GCP中为对应API密钥配置了合规的访问限制
Google登录功能实现代码如下:
private void loginUserWithGoogle() { GoogleSignInOptions gsio = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(getOwnerActivity().getString(R.string.default_web_client_id)) .requestEmail() .build(); GoogleSignInClient gsic = GoogleSignIn.getClient(getContext(), gsio); Intent sii = gsic.getSignInIntent(); getOwnerActivity().startActivityForResult(sii, GOOGLE_SIGN_IN_REQUEST_CODE); } public void credentialsFromGoogleIntent(@Nullable Intent data) { Task<GoogleSignInAccount> accountTask = GoogleSignIn.getSignedInAccountFromIntent(data); accountTask.addOnCompleteListener(receiveAuthInfo -> { if (receiveAuthInfo.isSuccessful()) { GoogleSignInAccount account = accountTask.getResult(); AuthCredential credential = GoogleAuthProvider.getCredential(account.getIdToken(), null); auth.signInWithCredential(credential). addOnCompleteListener(completeSignIn -> { if (!completeSignIn.isSuccessful()) { Log.w("LoginWindow", "signInWithCedential:Failure", completeSignIn.getException()); return; } CollectionReference reference = db.collection(USER_COLLECTION); FirebaseUser user = auth.getCurrentUser(); Query query = reference.whereEqualTo("uuid", user.getDisplayName()); query.get().addOnCompleteListener(task -> { if (task.getResult().size() <= 0) { UserProfileChangeRequest.Builder build = new UserProfileChangeRequest.Builder(); String userId = UUID.randomUUID().toString(); build.setDisplayName(userId); Task<Void> task1 = user.updateProfile(build.build()); Map<String, Object> userData = new HashMap<>(); userData.put("uuid", userId); userData.put("password", "irrelevant"); Task<DocumentReference> task2 = reference.add(userData); Tasks.whenAll(task1, task2).continueWith(taskContinue -> { Intent intent = new Intent(getOwnerActivity(), MainActivity.class); getOwnerActivity().startActivity(intent); return null; }); } else { Intent intent = new Intent(getOwnerActivity(), MainActivity.class); getOwnerActivity().startActivity(intent); } }); }); } else Log.w("LoginWindow", receiveAuthInfo.getException().toString()); }); }
问题根因
重建后旧密钥反复出现的核心原因是项目中存在多份google-services.json文件,Gradle构建时优先读取了其他模块/构建变体目录下存储的带旧密钥的配置文件,并未使用替换到app模块根目录的新配置文件,最终导致构建生成的资源文件始终写入旧的过期密钥。
注意:build目录下的所有文件都属于构建产物,每次编译时会被重新生成,手动修改、删除该目录下的文件不会对最终构建结果产生任何持久影响。
解决步骤
按以下顺序操作可彻底解决问题:
- 全局搜索项目目录下所有名为
google-services.json的文件并全部删除,不要遗漏debug/release等构建变体专属目录、其他子模块目录下的配置文件 - 执行Android Studio的
Clean Project,完成后再执行Invalidate Caches / Restart清除IDE缓存 - 回到Firebase控制台进入项目设置,重新下载对应应用包名的最新
google-services.json配置文件,确认文件内api_key字段的值为GCP新生成的有效密钥 - 将新的配置文件放到app模块的根目录(即
app/层级,不要放到build目录或其他子目录下) - 检查项目级
build.gradle和app级build.gradle中配置的google-services插件版本,升级到最新稳定版,避免旧版本插件的配置读取bug - 重新执行
Rebuild Project,编译完成后检查app\build\generated\res\google-services\debug\values\values.xml中的google_api_key值,确认已经替换为新密钥后再运行应用即可
内容的提问来源于stack exchange,提问作者Natanoy
相关产品推荐
相关产品推荐

