androidgoogle-signinandroid-credential-manager

getCredentialAsync handle prompt dismiss


I'm making a android game with java, using CredentialManager to prompt the user to choose a Google account.

My code works but when the user taps outside the prompt, the prompt closes, but the OnCancelListener callback isn't invoked, nor is onResult or onError.

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() {
            // HERE NEVER TRIGGERED!
            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();
            }
        }
    );
}

build.gradle (Android module):

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"

Maybe CancellationSignal.onCancel is triggered only it I explicitely call .cancel on the request, if so how to handle the dismiss?

I also noticed that if the user click on "cancel" in that google prompt, the GetCredentialCancellationException will be thrown, so I would expect the same exception if the user touches outside that prompt, but instead it does not happen.

I'm using a Samsung Galaxy M53 5G with Android 14, Google Play system update May 1, 2024 and One UI version 6.0.

Edit:

I tried on my Samsung Galaxy Tab A (2018, 10.5) with Android 10 and One UI 2.1 and it throws GetCredentialCancellationException as expected.


Solution

  • What version of Android are you testing that on? Tapping outside of the bottomsheet should call CredentialManagerCallback#onError(exception) and you should get the GetCredentialException exception with the message: "User cancelled the selector"; I just tested that on Android 15 and that is what I got:

    androidx.credentials.exceptions.GetCredentialCancellationException: User cancelled the selector