blob: ad38abc609da1b2f96b1c66b0e5bbdb0e502efb2 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.example.android.fingerprintdialog
import android.hardware.fingerprint.FingerprintManager
import android.os.CancellationSignal
import android.widget.ImageView
import android.widget.TextView
/**
* Small helper class to manage text/icon around fingerprint authentication UI.
*/
class FingerprintUiHelper
/**
* Constructor for [FingerprintUiHelper].
*/
internal constructor(private val fingerprintMgr: FingerprintManager,
private val icon: ImageView,
private val errorTextView: TextView,
private val callback: Callback
) : FingerprintManager.AuthenticationCallback() {
private var cancellationSignal: CancellationSignal? = null
private var selfCancelled = false
val isFingerprintAuthAvailable: Boolean
get() = fingerprintMgr.isHardwareDetected && fingerprintMgr.hasEnrolledFingerprints()
private val resetErrorTextRunnable = Runnable {
icon.setImageResource(R.drawable.ic_fp_40px)
errorTextView.run {
setTextColor(errorTextView.resources.getColor(R.color.hint_color, null))
text = errorTextView.resources.getString(R.string.fingerprint_hint)
}
}
fun startListening(cryptoObject: FingerprintManager.CryptoObject) {
if (!isFingerprintAuthAvailable) return
cancellationSignal = CancellationSignal()
selfCancelled = false
fingerprintMgr.authenticate(cryptoObject, cancellationSignal, 0, this, null)
icon.setImageResource(R.drawable.ic_fp_40px)
}
fun stopListening() {
cancellationSignal?.also {
selfCancelled = true
it.cancel()
}
cancellationSignal = null
}
override fun onAuthenticationError(errMsgId: Int, errString: CharSequence) {
if (!selfCancelled) {
showError(errString)
icon.postDelayed({ callback.onError() }, ERROR_TIMEOUT_MILLIS)
}
}
override fun onAuthenticationHelp(helpMsgId: Int, helpString: CharSequence) =
showError(helpString)
override fun onAuthenticationFailed() =
showError(icon.resources.getString(R.string.fingerprint_not_recognized))
override fun onAuthenticationSucceeded(result: FingerprintManager.AuthenticationResult) {
errorTextView.run {
removeCallbacks(resetErrorTextRunnable)
setTextColor(errorTextView.resources.getColor(R.color.success_color, null))
text = errorTextView.resources.getString(R.string.fingerprint_success)
}
icon.run {
setImageResource(R.drawable.ic_fingerprint_success)
postDelayed({ callback.onAuthenticated() }, SUCCESS_DELAY_MILLIS)
}
}
private fun showError(error: CharSequence) {
icon.setImageResource(R.drawable.ic_fingerprint_error)
errorTextView.run {
text = error
setTextColor(errorTextView.resources.getColor(R.color.warning_color, null))
removeCallbacks(resetErrorTextRunnable)
postDelayed(resetErrorTextRunnable, ERROR_TIMEOUT_MILLIS)
}
}
interface Callback {
fun onAuthenticated()
fun onError()
}
companion object {
val ERROR_TIMEOUT_MILLIS: Long = 1600
val SUCCESS_DELAY_MILLIS: Long = 1300
}
}