2019独角兽企业重金招聘Python工程师标准>>>

public class FingerprintActivity extends Activity implements OnClickListener {

private FingerprintManager manager;
    private CancellationSignal signal;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fingerprint);
        findViewById(R.id.Fingerprint).setOnClickListener(this);
        manager = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE);
    }

@SuppressLint("NewApi")
    @Override
    public void onClick(View arg0) {
        switch (arg0.getId()) {
        case R.id.Fingerprint:

if (!manager.isHardwareDetected()) {
                Toast.makeText(this, "设备不支持", Toast.LENGTH_LONG).show();
                return;
            }
            KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
            if (!keyguardManager.isKeyguardSecure()) {
                Toast.makeText(this, "请设置图案锁", Toast.LENGTH_LONG).show();
                return;
            }
            if (!manager.hasEnrolledFingerprints()) {
                Toast.makeText(this, "请设置指纹", Toast.LENGTH_LONG).show();
                return;
            }

try {
                CryptoObjectHelper helper = new CryptoObjectHelper();
                signal = new CancellationSignal();
                /**
                 *FingerprintManager.authenticate(CryptoObject crypto, 
                 * CancellationSignal cancel, 
                 * int flags, AuthenticationCallback callback,
                 *  Handler handler)参数解释
                 *  1. crypto这是一个加密类的对象,指纹扫描器会使用这个对象来判断认证结果的合法性。
                 *  这个对象可以是null,但是这样的话,就意味这app无条件信任认证的结果,
                 *  虽然从理论上这个过程可能被攻击,数据可以被篡改,
                 *  这是app在这种情况下必须承担的风险。因此,建议这个参数不要置为null。
                 *  这个类的实例化有点麻烦,主要使用javax的security接口实现
                 * CryptoObjectHelper为写好的工具类直接引用即可
                 * 2.cancel 这个是CancellationSignal类的一个对象,
                 * 这个对象用来在指纹识别器扫描用户指纹的是时候取消当前的扫描操作,
                 * 如果不取消的话,那么指纹扫描器会移植扫描直到超时(一般为30s,取决于具体的厂商实现),
                 * 这样的话就会比较耗电。建议这个参数不要置为null。 
                 * 3.flags 标识位,根据上图的文档描述,这个位暂时应该为0,这个标志位应该是保留将来使用的。
                 * 4.callback 这个是FingerprintManager.AuthenticationCallback类的对象,
                 * 这个是这个接口中除了第一个参数之外最重要的参数了。
                 * 当系统完成了指纹认证过程(失败或者成功都会)后,
                 * 会回调这个对象中的接口,通知app认证的结果。这个参数不能为NULL
                 * 5.handler 这是Handler类的对象,如果这个参数不为null的话,
                 * 那么FingerprintManager将会使用这个handler中的looper来处理来自指纹识别硬件的消息。
                 * 通常来讲,开发这不用提供这个参数,可以直接置为null,
                 * 因为FingerprintManager会默认使用app的main looper来处理。
                 * 
                 * */
                manager.authenticate(helper.buildCryptoObject(), signal, 0,new MyAuthCallback(FingerprintActivity.this), null);

} catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;

default:
            break;
        }

}
    @SuppressLint("NewApi")
    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
        signal.cancel();
    }

}

MyAuthCallback 类

public class MyAuthCallback extends AuthenticationCallback{

private Context context;
    public MyAuthCallback(Context context){
        this.context = context;
    }

/**
     * 这个接口会在认证成功之后回调。我们可以在这个方法中提示用户认证成功。
     * 这里需要说明一下,如果我们上面在调用authenticate的时候,我们的CryptoObject不是null的话,
     * 那么我们在这个方法中可以通过AuthenticationResult来获得Cypher对象然后调用它的doFinal方法。
     * doFinal方法会检查结果是不是会拦截或者篡改过,如果是的话会抛出一个异常。
     * 当我们发现这些异常的时候都应该将认证当做是失败来来处理,为了安全建议大家都这么做。 
     * 
     * */
    @Override
    public void onAuthenticationSucceeded(AuthenticationResult result) {
        // TODO Auto-generated method stub
        super.onAuthenticationSucceeded(result);
        Toast.makeText(context, "成功", Toast.LENGTH_LONG).show();
        //AuthenticationResult来获得Cypher对象然后调用它的doFinal方法。
        //doFinal方法会检查结果是不是会拦截或者篡改过,如果是的话会抛出一个异常。
        //当我们发现这些异常的时候都应该将认证当做是失败来来处理,为了安全建议大家都这么做。 
        try {
            byte [] by =result.getCryptoObject().getCipher().doFinal();
            String date  = new String(by, "UTF-8");

Log.e("TAG", date);

}  catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     * 
     * 这个接口会在系统指纹认证失败的情况的下才会回调。注意这里的认证失败和上面的认证错误是不一样的,
     * 虽然结果都是不能认证。认证失败是指所有的信息都采集完整,并且没有任何异常,
     * 但是这个指纹和之前注册的指纹是不相符的;但是认证错误是指在采集或者认证的过程中出现了错误,
     * 比如指纹传感器工作异常等。也就是说认证失败是一个可以预期的正常情况,而认证错误是不可预期的异常情况。 
     * 
     * */
    @Override
    public void onAuthenticationFailed() {
        // TODO Auto-generated method stub
        super.onAuthenticationFailed();
        Toast.makeText(context, "认证失败", Toast.LENGTH_LONG).show();
    }
    /**
     * 上面的认证失败是认证过程中的一个异常情况,我们说那种情况是因为出现了不可恢复的错误,
     * 而我们这里的OnAuthenticationHelp方法是出现了可以回复的异常才会调用的。
     * 什么是可以恢复的异常呢?一个常见的例子就是:
     * 手指移动太快,当我们把手指放到传感器上的时候,如果我们很快地将手指移走的话,
     * 那么指纹传感器可能只采集了部分的信息,因此认证会失败。
     * 但是这个错误是可以恢复的,因此只要提示用户再次按下指纹,并且不要太快移走就可以解决。
     * 
     * */
    @Override
    public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
        // TODO Auto-generated method stub
        super.onAuthenticationHelp(helpCode, helpString);
        Toast.makeText(context, "再次按下指纹", Toast.LENGTH_LONG).show();
    }
    /**
     * 这个接口会再系统指纹认证出现不可恢复的错误的时候才会调用,并且参数errorCode就给出了错误码,
     * 标识了错误的原因。这个时候app能做的只能是提示用户重新尝试一遍。 
     * 
     * **/
    @Override
    public void onAuthenticationError(int errorCode, CharSequence errString) {
        // TODO Auto-generated method stub
        super.onAuthenticationError(errorCode, errString);
        Toast.makeText(context, "认证异常", Toast.LENGTH_LONG).show();
    }

}

/**
 * 参考链接:http://blog.csdn.net/baniel01/article/details/51991764
 * 
 * **/

public class CryptoObjectHelper {
    // This can be key name you want. Should be unique for the app.
    static final String KEY_NAME = "com.createchance.android.sample.fingerprint_authentication_key";

// We always use this keystore on Android.
    static final String KEYSTORE_NAME = "AndroidKeyStore";

// Should be no need to change these values.
    static final String KEY_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES;
    static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC;
    static final String ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7;
    static final String TRANSFORMATION = KEY_ALGORITHM + "/" +
            BLOCK_MODE + "/" +
            ENCRYPTION_PADDING;
    final KeyStore _keystore;

public CryptoObjectHelper() throws Exception
    {
        _keystore = KeyStore.getInstance(KEYSTORE_NAME);
        _keystore.load(null);
    }

//FingerprintManagerCompat.CryptoObject buildCryptoObject() 
    public FingerprintManager.CryptoObject buildCryptoObject() throws Exception{
        Cipher cipher = createCipher(true);
        return new FingerprintManager.CryptoObject(cipher);
    }

Cipher createCipher(boolean retry) throws Exception{
        Key key = GetKey();
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        try
        {
            cipher.init(Cipher.ENCRYPT_MODE | Cipher.DECRYPT_MODE, key);
        } catch(KeyPermanentlyInvalidatedException e)
        {
            _keystore.deleteEntry(KEY_NAME);
            if(retry)
            {
                createCipher(false);
            } else
            {
                throw new Exception("Could not create the cipher for fingerprint authentication.", e);
            }
        }
        return cipher;
    }

Key GetKey() throws Exception
    {
        Key secretKey;
        if(!_keystore.isKeyEntry(KEY_NAME))
        {
            CreateKey();
        }

secretKey = _keystore.getKey(KEY_NAME, null);
        return secretKey;
    }

void CreateKey() throws Exception
    {
        KeyGenerator keyGen = KeyGenerator.getInstance(KEY_ALGORITHM, KEYSTORE_NAME);
        KeyGenParameterSpec keyGenSpec =
                new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
        .setBlockModes(BLOCK_MODE)
        .setEncryptionPaddings(ENCRYPTION_PADDING)
        .setUserAuthenticationRequired(true)
        .build();
        keyGen.init(keyGenSpec);
        keyGen.generateKey();
    }
}

地址:https://git.oschina.net/qswwers/Android-Fingerprint.git

转载于:https://my.oschina.net/u/2355512/blog/798827

Android指纹解锁相关推荐

  1. android指纹解锁_Android指纹锁

    android指纹解锁 In this tutorial, we'll be discussing the Android Fingerprint API and implement a Finger ...

  2. android指纹解锁动画,Android8.1 SystemUI Keyguard之指纹解锁流程

    手指在指纹传感器上摸一下就能解锁,Keyguard是怎么做到的呢? 下面我们就跟着源码,解析这整个过程. 何时开始监听指纹传感器? 先来看下IKeyguardService这个binder接口有哪些回 ...

  3. Android指纹解锁源码分析

    systemServer进程会在ZygoteInit中进行创建,而ZygoteInit是Zygote进程启动的. 在systemServer进程的run方法中会启动重要服务其中就包括指纹解锁相对应的服 ...

  4. android指纹解锁分析,浅析4种手机指纹解锁方式的优劣势

    手机科技发展到目前阶段,对于指纹解锁技术已经到第二阶段了,第一阶段有三种指纹解锁方式:正面.侧面.背面,而第二阶段那就是目前还处于上阵新兵状态的屏下指纹,这里我就我个人使用的情况,来谈一下这几种指纹解 ...

  5. android指纹解锁动画,Android指纹解锁示例代码

    Android6.0及以上系统支持指纹识别解锁功能:项目中用到,特此抽离出来,备忘. 功能是这样的:在用户将app切换到后台运行(超过一定的时长,比方说30秒),再进入程序中的时候就会弹出指纹识别的界 ...

  6. Android 指纹相关调研

    Android 指纹相关调研 背景:公司产品同学提出要接入指纹,用于登录场景,提高转化率,由于之前没接触过指纹,接下来就是指纹的相关调查. 一:指纹的优势 我们传统的登录方式,需要用户输入用户名和密码 ...

  7. android keyguard,Android8.1 SystemUI Keyguard之指纹解锁流程

    手指在指纹传感器上摸一下就能解锁,Keyguard是怎么做到的呢? 下面我们就跟着源码,解析这整个过程. 何时开始监听指纹传感器? 先来看下IKeyguardService这个binder接口有哪些回 ...

  8. android开发指纹解锁,Android-指纹解锁技术

    什么是指纹解锁技术 指纹解锁技术原理理解 指纹解锁技术的优势和缺点 在Android中的应用开发 什么是指纹解锁技术 根据人的指纹来验证是否能够解锁的技术,类似于通过输入密码来解锁,都是通过一定的数字 ...

  9. android 解锁流程,Android Q 指纹解锁流程

    Android Q 指纹解锁流程 // Authentation Finger Schedule: (close Screen, Authentation with finger(Success)) ...

最新文章

  1. mysql 不同连接的事务 会嵌套_MySQL——事务
  2. 被动信息收集之RECON-NG(七)
  3. WebService(1)名词了解
  4. QTP之对测试用例的自动化过程的分解
  5. numpy(5)-astype
  6. css实现一级下拉菜单
  7. 微信小程序python解析获取用户手机号_python获取微信小程序openid及用户信息
  8. onbeforeunload与onunlond的区别
  9. bin文件编辑_为MediaWiki安装可视化编辑器VisualEditor
  10. mysql必知必会_5天学完《MySQL必知必会》学习笔记之第四天
  11. JavaEE开发之SpringMVC中的自定义拦截器及异常处理
  12. 剑指offer全书题解 (Python)【更新完毕】
  13. 华为网络技术大赛笔记——数据库基础原理
  14. 栈和队列的共同处和不同处
  15. 帝国CMS采集帝国模板程序通用
  16. 【云学习笔记】二、免费云服务器与免费域名组合打造自己的个人空间
  17. 用 FFMPEG 合并 MP4 视频
  18. 抖音充值显示服务器繁忙是什么原因,为什么抖音充值总是失败呢
  19. 【论文笔记】Radatron: Accurate Detection Using Multi-Resolution Cascaded MIMO Radar
  20. 可以计算一元二次方程复数根的模拟计算机

热门文章

  1. 如果你的网站需要免费的 SVG 插图,一定不要错过 Undraw 这个网站
  2. 计算机毕业设计,Java+MySQL 高校校园招聘系统
  3. 怎么利用外链快速上排名?
  4. html 全景图three,室内房间全景图(基于three.js)
  5. PTA 数组 7-1 计算平均分并输出低于平均分的成绩
  6. 字符串与16进制之间的转换
  7. 爆火的《看漫画学Python》出PDF版了,文末自取
  8. matlab fpga 移植,使用MATLAB,Simulink以及基于模型的设计实现把电机控制算法移植到Zynq平台...
  9. Cstyle的UEFI导读: UEFI的N种实现及差别
  10. JDBC批量插入sql-踩坑笔记