diff --git a/CredentialManager/app/build.gradle b/CredentialManager/app/build.gradle
index ebddd33..bb498a4 100644
--- a/CredentialManager/app/build.gradle
+++ b/CredentialManager/app/build.gradle
@@ -32,10 +32,11 @@ keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
namespace 'com.google.credentialmanager.sample'
compileSdk 34
+ compileSdkPreview "VanillaIceCream"
defaultConfig {
applicationId "com.google.credentialmanager.sample"
minSdk 21
- targetSdk 34
+ targetSdkPreview "VanillaIceCream"
versionCode 1
versionName "1.0"
@@ -100,8 +101,8 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
- implementation 'androidx.credentials:credentials-play-services-auth:1.3.0-alpha01'
- implementation 'androidx.credentials:credentials:1.3.0-alpha01'
+ implementation 'androidx.credentials:credentials-play-services-auth:1.5.0-alpha02'
+ implementation 'androidx.credentials:credentials:1.5.0-alpha02'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
diff --git a/CredentialManager/app/src/main/java/com/google/credentialmanager/sample/SignInFragment.kt b/CredentialManager/app/src/main/java/com/google/credentialmanager/sample/SignInFragment.kt
index 494f7c4..09277b0 100644
--- a/CredentialManager/app/src/main/java/com/google/credentialmanager/sample/SignInFragment.kt
+++ b/CredentialManager/app/src/main/java/com/google/credentialmanager/sample/SignInFragment.kt
@@ -28,7 +28,9 @@ import androidx.credentials.GetCredentialRequest
import androidx.credentials.GetPasswordOption
import androidx.credentials.GetPublicKeyCredentialOption
import androidx.credentials.PasswordCredential
+import androidx.credentials.PendingGetCredentialRequest
import androidx.credentials.PublicKeyCredential
+import androidx.credentials.pendingGetCredentialRequest
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.google.credentialmanager.sample.databinding.FragmentSignInBinding
@@ -64,27 +66,67 @@ class SignInFragment : Fragment() {
credentialManager = CredentialManager.create(requireActivity())
- binding.signInWithSavedCredentials.setOnClickListener(signInWithSavedCredentials())
+ val getCredentialRequest = configureGetCredentialRequest()
+
+ configureAutofill(getCredentialRequest)
+
+ binding.signInWithSavedCredentials.setOnClickListener(
+ signInWithSavedCredentials(
+ getCredentialRequest
+ )
+ )
+ }
+
+ private fun configureAutofill(getCredentialRequest: GetCredentialRequest) {
+ binding.textUsername
+ .pendingGetCredentialRequest = PendingGetCredentialRequest(
+ getCredentialRequest
+ ) { response ->
+ if (response.credential is PublicKeyCredential) {
+ DataProvider.setSignedInThroughPasskeys(true)
+ }
+ if (response.credential is PasswordCredential) {
+ DataProvider.setSignedInThroughPasskeys(false)
+ }
+ showHome()
+ }
+ }
+
+ private fun configureGetCredentialRequest(): GetCredentialRequest {
+ val getPublicKeyCredentialOption =
+ GetPublicKeyCredentialOption(fetchAuthJsonFromServer(), null)
+ val getPasswordOption = GetPasswordOption()
+ val getCredentialRequest = GetCredentialRequest(
+ listOf(
+ getPublicKeyCredentialOption,
+ getPasswordOption
+ )
+ )
+ return getCredentialRequest
}
- private fun signInWithSavedCredentials(): View.OnClickListener {
+ private fun signInWithSavedCredentials(getCredentialRequest: GetCredentialRequest): View.OnClickListener {
return View.OnClickListener {
lifecycleScope.launch {
configureViews(View.VISIBLE, false)
- val data = getSavedCredentials()
+ val data = getSavedCredentials(getCredentialRequest)
configureViews(View.INVISIBLE, true)
data?.let {
- sendSignInResponseToServer()
- listener.showHome()
+ showHome()
}
}
}
}
+ private fun showHome() {
+ sendSignInResponseToServer()
+ listener.showHome()
+ }
+
private fun configureViews(visibility: Int, flag: Boolean) {
configureProgress(visibility)
binding.signInWithSavedCredentials.isEnabled = flag
@@ -103,19 +145,12 @@ class SignInFragment : Fragment() {
return true
}
- private suspend fun getSavedCredentials(): String? {
- val getPublicKeyCredentialOption =
- GetPublicKeyCredentialOption(fetchAuthJsonFromServer(), null)
- val getPasswordOption = GetPasswordOption()
+ private suspend fun getSavedCredentials(getCredentialRequest: GetCredentialRequest): String? {
+
val result = try {
credentialManager.getCredential(
requireActivity(),
- GetCredentialRequest(
- listOf(
- getPublicKeyCredentialOption,
- getPasswordOption
- )
- )
+ getCredentialRequest,
)
} catch (e: Exception) {
configureViews(View.INVISIBLE, true)
diff --git a/CredentialManager/app/src/main/java/com/google/credentialmanager/sample/SignUpFragment.kt b/CredentialManager/app/src/main/java/com/google/credentialmanager/sample/SignUpFragment.kt
index 36119a6..93974c1 100644
--- a/CredentialManager/app/src/main/java/com/google/credentialmanager/sample/SignUpFragment.kt
+++ b/CredentialManager/app/src/main/java/com/google/credentialmanager/sample/SignUpFragment.kt
@@ -215,23 +215,28 @@ class SignUpFragment : Fragment() {
// WebAuthn spec using e.domError
"An error occurred while creating a passkey, please check logs for additional details."
}
+
is CreateCredentialCancellationException -> {
// The user intentionally canceled the operation and chose not
// to register the credential.
"The user intentionally canceled the operation and chose not to register the credential. Check logs for additional details."
}
+
is CreateCredentialInterruptedException -> {
// Retry-able error. Consider retrying the call.
"The operation was interrupted, please retry the call. Check logs for additional details."
}
+
is CreateCredentialProviderConfigurationException -> {
// Your app is missing the provider configuration dependency.
// Most likely, you're missing "credentials-play-services-auth".
"Your app is missing the provider configuration dependency. Check logs for additional details."
}
+
is CreateCredentialUnknownException -> {
"An unknown error occurred while creating passkey. Check logs for additional details."
}
+
is CreateCredentialCustomException -> {
// You have encountered an error from a 3rd-party SDK. If you
// make the API call with a request object that's a subclass of
@@ -241,6 +246,7 @@ class SignUpFragment : Fragment() {
// exception.
"An unknown error occurred from a 3rd party SDK. Check logs for additional details."
}
+
else -> {
Log.w("Auth", "Unexpected exception type ${e::class.java.name}")
"An unknown error occurred."
diff --git a/CredentialManager/app/src/main/res/layout/fragment_sign_in.xml b/CredentialManager/app/src/main/res/layout/fragment_sign_in.xml
index 289eb17..1569af4 100644
--- a/CredentialManager/app/src/main/res/layout/fragment_sign_in.xml
+++ b/CredentialManager/app/src/main/res/layout/fragment_sign_in.xml
@@ -28,7 +28,7 @@
android:layout_marginTop="20dp"
android:gravity="center"
android:padding="16dp"
- android:text="Sign in"
+ android:text="@string/sign_in"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
@@ -39,7 +39,7 @@
android:id="@+id/circularProgressIndicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
+ android:layout_marginTop="20dp"
android:indeterminate="true"
android:visibility="invisible"
app:layout_constraintCircleRadius="0dp"
@@ -55,8 +55,8 @@
android:id="@+id/textProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginBottom="10dp"
- android:text="operation in progress... "
+ android:layout_marginBottom="16dp"
+ android:text="@string/operation_in_progress"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@+id/circularProgressIndicator"
app:layout_constraintStart_toEndOf="@+id/circularProgressIndicator"
@@ -66,11 +66,21 @@
android:id="@+id/sign_in_with_savedCredentials"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:text="Sign in with passkey/saved password"
+ android:layout_marginTop="40dp"
+ android:text="@string/sign_in_with_passkey_saved_password"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/circularProgressIndicator" />
+
+
diff --git a/CredentialManager/app/src/main/res/values/strings.xml b/CredentialManager/app/src/main/res/values/strings.xml
index f9dbd19..eb63159 100644
--- a/CredentialManager/app/src/main/res/values/strings.xml
+++ b/CredentialManager/app/src/main/res/values/strings.xml
@@ -25,4 +25,8 @@
Hello first fragment
Hello second fragment. Arg: %1$s
+ Sign in
+ operation in progress...
+ Sign in with passkey/saved password
+ Autofill saved credentials