这是一个非常简易的指纹认证界面,相信没什么需要解释的地方。界面大致样式如下图所示。

android接入gpuimage Android接入指纹仪的方案_Android

注意,通常为了让用户清楚的知道现在需要进行指纹认证,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;
 }@Override
 public void onAttach(Context context) {
 super.onAttach(context);
 mActivity = (LoginActivity) getActivity();
 }@Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 fingerprintManager = getContext().getSystemService(FingerprintManager.class);
 setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Material_Light_Dialog);
 }@Nullable
 @Override
 public 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() {
 @Override
 public void onClick(View v) {
 dismiss();
 stopListening();
 }
 });
 return v;
 }@Override
 public void onResume() {
 super.onResume();startListening(mCipher);
 }@Override
 public 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() {
 @Override
 public 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();
 }
 }
 }@Override
 public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
 errorMsg.setText(helpString);
 }@Override
 public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
 Toast.makeText(mActivity, “指纹认证成功”, Toast.LENGTH_SHORT).show();
 mActivity.onAuthenticated();
 }@Override
 public 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;
@Override
 protected 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;
 }
 }
 return true;
 }@TargetApi(23)
 private void initKey() {
 try {
 keyStore = KeyStore.getInstance(“AndroidKeyStore”);
 keyStore.load(null);
 KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, “AndroidKeyStore”);
 KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(DEFAULT_KEY_NAME,
 KeyProperties.PURPOSE_ENCRYPT |
 KeyProperties.PURPOSE_DECRYPT)
 .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
 .setUserAuthenticationRequired(true)
 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7);
 keyGenerator.init(builder.build());
 keyGenerator.generateKey();
 } catch (Exception e) {