You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

新Google Credential Manager抛出TransactionTooLargeException的解决咨询

Google Credential Manager 开启setFilterByAuthorizedAccounts(false)时触发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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 06:36:10