Skip to content

Instantly share code, notes, and snippets.

@jakubkinst
Last active August 1, 2019 12:22
Show Gist options
  • Save jakubkinst/9c48cbf5c5af4eff7a023c5f77022eb8 to your computer and use it in GitHub Desktop.
Save jakubkinst/9c48cbf5c5af4eff7a023c5f77022eb8 to your computer and use it in GitHub Desktop.
SmartLockManager
package com.uncommon.model.smartlock
import android.app.Activity
import android.content.Intent
import android.content.IntentSender
import com.google.android.gms.auth.api.credentials.Credential
import com.google.android.gms.auth.api.credentials.CredentialPickerConfig
import com.google.android.gms.auth.api.credentials.CredentialRequest
import com.google.android.gms.auth.api.credentials.Credentials
import com.google.android.gms.auth.api.credentials.HintRequest
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.common.api.ResolvableApiException
import com.strv.ktools.logD
import com.strv.ktools.logE
class SmartLockManager(val activity: Activity, val callback: (Credential) -> Unit) {
companion object {
private const val RC_READ = 38971
private const val RC_HINT = 38972
private const val RC_SAVE = 38973
}
private val client = Credentials.getClient(activity)
fun fetchCredentials() {
val credentialRequest = CredentialRequest.Builder()
.setPasswordLoginSupported(true)
.build()
client.request(credentialRequest).addOnCompleteListener { task ->
if (task.isSuccessful) {
callback(task.result.credential)
} else {
val e = task.exception
if (e is ResolvableApiException) {
// This is most likely the case where the user has multiple saved
// credentials and needs to pick one. This requires showing UI to
// resolve the read request.
resolveResult(e, RC_READ)
} else if (e is ApiException) {
// The user must create an account or sign in manually.
logE("Unsuccessful credential request.", e)
// no complete Credential found, let's try to fetch hints at least
fetchHints()
}
}
}
}
fun fetchHints() {
val hintRequest = HintRequest.Builder()
.setHintPickerConfig(CredentialPickerConfig.Builder()
.setShowCancelButton(true)
.build())
.setEmailAddressIdentifierSupported(true)
.build()
val intent = client.getHintPickerIntent(hintRequest)
try {
activity.startIntentSenderForResult(intent.intentSender, RC_HINT, null, 0, 0, 0)
} catch (e: IntentSender.SendIntentException) {
logE("Could not start hint picker Intent", e)
}
}
fun storeCredential(credential: Credential) {
client.save(credential).addOnCompleteListener { task ->
if (task.isSuccessful) {
logD("SAVE: OK")
} else {
val e = task.exception
if (e is ResolvableApiException) {
// Try to resolve the save request. This will prompt the user if
// the credential is new.
resolveResult(e, RC_SAVE)
}
}
}
}
private fun resolveResult(rae: ResolvableApiException, requestCode: Int) {
try {
rae.startResolutionForResult(activity, requestCode)
} catch (e: IntentSender.SendIntentException) {
logE("Failed to send resolution.", e)
}
}
// NOTE: this must be called from Activity to pass results
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
RC_READ -> if (resultCode == Activity.RESULT_OK) {
val credential = data!!.getParcelableExtra<Credential>(Credential.EXTRA_KEY)
callback(credential)
} else {
logE("Credential Read: NOT OK")
}
RC_HINT -> if (resultCode == Activity.RESULT_OK) {
val credential = data!!.getParcelableExtra<Credential>(Credential.EXTRA_KEY)
callback(credential)
} else {
logE("Hint Read: NOT OK")
}
RC_SAVE -> if (resultCode == Activity.RESULT_OK) {
logD("SAVE: OK")
} else {
logE("SAVE: Canceled by user")
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment