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.

Take a one-minute survey?
Help us improve Android tools and documentation.