Android從6.0系統開始就支持指紋認證功能了,指紋功能還需要有硬件支持才行
指紋與手機系統設置的指紋進行匹配
如圖:

在LoginActivity 中彈出指紋驗證Fragment,驗證成功進入MainActivity中
代碼:
創建FingerprintDialogFragment 繼承 DialogFragment
package com.chuanye.zhiwendemo;
import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import javax.crypto.Cipher;
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();
}
@SuppressLint("NewApi")
@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();
}
@SuppressLint({"MissingPermission", "NewApi"})
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);
}
@SuppressLint("NewApi")
private void stopListening() {
if (mCancellationSignal != null) {
mCancellationSignal.cancel();
mCancellationSignal = null;
isSelfCancelled = true;
}
}
}
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_fp_40px"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="請驗證指紋解鎖"
android:textColor="#000"
android:textSize="16sp"
/>
<TextView
android: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"
/>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="10dp"
android:background="#ccc"
/>
<TextView
android:id="@+id/cancel"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="取消"
android:textColor="#5d7883"
android:textSize="16sp"
/>
</LinearLayout>
LoginActivity 中
package com.chuanye.zhiwendemo;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
import java.security.KeyStore;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
public class LoginActivity extends AppCompatActivity {
//https://blog.csdn.net/guolin_blog/article/details/81450114
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();
}
}
/**
* 判斷是否支持指紋
* @return
*/
@SuppressLint("MissingPermission")
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(getSupportFragmentManager(), "fingerprint");
}
public void onAuthenticated() {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}
}
activity_main.xml布局
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="已進入App主界面"
android:textSize="18sp"
android:layout_gravity="center"
/>
</FrameLayout>
最后添加權限
<uses-permission android:name="android.permission.USE_FINGERPRINT"></uses-permission>
注意,通常為了讓用戶清楚的知道現在需要進行指紋認證,Google官方建議最好使用一個通用的指紋圖標,而不應該由各APP制作自己的指紋圖標。為此,Google也特意提供了一套指紋認證的組圖,可以 點擊這里 查看和下載。
指紋認證不能單獨使用,必須要配合着圖案或其他認證方式一起來使用,因為一定要提供一個在設備不支持指紋情況下的其他認證方式
另外FingerprintManager在最新的Android 9.0系統上已經被廢棄了因為Android 9.0系統提供了更加強大的生物識別認證功能,包括指紋識別、面部識別、甚至是虹膜識別等等,因此僅僅只能用於指紋識別的FingerprintManager已經不能滿足新系統的強大需求了。
參考與郭神的https://blog.csdn.net/guolin_blog/article/details/81450114
