新Google Credential Manager抛出TransactionTooLargeException的解决咨询
问题背景
我正尝试迁移至Google SignIn with Credential Manager,集成代码如下:
val option = GetGoogleIdOption.Builder() .setFilterByAuthorizedAccounts(false) .setServerClientId(WEB_CLIENT_ID) .setAutoSelectEnabled(false) .build() val request = GetCredentialRequest.Builder() .addCredentialOption(option) .build() val manager = CredentialManager.create(this) lifecycleScope.launch { try { val credential = manager.getCredential(this@MyActivity, request) print(credential) } catch (exception: GetCredentialException) { println(exception) } }
该代码在模拟器正常运行,实体手机上设置setFilterByAuthorizedAccounts(true)也能正常工作,但设为false时调用getCredential会抛出以下异常:
Second failure launching com.android.credentialmanager/.CredentialSelectorActivity, giving up (Ask Gemini) android.os.TransactionTooLargeException: data parcel size 609076 bytes at android.os.BinderProxy.transactNative(Native Method) at android.os.BinderProxy.transact(BinderProxy.java:586) at android.app.IApplicationThread$Stub$Proxy.scheduleTransaction(IApplicationThread.java:1977) at android.app.servertransaction.ClientTransaction.schedule(ClientTransaction.java:178) at com.android.server.wm.ClientLifecycleManager.scheduleTransaction(ClientLifecycleManager.java:65) at com.android.server.wm.ClientLifecycleManager.scheduleTransactionAndLifecycleItems(ClientLifecycleManager.java:143) at com.android.server.wm.ActivityTaskSupervisor.realStartActivityLocked(ActivityTaskSupervisor.java:956) at com.android.server.wm.RootWindowContainer$AttachApplicationHelper.test(RootWindowContainer.java:3805) at com.android.server.wm.RootWindowContainer$AttachApplicationHelper.test(RootWindowContainer.java:3755) at com.android.server.wm.ActivityRecord.forAllActivities(ActivityRecord.java:4743) at com.android.server.wm.WindowContainer.forAllActivities(WindowContainer.java:1831) at com.android.server.wm.WindowContainer.forAllActivities(WindowContainer.java:1825) at com.android.server.wm.RootWindowContainer$AttachApplicationHelper.accept(RootWindowContainer.java:3793) at com.android.server.wm.RootWindowContainer$AttachApplicationHelper.accept(RootWindowContainer.java:3755) at com.android.server.wm.Task.forAllRootTasks(Task.java:3198) at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2212) at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2212) at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2212) at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2212) at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2212) at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2212) at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:2205) at com.android.server.wm.RootWindowContainer$AttachApplicationHelper.process(RootWindowContainer.java:3771) at com.android.server.wm.RootWindowContainer.attachApplication(RootWindowContainer.java:1858) at com.android.server.wm.ActivityTaskManagerService$LocalService.attachApplication(ActivityTaskManagerService.java:6582) at com.android.server.am.ActivityManagerService.finishAttachApplicationInner(ActivityManagerService.java:4904) at com.android.server.am.ActivityManagerService.finishAttachApplication(ActivityManagerService.java:5006) at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2750) at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2798) at android.os.Binder.execTransactInternal(Binder.java:1496) at android.os.Binder.execTransact(Binder.java:1440)
核心原因是关闭授权账户过滤后,Credential Manager尝试加载大量账户数据,导致Parcel大小超过系统500KB上限,触发TransactionTooLargeException。
可行的临时解决办法
1. 保持授权账户过滤(优先推荐)
如果业务场景允许,维持setFilterByAuthorizedAccounts(true)的设置,只显示已授权过当前应用的账户,这样返回的账户数据量较小,不会触发Parcel大小限制。
2. 临时回退到旧版Google Sign-In API
如果必须展示所有账户,可以暂时切换到旧版Google Sign-In API,它的账户选择逻辑不会出现Parcel数据超标的问题:
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(WEB_CLIENT_ID) .requestEmail() .build() val googleSignInClient = GoogleSignIn.getClient(this, gso) // 启动账户选择界面 startActivityForResult(googleSignInClient.signInIntent, RC_SIGN_IN)
3. 捕获异常并执行降级逻辑
在捕获GetCredentialException时,判断底层是否为TransactionTooLargeException,如果是则引导用户切换到其他登录方式:
lifecycleScope.launch { try { val credential = manager.getCredential(this@MyActivity, request) print(credential) } catch (exception: GetCredentialException) { val cause = exception.cause if (cause is TransactionTooLargeException) { // 触发降级处理,比如提示用户切换登录方式 showToast("当前账户过多,请尝试其他登录方式") // 或直接启动旧版Sign-In流程 } else { // 处理其他CredentialManager异常 println(exception) } } }
关于修改事务最大限制的说明
无法通过应用代码修改系统的Binder事务大小限制,这个500KB的上限是Android系统层面的硬限制,第三方应用没有权限调整,只能等待Google修复Credential Manager在加载大量账户时的Parcel数据过大问题。
内容的提问来源于stack exchange,提问作者Ravers
相关产品推荐
相关产品推荐

