安卓6后,开始官方支持指纹识别的api。主要用到的类是FingerprintManager。但是该类在低于6的安卓环境上运行会崩溃。因此有了衍生的FingerprintManagerCompat和FingerprintManagerCompat23。其中23这个版本包含了对23之后的api的特殊处理,而FingerprintManagerCompat内部对api进行了判断,我们只需要直接调用它就好。
static {
if (Build.VERSION.SDK_INT >= 23) {
IMPL = new Api23FingerprintManagerCompatImpl();
} else {
IMPL = new LegacyFingerprintManagerCompatImpl();
}
}
这里我教大家如何入门的使用这个官方的指纹api。有人就要问,为什么叫入门。是因为
这个方法里面的第一个参数 FingerprintManagerCompat.CryptoObject。这个参数才是指纹识别的关键。比较复杂,有兴趣的童鞋可以度娘一下用法。我在demo里面没有涉及到它,只是简单的实现指纹别的基础功能,写了一个辅助类:
public class FingerPrintHelper {
static final String PREFERENCE_FINGER_PRINT_CONFIG_NAME = "fingerPrint";
static final String PREFERENCE_KEY_IS_SUPPORT_FINGER_PRINT = "isSupportFingerPrint";
static final String PREFERENCE_KEY_HAS_EVER_CHECKED = "hasEverCheckedSupportFingerPrint";
static final String TAG = "fingerPrint";
public static SharedPreferences getConfig() {
return ContextUtil.getContext().getSharedPreferences(PREFERENCE_FINGER_PRINT_CONFIG_NAME, Context.MODE_PRIVATE);
}
public static void clearConfig() {
getConfig().edit().clear().commit();
}
private static void setSupportFingerPrint(boolean isSupport) {
SharedPreferences.Editor editor = getConfig().edit();
editor.putBoolean(PREFERENCE_KEY_IS_SUPPORT_FINGER_PRINT, isSupport);
editor.commit();
}
/**
* 判断当前手机支不支持指纹识别
* 这种方法仅限于api低于安卓6.0但是手机厂家有会支持的手机。如小米,VIVO的一些机型。
* 可取性不是很好。
*
* @return
*/
public static boolean isSupportFingerPrint() {
boolean res = false;
if (!hasEverCheckedFingerPrintSupport()) {
res = checkSupportFingerPrint();
setSupportFingerPrint(res);
setHasEverCheckedFingerPrintSupport(true);
} else {
res = getConfig().getBoolean(PREFERENCE_KEY_IS_SUPPORT_FINGER_PRINT, false);
}
return res;
}
private static boolean hasEverCheckedFingerPrintSupport() {
return getConfig().getBoolean(PREFERENCE_KEY_HAS_EVER_CHECKED, false);
}
private static void setHasEverCheckedFingerPrintSupport(boolean hasEver) {
SharedPreferences.Editor editor = getConfig().edit();
editor.putBoolean(PREFERENCE_KEY_HAS_EVER_CHECKED, hasEver);
editor.commit();
}
/**
* 检测当前的手机支不支持指纹识别,实际上就是判断一下当前的手机API有没有{@link android.hardware.fingerprint.FingerprintManager}这个类
*
* @return
*/
private static boolean checkSupportFingerPrint() {
boolean result = false;
try {
Class.forName("android.hardware.fingerprint.FingerprintManager"); // 通过反射判断是否存在该类
result = true;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return result;
}
/**
* 开始进行指纹识别
* @param context
* @param cancellationSignal 指纹识别取消的控制器
* @param callback 指纹识别回调函数
*/
public static void doFingerPrint(Context context, android.support.v4.os.CancellationSignal cancellationSignal, FingerprintManagerCompat.AuthenticationCallback callback) {
FingerprintManagerCompat managerCompat = FingerprintManagerCompat.from(context);
managerCompat.authenticate(null, 0, cancellationSignal, callback, null);
}
/**
* 官方写法,用于判断是否支持指纹识别
*
* @param context
* @return
*/
public static boolean isHardWareDetected(Context context) {
return FingerprintManagerCompat.from(context).isHardwareDetected();
}
/**
* 官方写法,当前手机是否设置过指纹
*
* @param context
* @return
*/
public static boolean hasEnrolledFingerPrint(Context context) {
return FingerprintManagerCompat.from(context).hasEnrolledFingerprints();
}
}
然后再自定义对话框,实现这个功能:
public class FingerPrintDialog extends AbstractDialogFragment implements View.OnClickListener{
private Button btn_cancel;
private ImageView iv_back;
private ImageView iv_icon_finger;
private TextView tv_title;
private TextView tv_desc;
private ProgressBar mProgressBar;
private boolean enableVibrator=true;//是否开启震动
private Vibrator mVibrator;
private CancellationSignal mCancellationSignal;//指纹识别取消控制器
private static final int COLOR_ERROR= R.color.colorAccent;
private static final int COLOR_WARN=R.color.orange;
private static final int COLOR_SUCCESS=R.color.green;
private boolean isSuccess;//指纹识别是否成功
private OnDismissListener mOnDismissListener;
public void setOnDismissListener(OnDismissListener onDismissListener) {
mOnDismissListener = onDismissListener;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mVibrator= (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE);
}
public static FingerPrintDialog showDialog(FragmentActivity activity, boolean cancelable, String tag, OnDismissListener onDismissListener){
FingerPrintDialog dialog=new FingerPrintDialog();
dialog.setCancelable(cancelable);
dialog.setOnDismissListener(onDismissListener);
dialog.show(activity.getSupportFragmentManager(),tag);
dialog.startFingerPrint();
return dialog;
}
public static FingerPrintDialog showDialog(FragmentActivity activity, OnDismissListener onDismissListener){
return showDialog(activity,true,"",onDismissListener);
}
@Override
protected int setLayoutId() {
return R.layout.dialog_finger_print;
}
@Override
protected void bindView(View convertView, Bundle savedInstanceState) {
btn_cancel=findViewByIdAuto(R.id.btn_cancel);
iv_back=findViewByIdAuto(R.id.iv_back);
tv_title=findViewByIdAuto(R.id.tv_title);
tv_desc=findViewByIdAuto(R.id.tv_desc);
iv_icon_finger=findViewByIdAuto(R.id.iv_icon_finger);
mProgressBar=findViewByIdAuto(R.id.progress);
}
@Override
protected void bindEvents(View convertView, Bundle savedInstanceState) {
Bundle data=getArguments();
iv_back.setOnClickListener(this);
btn_cancel.setOnClickListener(this);
setStyle(getString(R.string.finger_print_default),STYLE_DEFAULT);
}
@Override
public void onClick(View v) {
if(v==btn_cancel){
dismissAllowingStateLoss();
}else if(v==iv_back){
dismissAllowingStateLoss();
}
}
@Override
public void onDismiss(DialogInterface dialog) {
if(mCancellationSignal!=null){
mCancellationSignal.cancel();
mCancellationSignal=null;
}
if(mOnDismissListener!=null){
mOnDismissListener.onDismiss(isSuccess);
}
super.onDismiss(dialog);
}
@Override
protected int setWindowWidth() {
return (int) (super.setWindowWidth()*0.8);
}
private void startFingerPrint(){
mCancellationSignal=new CancellationSignal();
FingerPrintHelper.doFingerPrint(ContextUtil.getContext(), mCancellationSignal,new FingerprintManagerCompat.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
super.onAuthenticationError(errMsgId, errString);
setStyle(errString.toString(),STYLE_ERROR);
startVibrate();
}
@Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
super.onAuthenticationHelp(helpMsgId, helpString);
setStyle(helpString.toString(),STYLE_WARN);
startVibrate();
}
@Override
public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
setStyle(getString(R.string.finger_print_success),STYLE_SUCCESS);
startVibrate();
isSuccess=true;
(new Handler()).postDelayed(new Runnable() {
@Override
public void run() {
dismissAllowingStateLoss();
}
},1000);
}
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
setStyle(getString(R.string.finger_print_failed),STYLE_ERROR);
startVibrate();
}
});
}
public void startVibrate(){
if(enableVibrator && mVibrator!=null){
mVibrator.vibrate(200);
}
}
private static final int STYLE_DEFAULT=0;
private static final int STYLE_SUCCESS=1;
private static final int STYLE_ERROR=-1;
private static final int STYLE_WARN=2;
private void setStyle(String msg, int style){
tv_desc.setText(msg);
mProgressBar.setVisibility(View.VISIBLE);
switch (style){
case STYLE_ERROR:
tv_desc.setTextColor(ColorKit.getColorSrc(COLOR_ERROR));
DrawableKit.setDrawableTintColor(iv_icon_finger.getDrawable(),COLOR_ERROR);
break;
case STYLE_WARN:
tv_desc.setTextColor(ColorKit.getColorSrc(COLOR_WARN));
DrawableKit.removeDrawableTintColor(iv_icon_finger.getDrawable());
break;
case STYLE_SUCCESS:
tv_desc.setTextColor(ColorKit.getColorSrc(COLOR_SUCCESS));
DrawableKit.setDrawableTintColor(iv_icon_finger.getDrawable(),COLOR_SUCCESS);
mProgressBar.setVisibility(View.GONE);
break;
default:
tv_desc.setTextColor(ColorKit.getColorSrc(R.color.white_gray));
DrawableKit.removeDrawableTintColor(iv_icon_finger.getDrawable());
break;
}
}
/**
* 描述:对话框消失的时候的监听器
*
* <br>作者: cjs
* <br>创建时间: 2017/11/8 0008 15:26
* <br>邮箱: chenjunsen@outlook.com
* @version 1.0
*/
public interface OnDismissListener{
/**
* 对话框消失的时候
* @param isSuccess 验证是否成功
*/
void onDismiss(boolean isSuccess);
}
}
用法在此:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(FingerPrintHelper.isHardWareDetected(this) && FingerPrintHelper.hasEnrolledFingerPrint(this)){
FingerPrintDialog.showDialog(this, false, "fingerPrint", new FingerPrintDialog.OnDismissListener() {
@Override
public void onDismiss(boolean isSuccess) {
if(isSuccess){
setContentView(R.layout.activity_main);
}else{
finish();
System.exit(0);
}
}
});
}else{
Toast.makeText(this,"当前机型不支持安卓原生指纹系统或者你还没有设置指纹密码",Toast.LENGTH_LONG).show();
setContentView(R.layout.activity_main);
}
}
}
PS:目前我用三星S8 plus测试通过,其余机型,有兴趣的童鞋可以下载自测。
- SimpleNews新闻客户端(10920次查看,366次下载)
- DragGridView拖拽排序(5973次查看,72次下载)
- bihu逼乎(8624次查看,117次下载)
- 福利GankMM(3494次查看,26次下载)
- Yhb-2.0有惠报(3160次查看,32次下载)