Android 指纹识别 API 讲解,一种更快更好的用户体验,送给正在迷茫的你
<TextViewandroid:id="@+id/error_msg"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginTop="5dp"android:maxLines="1"android:textSize="12sp"android:textColor="#f45"/>
<Viewandroid:layout_width="match_parent"android:layout_height="0.5dp"android:layout_marginTop="10dp"android:background="#ccc"/>
<TextViewandroid:id="@+id/cancel"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:text="取消"android:textColor="#5d7883"android:textSize="16sp"/>
</LinearLayout>
这是一个非常简易的指纹认证界面,相信没什么需要解释的地方。界面大致样式如下图所示。
注意,通常为了让用户清楚的知道现在需要进行指纹认证,Google 官方建议最好使用一个通用的指纹图标,而不应该由各 APP 制作自己的指纹图标。为此,Google 也特意提供了一套指纹认证的组图,可以 [点击这里](
) 查看和下载。
二
接着我们创建一个 FingerprintDialogFragment 类,并让它继承自 DialogFragment,用于作为提示用户进行指纹认证的对话框,代码如下所示:
@TargetApi(23)public class FingerprintDialogFragment extends DialogFragment {
private FingerprintManager fingerprintManager;
private CancellationSignal mCancellationSignal;
private Cipher mCipher;
private LoginActivity mActivity;
private TextView errorMsg;
/**
标识是否是用户主动取消的认证。*/private boolean isSelfCancelled;
public void setCipher(Cipher cipher) {mCipher = cipher;}
@Overridepublic void onAttach(Context context) {super.onAttach(context);mActivity = (LoginActivity) getActivity();}
@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);fingerprintManager = getContext().getSystemService(FingerprintManager.class);setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Material_Light_Dialog);}
@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {View v = inflater.inflate(R.layout.fingerprint_dialog, container, false);errorMsg = v.findViewById(R.id.error_msg);TextView cancel = v.findViewById(R.id.cancel);cancel.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {dismiss();stopListening();}});return v;}
@Overridepublic void onResume() {super.onResume();
startListening(mCipher);}
@Overridepublic void onPause() {super.onPause();
stopListening();}
private void startListening(Cipher cipher) {isSelfCancelled = false;mCancellationSignal = new CancellationSignal();fingerprintManager.authenticate(new FingerprintManager.CryptoObject(cipher), mCancellationSignal, 0, new FingerprintManager.AuthenticationCallback() {@Overridepublic void onAuthenticationError(int errorCode, CharSequence errString) {if (!isSelfCancelled) {errorMsg.setText(errString);if (errorCode == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT) {Toast.makeText(mActivity, errString, Toast.LENGTH_SHORT).show();dismiss();}}}
@Overridepublic void onAuthenticationHelp(int helpCode, CharSequence helpString) {errorMsg.setText(helpString);}
@Overridepublic void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {Toast.makeText(mActivity, "指纹认证成功", Toast.LENGTH_SHORT).show();mActivity.onAuth
enticated();}
@Overridepublic void onAuthenticationFailed() {errorMsg.setText("指纹认证失败,请再试一次");}}, null);}
private void stopListening() {if (mCancellationSignal != null) {mCancellationSignal.cancel();mCancellationSignal = null;isSelfCancelled = true;}}
}
说了是实现一个最简版的指纹认证 Demo,因此这里的代码也都是非常简单的,基本上就是一个 Fragment 类的最普通实现,下面我带大家简单解析一下。
首先 setCipher() 方法用于接受一个 Cipher 对象,这个参数在待会进行指纹认证的时候会用到。
三
接下来几个生命周期方法都很简单,在 onAttach() 方法中获取了 Activity 的实例,在 onCreate() 方法获取了 FingerprintManager 的实例,在 onCreateView() 方法中加载了我们刚刚创建的 fingerprint_dialog.xml 布局,都是一些常规操作。
紧接着重点的要来了,在 onResume() 方法中调用了 startListening() 方法开始指纹认证监听,在 onPause() 方法中调用了 stopListening() 方法停止指纹认证监听。为什么要这么做呢?因为指纹传感器和摄像头类似,是不能多个程序同时使用的,因此任何一个程序都不应该在非前台时刻占用着指纹传感器的资源,所以需要在 onPause() 方法中及时释放资源。
那么,现在我们只需要把所有的目光都放在 startListening() 和 stopListening() 这两个方法上就可以了。在 startListening() 方法中,调用了 FingerprintManager 的 authenticate() 方法来开启指纹指纹监听。authenticate() 方法接收五个参数,第一个参数是 CryptoObject 对象,这里我们只需要将刚才传入的 Cipher 对象包装成 CryptoObject 对象就可以了。第二个参数是 CancellationSignal 对象,可以使用它来取消指纹认证操作。第三个参数是可选参数,官方的建议是直接传 0 就可以了。第四个参数用于接收指纹认证的回调,上述代码中我将所有的回调可能都进行了界面提示,方便大家观察。第五个参数用于指定处理回调的 Handler,这里直接传 null 表示回调到主线程即可。
而在 stopListening() 方法中的逻辑则简单得多了,我们只需要调用 CancellationSignal 的 cancel() 方法将指纹认证操作取消就可以了。
这样我们就将 FingerprintDialogFragment 中的代码全部完成了,这段代码可以直接复制到任意项目当中来作为指纹认证提醒对话框。
四
最后,我们再来编写一个简单的登录界面,整个指纹认证过程就完整了。创建 LoginActivity,代码如下所示:
public class LoginActivity extends AppCompatActivity {
private static final String DEFAULT_KEY_NAME = "default_key";
KeyStore keyStore;
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);if (supportFingerprint()) {initKey();initCipher();}}
public boolean supportFingerprint() {if (Build.VERSION.SDK_INT < 23) {Toast.makeText(this, "您的系统版本过低,不支持指纹功能", Toast.LENGTH_SHORT).show();return false;} else {KeyguardManager keyguardManager = getSystemService(KeyguardManager.class);FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class);if (!fingerprintManager.isHardwareDetected()) {Toast.makeText(this, "您的手机不支持指纹功能", Toast.LENGTH_SHORT).show();return false;} else if (!keyguardManager.isKeyguardSecure()) {Toast.makeText(this, "您还未设置锁屏,请先设置锁屏并添加一个指纹", Toast.LENGTH_SHORT).show();return false;} else if (!fingerprintManager.hasEnrolledFingerprints()) {Toast.makeText(this, "您至少需要在系统设置中添加一个指纹", Toast.LENGTH_SHORT).show();return false;}
评论