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

Android CredentialManager弹窗点击外部关闭无回调问题求助

问题描述

使用Java开发安卓游戏,通过CredentialManager唤起Google账号选择弹窗时出现异常行为:

  • 点击弹窗内的「取消」按钮,会正常触发onError回调并抛出GetCredentialCancellationException
  • 点击弹窗外部关闭弹窗时,CancellationSignal.OnCancelListener、onResult、onError均无任何回调触发
  • 该问题仅在**三星Galaxy M53 5G(Android 14,One UI 6.0)**上出现,**三星Galaxy Tab A(2018,Android 10,One UI 2.1)**可正常触发GetCredentialCancellationException

相关代码

登录逻辑代码

public void signIn_credentialManager() {
    String nonce = randomNonce();
    GetCredentialRequest request;
    googleIdOption = new GetGoogleIdOption.Builder()
        .setFilterByAuthorizedAccounts(false)
        .setServerClientId("...")
        .setAutoSelectEnabled(true)
        .setNonce(nonce)
        .build();
    request = new GetCredentialRequest.Builder()
        .addCredentialOption(googleIdOption)
        .build();
    CancellationSignal cancellationSignal = new CancellationSignal();
    cancellationSignal.setOnCancelListener(new CancellationSignal.OnCancelListener() {
        @Override
        public void onCancel() {
            // 此回调从未触发
            log(LOG_TAG, "credentialManager.getCredentialAsync onCancel");
        }
    });
    cancellationSignal.throwIfCanceled();
    log(LOG_TAG, "credentialManager.getCredentialAsync");
    credentialManager.getCredentialAsync(
        context,
        request,
        cancellationSignal,
        executor,
        new CredentialManagerCallback<GetCredentialResponse, GetCredentialException>() {
            @Override
            public void onResult(GetCredentialResponse result) {
                log(LOG_TAG, "CredentialManagerCallback onResult");
                try {
                    ...
                }
                catch (Exception e) {
                    log(LOG_TAG, "CredentialManagerCallback Exception!");
                    e.printStackTrace();
                }
            }
            @Override
            public void onError(@NonNull GetCredentialException e) {
                log(LOG_TAG, "CredentialManagerCallback Error!");
                e.printStackTrace();
            }
        }
    );
}

Android模块build.gradle配置

plugins {
    id "org.jetbrains.kotlin.android" version "1.9.24" apply false
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'

android {
    compileSdk 35
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs('src/main/java')
            aidl.srcDirs('src/main/java')
            renderscript.srcDirs('src/main/java')
            res.srcDirs('res')
            assets.srcDirs('../assets')
            jniLibs.srcDirs('libs')
        }
    }
    packagingOptions {
        resources.with {
            excludes += ['META-INF/robovm/ios/robovm.xml',
                         'META-INF/DEPENDENCIES.txt', 'META-INF/DEPENDENCIES', 'META-INF/dependencies.txt', '**/*.gwt.xml']
            pickFirsts += ['META-INF/LICENSE.txt', 'META-INF/LICENSE', 'META-INF/license.txt', 'META-INF/LGPL2.1',
                           'META-INF/NOTICE.txt', 'META-INF/NOTICE', 'META-INF/notice.txt']
        }
    }
    defaultConfig {
        applicationId 'app.mywebsite.myappname'
        minSdkVersion 24
        targetSdkVersion 35
        versionCode 1
        versionName "1.0.0 test"
//        multiDexEnabled true
    }
    namespace "app.mywebsite.myappname"
    compileOptions {
        sourceCompatibility "11"
        targetCompatibility "11"
        coreLibraryDesugaringEnabled true
    }
    buildTypes {
        debug {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            debuggable true
        }
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            debuggable false
        }
    }
    buildFeatures {
        buildConfig = true
    }
}

repositories {
    google()
}

configurations { natives }

dependencies {
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
    implementation "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
    implementation project(':core')

    natives "com.badlogicgames.gdx:..."

    implementation 'androidx.appcompat:appcompat:1.7.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation platform('com.google.firebase:firebase-bom:33.10.0')
    implementation 'com.google.firebase:firebase-crashlytics:19.4.1'
    implementation 'com.google.firebase:firebase-analytics:22.3.0'

    implementation "androidx.credentials:credentials:1.5.0"
    implementation "androidx.credentials:credentials-play-services-auth:1.5.0"
    implementation "com.google.android.libraries.identity.googleid:googleid:1.1.1"

    implementation "com.google.android.gms:play-services-games-v2:20.1.2"
    implementation 'com.google.android.gms:play-services-auth:21.3.0'
}

tasks.register('run', Exec) {
    def path
    def localProperties = project.file("../local.properties")
    if (localProperties.exists()) {
        Properties properties = new Properties()
        localProperties.withInputStream { instr ->
            properties.load(instr)
        }
        def sdkDir = properties.getProperty('sdk.dir')
        if (sdkDir) {
            path = sdkDir
        } else {
            path = "$System.env.ANDROID_SDK_ROOT"
        }
    } else {
        path = "$System.env.ANDROID_SDK_ROOT"
    }

    def adb = path + "/platform-tools/adb"
    commandLine "$adb", 'shell', 'am', 'start', '-n', 'app.mywebsite.myappname/app.mywebsite.myappname.android.MainActivity'
}

eclipse.project.name = appName + "-android"

核心疑问

  1. CancellationSignal.onCancel是否仅在主动调用.cancel()时才会触发?
  2. 如何处理弹窗外部点击关闭的情况?

解决方案

关于CancellationSignal的说明

CancellationSignal.OnCancelListener确实仅在主动调用cancellationSignal.cancel()时触发,系统弹窗的外部点击关闭并不会自动触发这个信号,这是设计预期。

处理外部点击关闭的方案

方案1:升级Credentials库版本

优先升级androidx.credentials相关依赖到最新稳定版,Google可能已经修复了高版本系统上的回调不一致问题:

implementation "androidx.credentials:credentials:1.6.0"
implementation "androidx.credentials:credentials-play-services-auth:1.6.0"
implementation "com.google.android.libraries.identity.googleid:googleid:1.2.0"

方案2:监听页面生命周期回调

如果升级库后问题仍存在,可通过监听当前页面的生命周期判断弹窗是否被外部关闭:

  1. 新增标记位记录弹窗状态:
private boolean isCredentialPickerShowing = false;
  1. 调用getCredentialAsync时设置标记:
isCredentialPickerShowing = true;
credentialManager.getCredentialAsync(...);
  1. 在Activity的onResume中检查并处理:
@Override
protected void onResume() {
    super.onResume();
    if (isCredentialPickerShowing) {
        // 弹窗已关闭且未触发回调,执行取消逻辑
        handleCredentialCancellation();
        isCredentialPickerShowing = false;
    }
}

private void handleCredentialCancellation() {
    log(LOG_TAG, "Credential picker closed via outside tap");
    // 这里添加取消后的处理逻辑,比如重置状态、提示用户等
}

注意:需要在onResult和onError回调中也重置isCredentialPickerShowing = false;,避免误判。

方案3:自定义弹窗拦截(不推荐)

不建议通过自定义弹窗或拦截触摸事件的方式处理,会破坏系统原生的账号选择体验,优先使用前两种方案。


内容的提问来源于stack exchange,提问作者user2342558

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 20:24:55