Home | History | Annotate | Download | only in fingerprintdialog
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package com.example.android.fingerprintdialog
     18 
     19 import android.hardware.fingerprint.FingerprintManager
     20 import android.os.CancellationSignal
     21 import android.widget.ImageView
     22 import android.widget.TextView
     23 
     24 /**
     25  * Small helper class to manage text/icon around fingerprint authentication UI.
     26  */
     27 class FingerprintUiHelper
     28 
     29 /**
     30  * Constructor for [FingerprintUiHelper].
     31  */
     32 internal constructor(private val fingerprintMgr: FingerprintManager,
     33         private val icon: ImageView,
     34         private val errorTextView: TextView,
     35         private val callback: Callback
     36 ) : FingerprintManager.AuthenticationCallback() {
     37 
     38     private var cancellationSignal: CancellationSignal? = null
     39     private var selfCancelled = false
     40 
     41     val isFingerprintAuthAvailable: Boolean
     42         get() = fingerprintMgr.isHardwareDetected && fingerprintMgr.hasEnrolledFingerprints()
     43 
     44     private val resetErrorTextRunnable = Runnable {
     45         icon.setImageResource(R.drawable.ic_fp_40px)
     46         errorTextView.run {
     47             setTextColor(errorTextView.resources.getColor(R.color.hint_color, null))
     48             text = errorTextView.resources.getString(R.string.fingerprint_hint)
     49         }
     50     }
     51 
     52     fun startListening(cryptoObject: FingerprintManager.CryptoObject) {
     53         if (!isFingerprintAuthAvailable) return
     54         cancellationSignal = CancellationSignal()
     55         selfCancelled = false
     56         fingerprintMgr.authenticate(cryptoObject, cancellationSignal, 0, this, null)
     57         icon.setImageResource(R.drawable.ic_fp_40px)
     58     }
     59 
     60     fun stopListening() {
     61         cancellationSignal?.also {
     62             selfCancelled = true
     63             it.cancel()
     64         }
     65         cancellationSignal = null
     66     }
     67 
     68     override fun onAuthenticationError(errMsgId: Int, errString: CharSequence) {
     69         if (!selfCancelled) {
     70             showError(errString)
     71             icon.postDelayed({ callback.onError() }, ERROR_TIMEOUT_MILLIS)
     72         }
     73     }
     74 
     75     override fun onAuthenticationHelp(helpMsgId: Int, helpString: CharSequence) =
     76             showError(helpString)
     77 
     78     override fun onAuthenticationFailed() =
     79             showError(icon.resources.getString(R.string.fingerprint_not_recognized))
     80 
     81     override fun onAuthenticationSucceeded(result: FingerprintManager.AuthenticationResult) {
     82         errorTextView.run {
     83             removeCallbacks(resetErrorTextRunnable)
     84             setTextColor(errorTextView.resources.getColor(R.color.success_color, null))
     85             text = errorTextView.resources.getString(R.string.fingerprint_success)
     86         }
     87         icon.run {
     88             setImageResource(R.drawable.ic_fingerprint_success)
     89             postDelayed({ callback.onAuthenticated() }, SUCCESS_DELAY_MILLIS)
     90         }
     91     }
     92 
     93     private fun showError(error: CharSequence) {
     94         icon.setImageResource(R.drawable.ic_fingerprint_error)
     95         errorTextView.run {
     96             text = error
     97             setTextColor(errorTextView.resources.getColor(R.color.warning_color, null))
     98             removeCallbacks(resetErrorTextRunnable)
     99             postDelayed(resetErrorTextRunnable, ERROR_TIMEOUT_MILLIS)
    100         }
    101     }
    102 
    103     interface Callback {
    104         fun onAuthenticated()
    105         fun onError()
    106     }
    107 
    108     companion object {
    109         val ERROR_TIMEOUT_MILLIS: Long = 1600
    110         val SUCCESS_DELAY_MILLIS: Long = 1300
    111     }
    112 }
    113