@@ -22,6 +22,8 @@ import android.os.Build
2222import android.os.Bundle
2323import android.util.Log
2424import androidx.annotation.RequiresApi
25+ import androidx.credentials.CreatePasswordRequest
26+ import androidx.credentials.CreatePublicKeyCredentialRequest
2527import androidx.credentials.CredentialManager
2628import androidx.credentials.CustomCredential
2729import androidx.credentials.GetCredentialRequest
@@ -30,7 +32,14 @@ import androidx.credentials.GetPasswordOption
3032import androidx.credentials.GetPublicKeyCredentialOption
3133import androidx.credentials.PasswordCredential
3234import androidx.credentials.PublicKeyCredential
35+ import androidx.credentials.exceptions.CreateCredentialCancellationException
36+ import androidx.credentials.exceptions.CreateCredentialCustomException
37+ import androidx.credentials.exceptions.CreateCredentialException
38+ import androidx.credentials.exceptions.CreateCredentialInterruptedException
39+ import androidx.credentials.exceptions.CreateCredentialProviderConfigurationException
40+ import androidx.credentials.exceptions.CreateCredentialUnknownException
3341import androidx.credentials.exceptions.GetCredentialException
42+ import androidx.credentials.exceptions.publickeycredential.CreatePublicKeyCredentialDomException
3443import kotlinx.coroutines.coroutineScope
3544import kotlinx.coroutines.runBlocking
3645import org.json.JSONObject
@@ -43,6 +52,7 @@ class PasskeyAndPasswordFunctions (
4352 // CredentialManager.
4453 private val credentialManager = CredentialManager .create(context)
4554 // [END android_identity_initialize_credman]
55+ private val activityContext = context
4656
4757 // Placeholder for TAG log value.
4858 val TAG = " "
@@ -55,8 +65,7 @@ class PasskeyAndPasswordFunctions (
5565 */
5666 @RequiresApi(Build .VERSION_CODES .UPSIDE_DOWN_CAKE )
5767 fun signInFlow (
58- creationResult : JSONObject ,
59- activityContext : Context ,
68+ creationResult : JSONObject
6069 ) {
6170 val requestJson = creationResult.toString()
6271 // [START android_identity_get_password_passkey_options]
@@ -166,6 +175,93 @@ class PasskeyAndPasswordFunctions (
166175 }
167176 }
168177 // [END android_identity_launch_sign_in_flow_2]
178+
179+ // [START android_identity_create_passkey]
180+ suspend fun createPasskey (requestJson : String , preferImmediatelyAvailableCredentials : Boolean ) {
181+ val createPublicKeyCredentialRequest = CreatePublicKeyCredentialRequest (
182+ // Contains the request in JSON format. Uses the standard WebAuthn
183+ // web JSON spec.
184+ requestJson = requestJson,
185+ // Defines whether you prefer to use only immediately available
186+ // credentials, not hybrid credentials, to fulfill this request.
187+ // This value is false by default.
188+ preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials,
189+ )
190+
191+ // Execute CreateCredentialRequest asynchronously to register credentials
192+ // for a user account. Handle success and failure cases with the result and
193+ // exceptions, respectively.
194+ coroutineScope {
195+ try {
196+ val result = credentialManager.createCredential(
197+ // Use an activity-based context to avoid undefined system
198+ // UI launching behavior
199+ context = activityContext,
200+ request = createPublicKeyCredentialRequest,
201+ )
202+ // Handle passkey creation result
203+ } catch (e : CreateCredentialException ){
204+ handleFailure(e)
205+ }
206+ }
207+ }
208+ // [END android_identity_create_passkey]
209+
210+ // [START android_identity_handle_create_passkey_failure]
211+ fun handleFailure (e : CreateCredentialException ) {
212+ when (e) {
213+ is CreatePublicKeyCredentialDomException -> {
214+ // Handle the passkey DOM errors thrown according to the
215+ // WebAuthn spec.
216+ }
217+ is CreateCredentialCancellationException -> {
218+ // The user intentionally canceled the operation and chose not
219+ // to register the credential.
220+ }
221+ is CreateCredentialInterruptedException -> {
222+ // Retry-able error. Consider retrying the call.
223+ }
224+ is CreateCredentialProviderConfigurationException -> {
225+ // Your app is missing the provider configuration dependency.
226+ // Most likely, you're missing the
227+ // "credentials-play-services-auth" module.
228+ }
229+ is CreateCredentialCustomException -> {
230+ // You have encountered an error from a 3rd-party SDK. If you
231+ // make the API call with a request object that's a subclass of
232+ // CreateCustomCredentialRequest using a 3rd-party SDK, then you
233+ // should check for any custom exception type constants within
234+ // that SDK to match with e.type. Otherwise, drop or log the
235+ // exception.
236+ }
237+ else -> Log .w(TAG , " Unexpected exception type ${e::class .java.name} " )
238+ }
239+ }
240+ // [END android_identity_handle_create_passkey_failure]
241+
242+ // [START android_identity_register_password]
243+ suspend fun registerPassword (username : String , password : String ) {
244+ // Initialize a CreatePasswordRequest object.
245+ val createPasswordRequest =
246+ CreatePasswordRequest (id = username, password = password)
247+
248+ // Create credential and handle result.
249+ coroutineScope {
250+ try {
251+ val result =
252+ credentialManager.createCredential(
253+ // Use an activity based context to avoid undefined
254+ // system UI launching behavior.
255+ activityContext,
256+ createPasswordRequest
257+ )
258+ // Handle register password result
259+ } catch (e: CreateCredentialException ) {
260+ handleFailure(e)
261+ }
262+ }
263+ }
264+ // [END android_identity_register_password]
169265}
170266
171267sealed class ExampleCustomCredential {
0 commit comments