1 /* 2 * Copyright (C) 2015 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 public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback { 28 29 private static final long ERROR_TIMEOUT_MILLIS = 1600; 30 private static final long SUCCESS_DELAY_MILLIS = 1300; 31 32 private final FingerprintManager mFingerprintManager; 33 private final ImageView mIcon; 34 private final TextView mErrorTextView; 35 private final Callback mCallback; 36 private CancellationSignal mCancellationSignal; 37 38 private boolean mSelfCancelled; 39 40 /** 41 * Constructor for {@link FingerprintUiHelper}. 42 */ FingerprintUiHelper(FingerprintManager fingerprintManager, ImageView icon, TextView errorTextView, Callback callback)43 FingerprintUiHelper(FingerprintManager fingerprintManager, 44 ImageView icon, TextView errorTextView, Callback callback) { 45 mFingerprintManager = fingerprintManager; 46 mIcon = icon; 47 mErrorTextView = errorTextView; 48 mCallback = callback; 49 } 50 isFingerprintAuthAvailable()51 public boolean isFingerprintAuthAvailable() { 52 // The line below prevents the false positive inspection from Android Studio 53 // noinspection ResourceType 54 return mFingerprintManager.isHardwareDetected() 55 && mFingerprintManager.hasEnrolledFingerprints(); 56 } 57 startListening(FingerprintManager.CryptoObject cryptoObject)58 public void startListening(FingerprintManager.CryptoObject cryptoObject) { 59 if (!isFingerprintAuthAvailable()) { 60 return; 61 } 62 mCancellationSignal = new CancellationSignal(); 63 mSelfCancelled = false; 64 // The line below prevents the false positive inspection from Android Studio 65 // noinspection ResourceType 66 mFingerprintManager 67 .authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, this, null); 68 mIcon.setImageResource(R.drawable.ic_fp_40px); 69 } 70 stopListening()71 public void stopListening() { 72 if (mCancellationSignal != null) { 73 mSelfCancelled = true; 74 mCancellationSignal.cancel(); 75 mCancellationSignal = null; 76 } 77 } 78 79 @Override onAuthenticationError(int errMsgId, CharSequence errString)80 public void onAuthenticationError(int errMsgId, CharSequence errString) { 81 if (!mSelfCancelled) { 82 showError(errString); 83 mIcon.postDelayed(new Runnable() { 84 @Override 85 public void run() { 86 mCallback.onError(); 87 } 88 }, ERROR_TIMEOUT_MILLIS); 89 } 90 } 91 92 @Override onAuthenticationHelp(int helpMsgId, CharSequence helpString)93 public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { 94 showError(helpString); 95 } 96 97 @Override onAuthenticationFailed()98 public void onAuthenticationFailed() { 99 showError(mIcon.getResources().getString( 100 R.string.fingerprint_not_recognized)); 101 } 102 103 @Override onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result)104 public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { 105 mErrorTextView.removeCallbacks(mResetErrorTextRunnable); 106 mIcon.setImageResource(R.drawable.ic_fingerprint_success); 107 mErrorTextView.setTextColor( 108 mErrorTextView.getResources().getColor(R.color.success_color, null)); 109 mErrorTextView.setText( 110 mErrorTextView.getResources().getString(R.string.fingerprint_success)); 111 mIcon.postDelayed(new Runnable() { 112 @Override 113 public void run() { 114 mCallback.onAuthenticated(); 115 } 116 }, SUCCESS_DELAY_MILLIS); 117 } 118 showError(CharSequence error)119 private void showError(CharSequence error) { 120 mIcon.setImageResource(R.drawable.ic_fingerprint_error); 121 mErrorTextView.setText(error); 122 mErrorTextView.setTextColor( 123 mErrorTextView.getResources().getColor(R.color.warning_color, null)); 124 mErrorTextView.removeCallbacks(mResetErrorTextRunnable); 125 mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT_MILLIS); 126 } 127 128 private Runnable mResetErrorTextRunnable = new Runnable() { 129 @Override 130 public void run() { 131 mErrorTextView.setTextColor( 132 mErrorTextView.getResources().getColor(R.color.hint_color, null)); 133 mErrorTextView.setText( 134 mErrorTextView.getResources().getString(R.string.fingerprint_hint)); 135 mIcon.setImageResource(R.drawable.ic_fp_40px); 136 } 137 }; 138 139 public interface Callback { 140 onAuthenticated()141 void onAuthenticated(); 142 onError()143 void onError(); 144 } 145 } 146