Skip to content

Commit e286fd2

Browse files
authored
Merge pull request #87 from android/autofill_changes
Added autofill integration
2 parents d6bc2ef + 2647ef2 commit e286fd2

File tree

5 files changed

+80
-24
lines changed

5 files changed

+80
-24
lines changed

CredentialManager/app/build.gradle

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
3232
android {
3333
namespace 'com.google.credentialmanager.sample'
3434
compileSdk 34
35+
compileSdkPreview "VanillaIceCream"
3536
defaultConfig {
3637
applicationId "com.google.credentialmanager.sample"
3738
minSdk 21
38-
targetSdk 34
39+
targetSdkPreview "VanillaIceCream"
3940
versionCode 1
4041
versionName "1.0"
4142

@@ -100,8 +101,8 @@ dependencies {
100101
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
101102
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
102103

103-
implementation 'androidx.credentials:credentials-play-services-auth:1.3.0-alpha01'
104-
implementation 'androidx.credentials:credentials:1.3.0-alpha01'
104+
implementation 'androidx.credentials:credentials-play-services-auth:1.5.0-alpha02'
105+
implementation 'androidx.credentials:credentials:1.5.0-alpha02'
105106

106107
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3"
107108
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"

CredentialManager/app/src/main/java/com/google/credentialmanager/sample/SignInFragment.kt

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ import androidx.credentials.GetCredentialRequest
2828
import androidx.credentials.GetPasswordOption
2929
import androidx.credentials.GetPublicKeyCredentialOption
3030
import androidx.credentials.PasswordCredential
31+
import androidx.credentials.PendingGetCredentialRequest
3132
import androidx.credentials.PublicKeyCredential
33+
import androidx.credentials.pendingGetCredentialRequest
3234
import androidx.fragment.app.Fragment
3335
import androidx.lifecycle.lifecycleScope
3436
import com.google.credentialmanager.sample.databinding.FragmentSignInBinding
@@ -64,27 +66,67 @@ class SignInFragment : Fragment() {
6466

6567
credentialManager = CredentialManager.create(requireActivity())
6668

67-
binding.signInWithSavedCredentials.setOnClickListener(signInWithSavedCredentials())
69+
val getCredentialRequest = configureGetCredentialRequest()
70+
71+
configureAutofill(getCredentialRequest)
72+
73+
binding.signInWithSavedCredentials.setOnClickListener(
74+
signInWithSavedCredentials(
75+
getCredentialRequest
76+
)
77+
)
78+
}
79+
80+
private fun configureAutofill(getCredentialRequest: GetCredentialRequest) {
81+
binding.textUsername
82+
.pendingGetCredentialRequest = PendingGetCredentialRequest(
83+
getCredentialRequest
84+
) { response ->
85+
if (response.credential is PublicKeyCredential) {
86+
DataProvider.setSignedInThroughPasskeys(true)
87+
}
88+
if (response.credential is PasswordCredential) {
89+
DataProvider.setSignedInThroughPasskeys(false)
90+
}
91+
showHome()
92+
}
93+
}
94+
95+
private fun configureGetCredentialRequest(): GetCredentialRequest {
96+
val getPublicKeyCredentialOption =
97+
GetPublicKeyCredentialOption(fetchAuthJsonFromServer(), null)
98+
val getPasswordOption = GetPasswordOption()
99+
val getCredentialRequest = GetCredentialRequest(
100+
listOf(
101+
getPublicKeyCredentialOption,
102+
getPasswordOption
103+
)
104+
)
105+
return getCredentialRequest
68106
}
69107

70-
private fun signInWithSavedCredentials(): View.OnClickListener {
108+
private fun signInWithSavedCredentials(getCredentialRequest: GetCredentialRequest): View.OnClickListener {
71109
return View.OnClickListener {
72110

73111
lifecycleScope.launch {
74112
configureViews(View.VISIBLE, false)
75113

76-
val data = getSavedCredentials()
114+
val data = getSavedCredentials(getCredentialRequest)
77115

78116
configureViews(View.INVISIBLE, true)
79117

80118
data?.let {
81-
sendSignInResponseToServer()
82-
listener.showHome()
119+
showHome()
83120
}
84121
}
85122
}
86123
}
87124

125+
private fun showHome() {
126+
sendSignInResponseToServer()
127+
listener.showHome()
128+
}
129+
88130
private fun configureViews(visibility: Int, flag: Boolean) {
89131
configureProgress(visibility)
90132
binding.signInWithSavedCredentials.isEnabled = flag
@@ -103,19 +145,12 @@ class SignInFragment : Fragment() {
103145
return true
104146
}
105147

106-
private suspend fun getSavedCredentials(): String? {
107-
val getPublicKeyCredentialOption =
108-
GetPublicKeyCredentialOption(fetchAuthJsonFromServer(), null)
109-
val getPasswordOption = GetPasswordOption()
148+
private suspend fun getSavedCredentials(getCredentialRequest: GetCredentialRequest): String? {
149+
110150
val result = try {
111151
credentialManager.getCredential(
112152
requireActivity(),
113-
GetCredentialRequest(
114-
listOf(
115-
getPublicKeyCredentialOption,
116-
getPasswordOption
117-
)
118-
)
153+
getCredentialRequest,
119154
)
120155
} catch (e: Exception) {
121156
configureViews(View.INVISIBLE, true)

CredentialManager/app/src/main/java/com/google/credentialmanager/sample/SignUpFragment.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,23 +215,28 @@ class SignUpFragment : Fragment() {
215215
// WebAuthn spec using e.domError
216216
"An error occurred while creating a passkey, please check logs for additional details."
217217
}
218+
218219
is CreateCredentialCancellationException -> {
219220
// The user intentionally canceled the operation and chose not
220221
// to register the credential.
221222
"The user intentionally canceled the operation and chose not to register the credential. Check logs for additional details."
222223
}
224+
223225
is CreateCredentialInterruptedException -> {
224226
// Retry-able error. Consider retrying the call.
225227
"The operation was interrupted, please retry the call. Check logs for additional details."
226228
}
229+
227230
is CreateCredentialProviderConfigurationException -> {
228231
// Your app is missing the provider configuration dependency.
229232
// Most likely, you're missing "credentials-play-services-auth".
230233
"Your app is missing the provider configuration dependency. Check logs for additional details."
231234
}
235+
232236
is CreateCredentialUnknownException -> {
233237
"An unknown error occurred while creating passkey. Check logs for additional details."
234238
}
239+
235240
is CreateCredentialCustomException -> {
236241
// You have encountered an error from a 3rd-party SDK. If you
237242
// make the API call with a request object that's a subclass of
@@ -241,6 +246,7 @@ class SignUpFragment : Fragment() {
241246
// exception.
242247
"An unknown error occurred from a 3rd party SDK. Check logs for additional details."
243248
}
249+
244250
else -> {
245251
Log.w("Auth", "Unexpected exception type ${e::class.java.name}")
246252
"An unknown error occurred."

CredentialManager/app/src/main/res/layout/fragment_sign_in.xml

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
android:layout_marginTop="20dp"
2929
android:gravity="center"
3030
android:padding="16dp"
31-
android:text="Sign in"
31+
android:text="@string/sign_in"
3232
android:textSize="24sp"
3333
android:textStyle="bold"
3434
app:layout_constraintEnd_toEndOf="parent"
@@ -39,7 +39,7 @@
3939
android:id="@+id/circularProgressIndicator"
4040
android:layout_width="wrap_content"
4141
android:layout_height="wrap_content"
42-
android:layout_marginTop="10dp"
42+
android:layout_marginTop="20dp"
4343
android:indeterminate="true"
4444
android:visibility="invisible"
4545
app:layout_constraintCircleRadius="0dp"
@@ -55,8 +55,8 @@
5555
android:id="@+id/textProgress"
5656
android:layout_width="wrap_content"
5757
android:layout_height="wrap_content"
58-
android:layout_marginBottom="10dp"
59-
android:text="operation in progress... "
58+
android:layout_marginBottom="16dp"
59+
android:text="@string/operation_in_progress"
6060
android:visibility="invisible"
6161
app:layout_constraintBottom_toBottomOf="@+id/circularProgressIndicator"
6262
app:layout_constraintStart_toEndOf="@+id/circularProgressIndicator"
@@ -66,11 +66,21 @@
6666
android:id="@+id/sign_in_with_savedCredentials"
6767
android:layout_width="0dp"
6868
android:layout_height="wrap_content"
69-
android:layout_marginTop="10dp"
70-
android:text="Sign in with passkey/saved password"
69+
android:layout_marginTop="40dp"
70+
android:text="@string/sign_in_with_passkey_saved_password"
7171
android:textAllCaps="false"
7272
app:layout_constraintEnd_toEndOf="parent"
7373
app:layout_constraintStart_toStartOf="parent"
7474
app:layout_constraintTop_toBottomOf="@id/circularProgressIndicator" />
7575

76+
<androidx.appcompat.widget.AppCompatEditText
77+
android:id="@+id/text_username"
78+
android:layout_width="0dp"
79+
android:layout_height="wrap_content"
80+
android:layout_marginBottom="20dp"
81+
android:hint="@string/autofill_saved_credentials"
82+
app:layout_constraintBottom_toTopOf="@+id/sign_in_with_savedCredentials"
83+
app:layout_constraintEnd_toEndOf="parent"
84+
app:layout_constraintStart_toStartOf="parent" />
85+
7686
</androidx.constraintlayout.widget.ConstraintLayout>

CredentialManager/app/src/main/res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,8 @@
2525

2626
<string name="hello_first_fragment">Hello first fragment</string>
2727
<string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string>
28+
<string name="sign_in">Sign in</string>
29+
<string name="operation_in_progress">operation in progress...</string>
30+
<string name="sign_in_with_passkey_saved_password">Sign in with passkey/saved password</string>
31+
<string name="autofill_saved_credentials">Autofill saved credentials</string>
2832
</resources>

0 commit comments

Comments
 (0)