Skip to content

Most visited

Recently visited

navigation
AsymmetricFingerprintDialog / src / com.example.android.asymmetricfingerprintdialog /

FingerprintUiHelper.java

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.asymmetricfingerprintdialog;
18
 
19
import com.google.common.annotations.VisibleForTesting;
20
 
21
import android.hardware.fingerprint.FingerprintManager;
22
import android.os.CancellationSignal;
23
import android.widget.ImageView;
24
import android.widget.TextView;
25
 
26
import javax.inject.Inject;
27
 
28
/**
29
 * Small helper class to manage text/icon around fingerprint authentication UI.
30
 * This class assumes that the {@link android.Manifest.permission#USE_FINGERPRINT}
31
 * permission has already been granted. (As of API 23 this permission is normal instead of dangerous
32
 * and is granted at install time.)
33
 */
34
@SuppressWarnings("MissingPermission")
35
public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback {
36
 
37
    @VisibleForTesting static final long ERROR_TIMEOUT_MILLIS = 1600;
38
    @VisibleForTesting static final long SUCCESS_DELAY_MILLIS = 1300;
39
 
40
    private final FingerprintManager mFingerprintManager;
41
    private final ImageView mIcon;
42
    private final TextView mErrorTextView;
43
    private final Callback mCallback;
44
    private CancellationSignal mCancellationSignal;
45
 
46
    @VisibleForTesting boolean mSelfCancelled;
47
 
48
    /**
49
     * Builder class for {@link FingerprintUiHelper} in which injected fields from Dagger
50
     * holds its fields and takes other arguments in the {@link #build} method.
51
     */
52
    public static class FingerprintUiHelperBuilder {
53
        private final FingerprintManager mFingerPrintManager;
54
 
55
        @Inject
56
        public FingerprintUiHelperBuilder(FingerprintManager fingerprintManager) {
57
            mFingerPrintManager = fingerprintManager;
58
        }
59
 
60
        public FingerprintUiHelper build(ImageView icon, TextView errorTextView, Callback callback) {
61
            return new FingerprintUiHelper(mFingerPrintManager, icon, errorTextView,
62
                    callback);
63
        }
64
    }
65
 
66
    /**
67
     * Constructor for {@link FingerprintUiHelper}. This method is expected to be called from
68
     * only the {@link FingerprintUiHelperBuilder} class.
69
     */
70
    private FingerprintUiHelper(FingerprintManager fingerprintManager,
71
            ImageView icon, TextView errorTextView, Callback callback) {
72
        mFingerprintManager = fingerprintManager;
73
        mIcon = icon;
74
        mErrorTextView = errorTextView;
75
        mCallback = callback;
76
    }
77
 
78
    public boolean isFingerprintAuthAvailable() {
79
        return mFingerprintManager.isHardwareDetected()
80
                && mFingerprintManager.hasEnrolledFingerprints();
81
    }
82
 
83
    public void startListening(FingerprintManager.CryptoObject cryptoObject) {
84
        if (!isFingerprintAuthAvailable()) {
85
            return;
86
        }
87
        mCancellationSignal = new CancellationSignal();
88
        mSelfCancelled = false;
89
        mFingerprintManager
90
                .authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, this, null);
91
        mIcon.setImageResource(R.drawable.ic_fp_40px);
92
    }
93
 
94
    public void stopListening() {
95
        if (mCancellationSignal != null) {
96
            mSelfCancelled = true;
97
            mCancellationSignal.cancel();
98
            mCancellationSignal = null;
99
        }
100
    }
101
 
102
    @Override
103
    public void onAuthenticationError(int errMsgId, CharSequence errString) {
104
        if (!mSelfCancelled) {
105
            showError(errString);
106
            mIcon.postDelayed(new Runnable() {
107
                @Override
108
                public void run() {
109
                    mCallback.onError();
110
                }
111
            }, ERROR_TIMEOUT_MILLIS);
112
        }
113
    }
114
 
115
    @Override
116
    public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
117
        showError(helpString);
118
    }
119
 
120
    @Override
121
    public void onAuthenticationFailed() {
122
        showError(mIcon.getResources().getString(
123
                R.string.fingerprint_not_recognized));
124
    }
125
 
126
    @Override
127
    public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
128
        mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
129
        mIcon.setImageResource(R.drawable.ic_fingerprint_success);
130
        mErrorTextView.setTextColor(
131
                mErrorTextView.getResources().getColor(R.color.success_color, null));
132
        mErrorTextView.setText(
133
                mErrorTextView.getResources().getString(R.string.fingerprint_success));
134
        mIcon.postDelayed(new Runnable() {
135
            @Override
136
            public void run() {
137
                mCallback.onAuthenticated();
138
            }
139
        }, SUCCESS_DELAY_MILLIS);
140
    }
141
 
142
    private void showError(CharSequence error) {
143
        mIcon.setImageResource(R.drawable.ic_fingerprint_error);
144
        mErrorTextView.setText(error);
145
        mErrorTextView.setTextColor(
146
                mErrorTextView.getResources().getColor(R.color.warning_color, null));
147
        mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
148
        mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT_MILLIS);
149
    }
150
 
151
    @VisibleForTesting
152
    Runnable mResetErrorTextRunnable = new Runnable() {
153
        @Override
154
        public void run() {
155
            mErrorTextView.setTextColor(
156
                    mErrorTextView.getResources().getColor(R.color.hint_color, null));
157
            mErrorTextView.setText(
158
                    mErrorTextView.getResources().getString(R.string.fingerprint_hint));
159
            mIcon.setImageResource(R.drawable.ic_fp_40px);
160
        }
161
    };
162
 
163
    public interface Callback {
164
 
165
        void onAuthenticated();
166
 
167
        void onError();
168
    }
169
}
This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.