zoukankan      html  css  js  c++  java
  • Android 中指纹识别

    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

  • 相关阅读:
    49个128*128像素的天气png图标
    非常漂亮的千千静听皮肤[Warp]出自梦梦的作品
    腾讯的面试题
    什么是函数参数,如何传递函数参数
    我看了这视频,情不自禁的笑了
    WindowBlinds基础使用教程
    晒工资网站
    一个可以搜索word文档,电子表格,PDF,幻灯片的搜索引擎
    网页设计常用png小图标一套
    使用U盘时候的”无法停用通用卷”的解决办法
  • 原文地址:https://www.cnblogs.com/changyiqiang/p/11506692.html
Copyright © 2011-2022 走看看