Android指纹解锁

public class FingerprintActivity extends Activity implements OnClickListener {java

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

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

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

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

        default:
            break;
        }工具

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


}
 ui

MyAuthCallback 类this

 

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

相关文章
相关标签/搜索