Skip to content

Instantly share code, notes, and snippets.

@gotev
Last active October 16, 2018 15:02
Show Gist options
  • Save gotev/e645067c4fcf0562a16224fcd0394f91 to your computer and use it in GitHub Desktop.
Save gotev/e645067c4fcf0562a16224fcd0394f91 to your computer and use it in GitHub Desktop.
Smart Login Helper
/*
* Setup project first: https://developers.google.com/identity/smartlock-passwords/android/get-started
*/
import android.app.Activity.RESULT_OK
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.auth.api.credentials.Credential
import com.google.android.gms.auth.api.credentials.CredentialRequest
import com.google.android.gms.auth.api.credentials.Credentials
import com.google.android.gms.common.api.ResolvableApiException
import com.google.android.gms.tasks.Task
import java.lang.ref.WeakReference
class SmartLoginHelper(private val accountType: String,
private val retrieveCredentialsRequestCode: Int,
private val saveCredentialsRequestCode: Int,
passwordLoginSupported: Boolean,
delegate: Delegate) {
interface Delegate {
fun onRetrievedCredentials(success: Boolean, username: String, password: String?)
fun onSavedCredentials(success: Boolean)
fun onDeletedCredentials(success: Boolean)
}
private val credentialsRequest = CredentialRequest.Builder()
.setPasswordLoginSupported(passwordLoginSupported)
.setAccountTypes(accountType)
.build()
private val delegate = WeakReference(delegate)
private fun <T> Task<T>.then(context: AppCompatActivity,
onSuccess: (result: T?) -> Unit,
onResolvableApiExceptionCode: Int,
onError: (exception: Throwable?) -> Unit) {
this.addOnCompleteListener {
if (it.isSuccessful) {
onSuccess(it.result)
return@addOnCompleteListener
}
if (it.exception is ResolvableApiException) {
try {
(it.exception as ResolvableApiException).startResolutionForResult(context, onResolvableApiExceptionCode)
} catch (exc: Throwable) {
onError(exc)
}
return@addOnCompleteListener
}
onError(it.exception)
}
}
private fun onCredentialsNotRetrieved() {
delegate.get()?.onRetrievedCredentials(success = false, username = "", password = null)
}
fun retrieveSavedCredentials(context: AppCompatActivity) {
Credentials
.getClient(context)
.request(credentialsRequest)
.then(context, {
val credential = it?.credential
if (credential != null && credential.accountType == accountType) {
delegate.get()?.onRetrievedCredentials(success = true, username = credential.id, password = credential.password)
} else {
onCredentialsNotRetrieved()
}
}, onResolvableApiExceptionCode = retrieveCredentialsRequestCode, onError = {
onCredentialsNotRetrieved()
})
}
fun saveCredentials(context: AppCompatActivity, username: String, password: String) {
val credential = Credential.Builder(username)
.setAccountType(accountType)
.setPassword(password)
.build()
Credentials
.getClient(context)
.save(credential)
.then(context, {
delegate.get()?.onSavedCredentials(false)
}, onResolvableApiExceptionCode = saveCredentialsRequestCode, onError = {
delegate.get()?.onSavedCredentials(false)
})
}
fun deleteCredentials(context: AppCompatActivity, username: String) {
val credential = Credential.Builder(username)
.setAccountType(accountType)
.build()
Credentials.getClient(context).delete(credential).addOnCompleteListener { task ->
delegate.get()?.onDeletedCredentials(task.isSuccessful)
}
}
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
when (requestCode) {
retrieveCredentialsRequestCode -> {
if (resultCode == RESULT_OK) {
val credential = data.getParcelableExtra<Credential>(Credential.EXTRA_KEY)
delegate.get()?.onRetrievedCredentials(success = true, username = credential.id, password = credential.password)
} else {
onCredentialsNotRetrieved()
}
}
saveCredentialsRequestCode -> {
delegate.get()?.onSavedCredentials(resultCode == RESULT_OK)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment