While we use the XML and Kotlin setup, using edittext with email and password setup automatically shows options to fill the detail in suggestion of the keyboard but the same thing does not occur in the Compose architecture.
Have they provided a way to do it or is it a compose drawback for now?
I know we can build it as XML and put it in the composable but its not a clean way so if there is any proper solution to this, please help
Yes a proper solution did exist as mentioned below.
Using Google Credential Manager to Save User Credentials
First you will need the below dependency
androidx.credentials:credentials:1.2.2
This is my custom build class to handle the function
import android.app.Activity
import androidx.credentials.CreatePasswordRequest
import androidx.credentials.CredentialManager
import androidx.credentials.GetCredentialRequest
import androidx.credentials.GetPasswordOption
import androidx.credentials.PasswordCredential
import androidx.credentials.exceptions.CreateCredentialCancellationException
import androidx.credentials.exceptions.CreateCredentialException
import androidx.credentials.exceptions.GetCredentialCancellationException
import androidx.credentials.exceptions.GetCredentialException
import androidx.credentials.exceptions.NoCredentialException
class AccountManager(val activity: Activity) {
private val credentialManager = CredentialManager.create(activity)
suspend fun signUp(username: String, password: String): SignupResult {
return try {
credentialManager.createCredential(activity, CreatePasswordRequest(username, password))
SignupResult.Success(username)
} catch (e: CreateCredentialCancellationException) {
e.printStackTrace()
SignupResult.Cancelled
} catch (e: CreateCredentialException) {
SignupResult.Failure
} catch (e:Exception){
SignupResult.Failure
}
}
suspend fun signIn():SignInResult{
return try {
val res = credentialManager.getCredential(activity,GetCredentialRequest(listOf(GetPasswordOption())))
val credential = res.credential as? PasswordCredential ?: return SignInResult.Failure
SignInResult.Success(credential.id,credential.password)
} catch (e: GetCredentialCancellationException) {
e.printStackTrace()
SignInResult.Cancelled
} catch (e: NoCredentialException) {
SignInResult.NoCredentials
} catch (e: GetCredentialException) {
SignInResult.Failure
} catch (e:Exception){
SignInResult.Failure
}
}
}
sealed interface SignInResult {
data class Success(val username: String,val pwd: String) : SignInResult
data object Cancelled : SignInResult
data object Failure : SignInResult
data object NoCredentials : SignInResult
}
sealed interface SignupResult {
data class Success(val username: String) : SignupResult
data object Cancelled : SignupResult
data object Failure : SignupResult
}
Here i have also mentioned the imports for easy implementation
Below is the code for your composable
val context = LocalContext.current
val scope = rememberCoroutineScope()
val accountManager = remember {
AccountManager(context as ComponentActivity)
}
//submit the user entered email password to our custom class to save it
Text ("Login", modifier = Modifier.clickable {
scope.launch {
accountManager.signUp(email,password)
}
})
//When the screen is opened use below code to show user the prompt to fetch the details also errors can be handled specifically
LaunchedEffect(key1 = true) {
when (val res = accountManager.signIn()) {
SignInResult.Cancelled -> {}
SignInResult.Failure -> {}
SignInResult.NoCredentials -> {}
is SignInResult.Success -> {
//Update the field with this object
res.username
res.pwd
}
}
}