1. Zanim zaczniesz
Dowiedz się, jak wdrożyć funkcję Zaloguj się przez Google na Androidzie za pomocą Credential Manager.
Wymagania wstępne
- Podstawowa znajomość języka Kotlin na potrzeby tworzenia aplikacji na Androida.
- Podstawowa znajomość Jetpack Compose (więcej informacji).
Czego się nauczysz
- Utwórz projekt w chmurze Google Cloud i klienty OAuth.
- Wdróż proces logowania za pomocą planszy dolnej.
- Zaimplementuj proces logowania za pomocą przycisku.
Wymagania
- Zainstalowane Android Studio.
- Komputer spełniający wymagania systemowe Androida Studio i emulatora.
- Zainstalowany pakiet Java Development Kit (JDK).
2. Tworzenie projektu w Android Studio
Aby rozpocząć, utwórz nowy projekt w Android Studio:
- Otwórz Android Studio i kliknij Nowy projekt.

- Kliknij kolejno Telefon i tablet > Pusta aktywność i Dalej.

- Skonfiguruj ustawienia projektu:
- Nazwa: wybierz nazwę projektu.
- Nazwa pakietu: użyj domyślnej nazwy lub wybierz własną.
- Minimalny pakiet SDK: wybierz najnowszą stabilną wersję lub > Android 14.

- Kliknij Zakończ i poczekaj na zakończenie początkowej kompilacji projektu.

3. Konfigurowanie projektu Google Cloud
Tworzenie projektu Google Cloud
- Otwórz konsolę Google Cloud i wybierz lub utwórz projekt.

- Otwórz Interfejsy API i usługi > Ekran zgody OAuth.

- Kliknij Rozpocznij i wypełnij wymagane pola:
- Nazwa aplikacji: użyj nazwy aplikacji na Androida.
- Adres e-mail pomocy dla użytkowników: wybierz konto Google.
- Odbiorcy: kliknij Zewnętrzni.
- Informacje kontaktowe: wpisz swój adres e-mail.

- Zapoznaj się z zasadami dotyczącymi danych użytkownika w usługach interfejsu API Google i kliknij Utwórz.

Konfigurowanie klientów OAuth
Aby uzyskać identyfikatory klienta na potrzeby uwierzytelniania, musisz utworzyć klienta internetowego i klienta Androida w konsoli Google Cloud.
- Klient Androida: zabezpiecza żądania przez weryfikację nazwy pakietu i podpisu SHA-1 aplikacji.
- Klient internetowy: działa jako klient backendu usługi Logowanie przez Google.
Tworzenie klienta OAuth 2.0 na Androida
- Na stronie Klienci kliknij Utwórz klienta i jako Typ aplikacji wybierz Android.

- Wpisz nazwę pakietu aplikacji (zgodną z wierszem 1 w
MainActivity.kt). - Wygeneruj podpis SHA-1. Otwórz terminal Android Studio i uruchom:macOS/Linux:
Windows:keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
keytool -list -v -keystore "C:\Users\USERNAME\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
- Skopiuj odcisk cyfrowy SHA-1 z wyniku polecenia, wklej go w polu Odcisk cyfrowy SHA-1 w konsoli i kliknij Utwórz.

Tworzenie klienta internetowego OAuth 2.0
- Ponownie kliknij Utwórz klienta i jako Typ aplikacji wybierz Aplikacja internetowa.
- Nadaj nazwę klientowi internetowemu, pozostaw puste pola URL/Pochodzenie i kliknij Utwórz.

- Skopiuj wygenerowany identyfikator klienta z okna potwierdzenia. Użyjesz go w kodzie Kotlin.

4. Konfigurowanie urządzenia wirtualnego z Androidem (AVD)
Aby przetestować aplikację, możesz użyć fizycznego urządzenia z Androidem lub urządzenia wirtualnego z Androidem (AVD).
Tworzenie i uruchamianie AVD
- W Android Studio otwórz Menedżera urządzeń, kliknij Utwórz urządzenie wirtualne (lub ikonę +) i wybierz Telefon średniej wielkości.
- Wybierz najnowszą stabilną wersję jako obraz systemu i kliknij Zakończ.
- Uruchom emulator, klikając ikonę Odtwórz/Uruchom obok urządzenia.

Logowanie się na konto Google na urządzeniu
- W emulatorze otwórz aplikację Ustawienia i kliknij Google.
- Kliknij Zaloguj się na konto Google i postępuj zgodnie z instrukcjami.

5. Dodawanie zależności
Dodaj do projektu biblioteki wymagane do uwierzytelniania i integracji z Google ID:
- Otwórz Plik > Struktura projektu > Zależności > aplikacja.
- Kliknij + > Library Dependency (Zależność biblioteki), wyszukaj
com.google.android.libraries.identity.googleid:googleidi wybierz najnowszą wersję (np.1.1.1). - Ponownie kliknij + > Library Dependency (Zależność biblioteki), wyszukaj
play-services-authi wybierz bibliotekę z identyfikatorem grupycom.google.android.gms. - Aby zastosować zmiany i zsynchronizować projekt, kliknij OK.

6. Wdrażanie procesu planszy dolnej

Proces Bottom Sheet korzysta z interfejsu Credential Manager API, aby zapewnić użytkownikom uproszczony sposób logowania się w aplikacji za pomocą kont Google na Androidzie. Ten proces, zaprojektowany z myślą o szybkości i wygodzie, zwłaszcza dla powracających użytkowników, powinien być uruchamiany przy uruchomieniu aplikacji.
Tworzenie żądania logowania
- Aby rozpocząć, otwórz
MainActivity.kti usuń domyślne funkcjeGreeting()iGreetingPreview(). - Dodaj te instrukcje importu po dotychczasowych, zaczynając od wiersza 3:
import android.content.Context import android.os.Build import android.util.Log import android.widget.Toast import androidx.annotation.RequiresApi import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.credentials.CredentialManager import androidx.credentials.CustomCredential import androidx.credentials.GetCredentialRequest import androidx.credentials.exceptions.GetCredentialCancellationException import androidx.credentials.exceptions.GetCredentialCustomException import androidx.credentials.exceptions.GetCredentialException import androidx.credentials.exceptions.NoCredentialException import com.google.android.libraries.identity.googleid.GetGoogleIdOption import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential import com.google.android.libraries.identity.googleid.GoogleIdTokenParsingException import java.security.SecureRandom import java.util.Base64 import kotlinx.coroutines.delay import kotlinx.coroutines.launch const val TAG = "MainActivity" - Dodaj tę funkcję typu „composable” pod klasą
MainActivityw plikuMainActivity.kt:@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @Composable fun BottomSheet(webClientId: String) { val context = LocalContext.current // LaunchedEffect is used to run a suspend function when the composable is first launched. LaunchedEffect(Unit) { // Create a Google ID option with filtering by authorized accounts enabled. val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder() .setFilterByAuthorizedAccounts(true) .setServerClientId(webClientId) .setNonce(generateSecureRandomNonce()) .build() // Create a credential request with the Google ID option. val request: GetCredentialRequest = GetCredentialRequest.Builder() .addCredentialOption(googleIdOption) .build() // Attempt to sign in with the created request using an authorized account val e = signIn(request, context) // If the sign-in fails with NoCredentialException, there are no authorized accounts. // In this case, we attempt to sign in again with filtering disabled. if (e is NoCredentialException) { val googleIdOptionFalse: GetGoogleIdOption = GetGoogleIdOption.Builder() .setFilterByAuthorizedAccounts(false) .setServerClientId(webClientId) .setNonce(generateSecureRandomNonce()) .build() val requestFalse: GetCredentialRequest = GetCredentialRequest.Builder() .addCredentialOption(googleIdOptionFalse) .build() //We will build out this function in a moment signIn(requestFalse, context) } } } //This function is used to generate a secure nonce to pass in with our request fun generateSecureRandomNonce(byteLength: Int = 32): String { val randomBytes = ByteArray(byteLength) SecureRandom.getInstanceStrong().nextBytes(randomBytes) return Base64.getUrlEncoder().withoutPadding().encodeToString(randomBytes) }
Analiza kodu
LaunchedEffect(Unit): natychmiast uruchamia proces logowania, gdy element kompozycyjny jest wyświetlany po raz pierwszy.GetGoogleIdOption.Builder(): konfiguruje żądanie tokena identyfikatora Google.setFilterByAuthorizedAccounts(true): najpierw próbuje zalogować się w sposób cichy, filtrując konta, które użytkownik już autoryzował w tej aplikacji, co minimalizuje problemy dla powracających użytkowników.setNonce(...): przekazuje bezpieczny losowy identyfikator nonce wygenerowany dla każdego żądania przezgenerateSecureRandomNonce(), aby zapobiec atakom typu replay.
signIn(request, context): wykonuje żądanie. Jeśli się nie powiedzie (NoCredentialExceptionoznacza, że nie ma wcześniej autoryzowanego konta), proces wraca dosetFilterByAuthorizedAccounts(false), aby umożliwić użytkownikowi wybranie dowolnego konta Google zalogowanego na urządzeniu.
Wysyłanie prośby o zalogowanie
Po utworzeniu prośby o zalogowanie możesz użyć Menedżera danych logowania, aby dokończyć proces logowania. Utwórz funkcję o nazwie signIn, która wykonuje żądanie i obsługuje typowe wyjątki, które mogą wystąpić.
Dodaj tę funkcję poniżej funkcji BottomSheet w pliku MainActivity.kt:
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
suspend fun signIn(request: GetCredentialRequest, context: Context): Exception? {
val credentialManager = CredentialManager.create(context)
val failureMessage = "Sign in failed!"
//using delay() here helps prevent NoCredentialException when the BottomSheet Flow is triggered
//on the initial running of our app
delay(250)
return try {
// The getCredential is called to request a credential from Credential Manager.
val result = credentialManager.getCredential(
request = request,
context = context,
)
Log.i(TAG, result.toString())
val credential = result.credential
if (credential is CustomCredential &&
credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data)
Log.i(TAG, "Signed in as: ${googleIdTokenCredential.id}")
}
Toast.makeText(context, "Sign in successful!", Toast.LENGTH_SHORT).show()
Log.i(TAG, "(☞゚ヮ゚)☞ Sign in Successful! ☜(゚ヮ゚☜)")
null
} catch (e: GoogleIdTokenParsingException) {
Toast.makeText(context, failureMessage, Toast.LENGTH_SHORT).show()
Log.e(TAG, failureMessage + ": Issue with parsing received GoogleIdToken", e)
e
} catch (e: NoCredentialException) {
Toast.makeText(context, failureMessage, Toast.LENGTH_SHORT).show()
Log.e(TAG, failureMessage + ": No credentials found", e)
e
} catch (e: GetCredentialCancellationException) {
Toast.makeText(context, "Sign-in cancelled", Toast.LENGTH_SHORT).show()
Log.e(TAG, failureMessage + ": Sign-in was cancelled", e)
e
} catch (e: GetCredentialCustomException) {
Toast.makeText(context, failureMessage, Toast.LENGTH_SHORT).show()
Log.e(TAG, failureMessage + ": Issue with custom credential request", e)
e
} catch (e: GetCredentialException) {
Toast.makeText(context, failureMessage, Toast.LENGTH_SHORT).show()
Log.e(TAG, failureMessage + ": Failure getting credentials", e)
e
}
}
Analiza kodu
credentialManager.getCredential(...): wywołuje interfejs Credential Manager API, aby wyświetlić planszę dolną lub okno wyboru konta systemowego.delay(250): wstrzymuje działanie na krótko, aby zapobiec sytuacji wyścigu, gdy arkusz u dołu jest wywoływany natychmiast po uruchomieniu aplikacji, zanim usługa Credential Manager zakończy inicjowanie.- Obsługa wyjątków: przechwytuje i rejestruje typowe błędy związane z danymi logowania (np. anulowanie, brak danych logowania lub problemy z parsowaniem tokena) oraz wyświetla użytkownikowi powiadomienia.
Uruchamianie przepływu planszy dolnej
Zaktualizuj klasę MainActivity, aby wywoływać BottomSheet() podczas uruchamiania. Zastąp YOUR_CLIENT_ID_HERE identyfikatorem klienta aplikacji internetowej:
class MainActivity : ComponentActivity() {
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//replace with your own web client ID from Google Cloud Console
val webClientId = "YOUR_CLIENT_ID_HERE"
setContent {
//ExampleTheme - this is derived from the name of the project not any added library
//e.g. if this project was named "Testing" it would be generated as TestingTheme
ExampleTheme {
Surface(
modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background,
) {
//This will trigger on launch
BottomSheet(webClientId)
}
}
}
}
}
Zapisz projekt (Plik > Zapisz) i uruchom aplikację:
- Naciśnij przycisk uruchamiania:

- Gdy aplikacja zostanie uruchomiona na emulatorze, powinien pojawić się arkusz z prośbą o zalogowanie. Aby przetestować przepływ, kliknij Dalej.

- Powinno pojawić się powiadomienie potwierdzające, że logowanie się powiodło.

7. Wdrażanie automatyzacji przycisku

Przepływ przycisku zapewnia użytkownikom wyraźną opcję zalogowania się lub zarejestrowania. Używanie standardowych elementów marki zapewnia spójność informacji. Używaj wstępnie zatwierdzonych zasobów, które są zgodne z wytycznymi dotyczącymi promowania marki Zaloguj się przez Google.
Dodawanie ikony marki
- Pobierz zasoby marki tutaj i wyodrębnij plik ZIP.
- Kopiuj
signin-assets/Android/png@2x/neutral/android_neutral_sq_SI@2x.png. - W Android Studio wklej plik do folderu res > drawable, zmień jego nazwę na
siwg_button.pngi kliknij OK.
Kod przepływu przycisku
Ten proces ponownie wykorzystuje tę samą funkcję pomocniczą signIn, ale przekazuje GetSignInWithGoogleOption zamiast GetGoogleIdOption. W przeciwieństwie do przepływu Bottom Sheet przepływ z wyraźnym przyciskiem nie filtruje wstępnie ani nie wyświetla automatycznie prośby o podanie zapisanych danych logowania lub kluczy dostępu. Wklej tę funkcję typu „composable” pod funkcją BottomSheet:
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@Composable
fun ButtonUI(webClientId: String) {
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
val onClick: () -> Unit = {
val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption
.Builder(serverClientId = webClientId)
.setNonce(generateSecureRandomNonce())
.build()
val request: GetCredentialRequest = GetCredentialRequest.Builder()
.addCredentialOption(signInWithGoogleOption)
.build()
coroutineScope.launch {
signIn(request, context)
}
}
Image(
painter = painterResource(id = R.drawable.siwg_button),
contentDescription = "",
modifier = Modifier
.fillMaxSize()
.clickable(enabled = true, onClick = onClick)
)
}
Analiza kodu
GetSignInWithGoogleOption: w przeciwieństwie do przepływu arkusza u dołu przepływ z wyraźnym przyciskiem używa tej opcji, aby poprosić użytkowników o wybranie konta Google bez automatycznego filtrowania.coroutineScope.launch: uruchamia współprogram, aby asynchronicznie wykonać funkcję zawieszaniasignInpo kliknięciu przycisku.Image: wyświetla element rysowalnysiwg_buttonz logo marki i dołącza odbiornik kliknięć, aby wywołać przepływ.
Dodawanie przycisku do układu interfejsu
Zaktualizuj układ MainActivity, aby wyświetlać automatyczne BottomSheet i jawne ButtonUI wyrównane pionowo:
class MainActivity : ComponentActivity() {
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//replace with your own web client ID from Google Cloud Console
val webClientId = "YOUR_CLIENT_ID_HERE"
setContent {
//ExampleTheme - this is derived from the name of the project not any added library
//e.g. if this project was named "Testing" it would be generated as TestingTheme
ExampleTheme {
Surface(
modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background,
) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
//This will trigger on launch
BottomSheet(webClientId)
//This requires the user to press the button
ButtonUI(webClientId)
}
}
}
}
}
}
Testowanie automatyzacji przycisku
- Uruchom aplikację.
- Zamknij początkową planszę dolną, klikając poza jej obszarem.
- Kliknij przycisk Zaloguj się przez Google, aby otworzyć okno logowania, i wybierz swoje konto.

- Sprawdź wynik: w Logcat potwierdź wydruk nazwy użytkownika lub adresu e-mail.
8. Podsumowanie
Gratulacje! Udało Ci się wdrożyć logowanie się przez Google za pomocą Menedżera danych logowania na Androidzie.
Dodatkowe materiały
- Dokumentacja Menedżera danych logowania na Androidzie
- Przewodnik rozwiązywania problemów z Credential Managerem
- Najczęstsze pytania dotyczące Menedżera danych logowania
- Pomoc na StackOverflow
Pełny kod pliku MainActivity.kt
Oto pełny kod pliku MainActivity.kt:
package com.example.example
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.example.example.ui.theme.ExampleTheme
import android.content.ContentValues.TAG
import android.content.Context
import android.util.Log
import android.widget.Toast
import androidx.credentials.exceptions.GetCredentialException
import androidx.compose.foundation.clickable
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.credentials.CredentialManager
import androidx.credentials.exceptions.GetCredentialCancellationException
import androidx.credentials.exceptions.GetCredentialCustomException
import androidx.credentials.exceptions.NoCredentialException
import androidx.credentials.GetCredentialRequest
import com.google.android.libraries.identity.googleid.GetGoogleIdOption
import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption
import com.google.android.libraries.identity.googleid.GoogleIdTokenParsingException
import java.security.SecureRandom
import java.util.Base64
import kotlinx.coroutines.CoroutineScope
import androidx.compose.runtime.LaunchedEffect
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//replace with your own web client ID from Google Cloud Console
val webClientId = "YOUR_CLIENT_ID_HERE"
setContent {
//ExampleTheme - this is derived from the name of the project not any added library
//e.g. if this project was named "Testing" it would be generated as TestingTheme
ExampleTheme {
Surface(
modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background,
) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
//This will trigger on launch
BottomSheet(webClientId)
//This requires the user to press the button
ButtonUI(webClientId)
}
}
}
}
}
}
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@Composable
fun BottomSheet(webClientId: String) {
val context = LocalContext.current
// LaunchedEffect is used to run a suspend function when the composable is first launched.
LaunchedEffect(Unit) {
// Create a Google ID option with filtering by authorized accounts enabled.
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(true)
.setServerClientId(webClientId)
.setNonce(generateSecureRandomNonce())
.build()
// Create a credential request with the Google ID option.
val request: GetCredentialRequest = GetCredentialRequest.Builder()
.addCredentialOption(googleIdOption)
.build()
// Attempt to sign in with the created request using an authorized account
val e = signIn(request, context)
// If the sign-in fails with NoCredentialException, there are no authorized accounts.
// In this case, we attempt to sign in again with filtering disabled.
if (e is NoCredentialException) {
val googleIdOptionFalse: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(false)
.setServerClientId(webClientId)
.setNonce(generateSecureRandomNonce())
.build()
val requestFalse: GetCredentialRequest = GetCredentialRequest.Builder()
.addCredentialOption(googleIdOptionFalse)
.build()
signIn(requestFalse, context)
}
}
}
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@Composable
fun ButtonUI(webClientId: String) {
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
val onClick: () -> Unit = {
val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption
.Builder(serverClientId = webClientId)
.setNonce(generateSecureRandomNonce())
.build()
val request: GetCredentialRequest = GetCredentialRequest.Builder()
.addCredentialOption(signInWithGoogleOption)
.build()
coroutineScope.launch {
signIn(request, context)
}
}
Image(
painter = painterResource(id = R.drawable.siwg_button),
contentDescription = "",
modifier = Modifier
.fillMaxSize()
.clickable(onClick = onClick)
)
}
fun generateSecureRandomNonce(byteLength: Int = 32): String {
val randomBytes = ByteArray(byteLength)
SecureRandom.getInstanceStrong().nextBytes(randomBytes)
return Base64.getUrlEncoder().withoutPadding().encodeToString(randomBytes)
}
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
suspend fun signIn(request: GetCredentialRequest, context: Context): Exception? {
val credentialManager = CredentialManager.create(context)
val failureMessage = "Sign in failed!"
//using delay() here helps prevent NoCredentialException when the BottomSheet Flow is triggered
//on the initial running of our app
delay(250)
return try {
// The getCredential is called to request a credential from Credential Manager.
val result = credentialManager.getCredential(
request = request,
context = context,
)
Log.i(TAG, result.toString())
val credential = result.credential
if (credential is CustomCredential &&
credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data)
Log.i(TAG, "Signed in as: ${googleIdTokenCredential.id}")
}
Toast.makeText(context, "Sign in successful!", Toast.LENGTH_SHORT).show()
Log.i(TAG, "(☞゚ヮ゚)☞ Sign in Successful! ☜(゚ヮ゚☜)")
null
} catch (e: GoogleIdTokenParsingException) {
Toast.makeText(context, failureMessage, Toast.LENGTH_SHORT).show()
Log.e(TAG, failureMessage + ": Issue with parsing received GoogleIdToken", e)
e
} catch (e: NoCredentialException) {
Toast.makeText(context, failureMessage, Toast.LENGTH_SHORT).show()
Log.e(TAG, failureMessage + ": No credentials found", e)
e
} catch (e: GetCredentialCancellationException) {
Toast.makeText(context, "Sign-in cancelled", Toast.LENGTH_SHORT).show()
Log.e(TAG, failureMessage + ": Sign-in was cancelled", e)
e
} catch (e: GetCredentialCustomException) {
Toast.makeText(context, failureMessage, Toast.LENGTH_SHORT).show()
Log.e(TAG, failureMessage + ": Issue with custom credential request", e)
e
} catch (e: GetCredentialException) {
Toast.makeText(context, failureMessage, Toast.LENGTH_SHORT).show()
Log.e(TAG, failureMessage + ": Failure getting credentials", e)
e
}
}