Android FingerPrint之指纹识别

目前, 市面上的手机基本都支持了指纹解锁功能,甚至已经支持面部识别解锁,及虹膜识别了,但是在我们的App中却是很少有指纹登录的,包括一些金融类软件,这是因为,指纹识别是在Android 6.0 以上才被支持的,还需要有硬件的支持,这个由于Android 手机层次不齐,所以考虑到兼容性问题,就放弃了指纹识别,更多的是图案解锁功能。

那么,假如我们想做一款指纹解锁的APP,该怎么做呢。
先放张效果图吧。
Android FingerPrint之指纹识别_第1张图片

这里是先用没有录入指纹的手指验证了下,结果提示错误,后面用正确的手指进行验证,提示验证成功。

开始

前面说过了,指纹识别是从Android 6.0 开始的,所以我们在做之前呢,先要验证一些列的问题,看看我们的手机是否支持指纹识别。具体有:

  1. 系统大于等于 Android 6.0
  2. 硬件支持
  3. 系统中已经设置录入指纹
    代码:
private boolean isSupportFingerPrint() {
        if (Build.VERSION.SDK_INT >= 23) {
            // 权限判断
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "没有指纹识别权限", Toast.LENGTH_SHORT).show();
                return false;
            }

            // 硬件判断
            if (!manager.isHardwareDetected()) {
                Toast.makeText(this, "没有指纹识别模块", Toast.LENGTH_SHORT).show();
                return false;
            }

            if (!manager.hasEnrolledFingerprints()) {
                Toast.makeText(this, "您至少需要在系统设置中添加一个指纹", Toast.LENGTH_SHORT).show();
                return false;
            }
        } else {
            Toast.makeText(this, "您的手机暂不支持指纹识别", Toast.LENGTH_SHORT).show();
            return false;
        }

        return true;
    }

完了就可以初始化指纹识别的一些东西了

完整Activity代码:

public class MainActivity extends AppCompatActivity {

    private FingerprintManager manager;
    private KeyStore keyStore;
    private static final String DEFAULT_KEY_NAME = "default_key";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();
    }

    private void init() {
        manager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
        // 判断是否支持指纹
        if (isSupportFingerPrint()) {
            initKey();
            initCipher();
        }
    }

    private boolean isSupportFingerPrint() {
        if (Build.VERSION.SDK_INT >= 23) {
            // 权限判断
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "没有指纹识别权限", Toast.LENGTH_SHORT).show();
                return false;
            }

            // 硬件判断
            if (!manager.isHardwareDetected()) {
                Toast.makeText(this, "没有指纹识别模块", Toast.LENGTH_SHORT).show();
                return false;
            }

            if (!manager.hasEnrolledFingerprints()) {
                Toast.makeText(this, "您至少需要在系统设置中添加一个指纹", Toast.LENGTH_SHORT).show();
                return false;
            }
        } else {
            Toast.makeText(this, "您的手机暂不支持指纹识别", Toast.LENGTH_SHORT).show();
            return false;
        }

        return true;
    }

    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);
        }
    }

    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) {
        final FingerPrintDialog fingerPrintDialog = new FingerPrintDialog();
        fingerPrintDialog.setCipher(cipher);
        fingerPrintDialog.setCancelable(false);
        fingerPrintDialog.show(getSupportFragmentManager(), "fingerprint");
    }
}

我们在页面中的识别对话框实在DialogFragment中实现的,这样可以利用Fragment的生命周期来处理我们的监听,因为我们总不能一直占着传感器。
DialogFragment代码:里面有详细的注释,这里就不做解释了

public class FingerPrintDialog extends DialogFragment {

    private FingerprintManager manager;
    private TextView message;
    private CancellationSignal cancel;
    // 是否主动取消
    private boolean isCancel;
    private Cipher cipher;
    private Handler handler = new Handler();
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        manager = (FingerprintManager) getContext().getSystemService(FINGERPRINT_SERVICE);
        cancel = new CancellationSignal();
        setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Material_Light_Dialog);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.dialog_fingerprint, container, false);
        message = view.findViewById(R.id.error_msg);

        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        startListening();
    }

    @Override
    public void onPause() {
        super.onPause();
        stopListening();
    }

    public void setCipher(Cipher cipher){
        this.cipher = cipher;
    }

    private void startListening() {
        isCancel = false;
        manager.authenticate(new FingerprintManager.CryptoObject(cipher), cancel, 0, new FingerprintManager.AuthenticationCallback() {
            @Override
            public void onAuthenticationError(int errorCode, CharSequence errString) {
                if (!isCancel) {
                    message.setText(errString);
                    // 超过5次错误,自动锁住
                    if (errorCode == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT) {
                        Toast.makeText(getContext(), errString, Toast.LENGTH_SHORT).show();
                        dismiss();
                    }
                }
            }

            @Override
            public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
                message.setText(helpString);
            }

            @Override
            public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
                Toast.makeText(getContext(), "指纹识别成功!", Toast.LENGTH_SHORT).show();
                Intent intent = new Intent(getActivity(), SuccessPageActivity.class);
                startActivity(intent);
            }

            @Override
            public void onAuthenticationFailed() {
                message.setText("指纹验证失败,请重试!");
                // 一秒钟后去掉提示
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        message.setText(" ");
                    }
                }, 1000);
            }
        }, null);
    }

    private void stopListening() {
        isCancel = true;
    }
}

Demo 地址:https://github.com/Trac-MacGrady/FingerPrintVerification

你可能感兴趣的:(Android)