Android指纹识别API讲解,一种更快更好的用户体验

接着我们创建一个 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) {
throw new RuntimeException(e);
}
}

@TargetApi(23)
private void initCipher() {
try {
SecretKey key = (SecretKey) keyStore.getKey(DEFAULT_KEY_NAME, null);
Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + “/”

  • KeyProperties.BLOCK_MODE_CBC + “/”
  • KeyProperties.ENCRYPTION_PADDING_PKCS7);
    cipher.init(Cipher.ENCRYPT_MODE, key);
    showFingerPrintDialog(cipher);
    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    }

private void showFingerPrintDialog(Cipher cipher) {
FingerprintDialogFragment fragment = new FingerprintDialogFragment();
fragment.setCipher(cipher);
fragment.show(getFragmentManager(), “fingerprint”);
}

public void onAuthenticated() {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}

}

首先在 onCreate() 方法中,调用了 supportFingerprint() 方法来判断当前设备是否支持指纹认证功能。这一点是非常重要的,因为当设备不支持指纹认证的时候,还需要及时切换到如图案、密码等其他的认证方式。

当设备支持指纹认证的时候,再分为两步,第一步生成一个对称加密的 Key,第二步生成一个 Cipher 对象,这都是 Android 指纹认证 API 要求的标准用法。得到了 Cipher 对象之后,我们创建 FingerprintDialogFragment 的实例,并将 Cipher 对象传入,再将 FingerprintDialogFragment 显示出来就可以了。

最后的最后,当指纹认证成功之后,会在 FingerprintDialogFragment 的回调当中调用 LoginActivity 的 onAuthenticated() 方法,然后界面会跳转到 MainActivity,整个指纹认证过程就此结束。

总共就这些代码了,总体来说还是相当简单的,现在我们来运行一下看看实际的效果吧。打开应用之后会立刻弹出指纹认证对话框,此时先使用错误的手指来进行认证:

可以看到,当指纹验证失败的时候,会在界面上显示相应的错误提示信息。
接下来使用正确的手指来进行认证:

OK,指纹验证成功,并自动跳转到了 MainActivity 界面。
这样一个最简版的指纹认证 Demo 就此完成,大家如果想要在自己的 APP 中集成指纹认证功能,只需要复制粘贴本文中的代码就可以轻松实现了。如果想要下载完整的 Demo 源码,点击这里 即可下载。
在文章的结尾我还想再补充几句,虽然本文中的指纹认证 Demo 实现过程很简单,但是切记它是不能单独使用的,必须要配合着图案或其他认证方式一起来使用,因为一定要提供一个在设备不支持指纹情况下的其他认证方式。
另外,比较遗憾的是,虽然是刚刚写出来的文章,但是 FingerprintManager 在最新的 Android 9.0 系统上已经被废弃了。因为 Android 9.0 系统提供了更加强大的生物识别认证功能,包括指纹识别、面部识别、甚至是虹膜识别等等,因此仅仅只能用于指纹识别的 FingerprintManager 已经不能满足新系统的强大需求了。
不过大家也不用担心,虽然被标为废弃,但是至少在较长一段时间内,FingerprintManager 还是可以正常使用的。而我过段时间也会针对 Android 9.0 的生物识别功能专门再写一篇文章,敬请期待吧。

关注我的技术公众号“郭霖”,优质技术文章推送。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

Android开发除了flutter还有什么是必须掌握的吗?

相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了

除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了

除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;

[外链图片转存中…(img-z7kRlFdx-1711605566973)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值