设置指纹识别模块分析
Posted andy连长
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设置指纹识别模块分析相关的知识,希望对你有一定的参考价值。
设置指纹识别模块分析
一, 指纹项的加载
首先我们从指纹项的布局加载开始分析,从手机设置下边直观的可以发现,指纹项是放在二级菜单安全菜单里边的,下面我们就从代码里边分析一下,指纹项是如何被加载进来的。
首先我们应该从SecuritySettings.java的加载开始分析,在该类起来之后,在它的
@Override
public void onResume()
super.onResume();
// Make sure wereload the preference hierarchy since some of these settings
// depend on others...
createPreferenceHierarchy();
//省略代码
我们可以看到调用了createPreferenceHierarchy();方法,下面看看这个方法:
private PreferenceScreen createPreferenceHierarchy() PreferenceScreen root = getPreferenceScreen(); if (root != null) root.removeAll(); addPreferencesFromResource(R.xml.security_settings);//通过布局文件加载一些基础的布局 root = getPreferenceScreen(); //代码省略
if (mProfileChallengeUserId != UserHandle.USER_NULL && mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId)) addPreferencesFromResource(R.xml.security_settings_profile); addPreferencesFromResource(R.xml.security_settings_unification); final int profileResid = getResIdForLockUnlockScreen( getActivity(), mLockPatternUtils, mManagedPasswordProvider, mProfileChallengeUserId); addPreferencesFromResource(profileResid); maybeAddFingerprintPreference(root, mProfileChallengeUserId);
//从这里看到了我们想要的加载指纹的布局,下边看看这个方法内容:
//代码省略
private void maybeAddFingerprintPreference(PreferenceGroup securityCategory, int userId) Preference fingerprintPreference = FingerprintSettings.getFingerprintPreferenceForUser( securityCategory.getContext(), userId); if (fingerprintPreference != null) securityCategory.addPreference(fingerprintPreference);
这个方法看起来比较简单,首先是获取到这个fingerprintPreference,然后直接加载到securityCategory,从而让指纹项显示出来。但是点击事件却是在下边这个方法的,该方法getFingerprintPreferenceForUser()是在FingerprintSettings的一个全局方法,如下:
public static Preference getFingerprintPreferenceForUser(Context context, final int userId) FingerprintManager fpm = (FingerprintManager) context.getSystemService( Context.FINGERPRINT_SERVICE); if (fpm == null || !fpm.isHardwareDetected()) Log.v(TAG, "No fingerprint hardware detected!!"); return null; Preference fingerprintPreference = new Preference(context); fingerprintPreference.setKey(KEY_FINGERPRINT_SETTINGS);//设置点击的键 fingerprintPreference.setTitle(R.string.security_settings_fingerprint_preference_title); final List<Fingerprint> items = fpm.getEnrolledFingerprints(userId); final int fingerprintCount = items != null ? items.size() : 0; final String clazz;
//这个直接决定点击指纹项要启动的是哪个界面 if (fingerprintCount > 0) fingerprintPreference.setSummary(context.getResources().getQuantityString( R.plurals.security_settings_fingerprint_preference_summary, fingerprintCount, fingerprintCount)); clazz = FingerprintSettings.class.getName(); else fingerprintPreference.setSummary( R.string.security_settings_fingerprint_preference_summary_none); //slt yangxinzhao modified for lenovo UI clazz = FingerprintEnrollIntroduction.class.getName();
//这里是最关键的地方,为指纹项设置点击监听, fingerprintPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() @Override public boolean onPreferenceClick(Preference preference) final Context context = preference.getContext(); final UserManager userManager = UserManager.get(context); if (Utils.startQuietModeDialogIfNecessary(context, userManager, userId)) return false; Intent intent = new Intent(); intent.setClassName("com.android.settings", clazz); intent.putExtra(Intent.EXTRA_USER_ID, userId); context.startActivity(intent); return true; ); return fingerprintPreference;
从这个方法中可以看出主要是做了一些指纹界面的初始化工作。其中有个比较关键的判断条件就是fingerprintCount,如果指纹的个数不为0,那么就点击菜单项打开的是指纹注册引导界面,即FingerprintEnrollIntroduction,否则打开的就是指纹项界面,即FingerprintSettings。到此,整个指纹界面的加载流程就梳理完了。
二, 指纹界面处理逻辑
1,首先来看一下指纹界面(FingerprintSettings.java),该类继承SubSettings.java
而此类又是继承自SettingsActivity.java,首先我们从OnCreate()函数开始看:
@Override public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); CharSequence msg = getText(R.string.security_settings_fingerprint_preference_title); setTitle(msg);
可以看到这个函数里边仅仅只是设置了这个activity的title。下边再看一个方法:
@Override public Intent getIntent() Intent modIntent = new Intent(super.getIntent()); modIntent.putExtra(EXTRA_SHOW_FRAGMENT,
FingerprintSettingsFragment.class.getName());
return modIntent;
从此方法可以看到这个activity是绑定的FingerprintSettingsFragment,所以我们接下来只需要分析这个fragment就可以了。
2,分析此fragment还是先从onCreate()函数开始分析:
@Override public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); if (savedInstanceState != null) mToken = savedInstanceState.getByteArray( ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); mLaunchedConfirm = savedInstanceState.getBoolean( KEY_LAUNCHED_CONFIRM, false); mUserId = getActivity().getIntent().getIntExtra( Intent.EXTRA_USER_ID, UserHandle.myUserId()); Activity activity = getActivity(); mFingerprintManager = (FingerprintManager) activity.getSystemService( Context.FINGERPRINT_SERVICE); // Need to authenticate a session token if none if (mToken == null && mLaunchedConfirm == false) mLaunchedConfirm = true;//当进入该界面,就把标志位置为true launchChooseOrConfirmLock();//启动密码确认界面
从这个方法可以看到这里其实并没有做什么,只是进行了一些相关数据的初始化。但有一点需要注意,mLaunchedConfirm这变量表示是否需要进行密码确认,如果为false就需要进行密码确认,从而启动对应的密码确认界面,具体的方法如下:
private void launchChooseOrConfirmLock() Intent intent = new Intent(); long challenge = mFingerprintManager.preEnroll(); ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this); if (!helper.launchConfirmationActivity(CONFIRM_REQUEST, getString(R.string.security_settings_fingerprint_preference_title), null, null, challenge, mUserId)) intent.setClassName("com.android.settings", ChooseLockGeneric.class.getName()); intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); intent.putExtra(Intent.EXTRA_USER_ID, mUserId); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); intent.putExtra(Intent.EXTRA_USER_ID, mUserId); startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
接下来我们就看看这个fragment的onResume()方法:
@Override public void onResume() super.onResume(); // Make sure we reload the preference hierarchy since fingerprints may be added, // deleted or renamed. updatePreferences();
从这里可以看到整个指纹界面就是从这里开始创建的,具体代码如下:
private void updatePreferences() createPreferenceHierarchy();//进行界面的创建 retryFingerprint();//认证指纹,也就是在这个activity起来之后就可以直接认证指纹了
下面我们具体看看指纹界面是如何创建的,指纹界面包含两个部分,一部分是最下边的指纹使用介绍,这部分仅仅是一个textview,还有一部分就是每个指纹选项和添加指纹选项,我们稍后介绍,先来看看指纹介绍是如何添加的,代码如下:
@Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) super.onViewCreated(view, savedInstanceState); TextView v = (TextView) LayoutInflater.from(view.getContext()).inflate( R.layout.fingerprint_settings_footer, null); EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled( getActivity(), DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId); v.setText(getText(admin != null ? R.string.security_settings_fingerprint_enroll_disclaimer_lockscreen_disabled : R.string.security_settings_fingerprint_enroll_disclaimer)); /*end of slt yangxinzhao modified for lenovo UI */ setFooterView(v);
这部分代码很简单,仅仅是在onViewCreated()方法里边添加一个布局文件fingerprint_settings_footer.xml,这个布局文件仅仅是一个LinkTextView,仅作为显示文字之用,我们主要看看第二部分的指纹选项和添加指纹选项是如何加载的,代码如下:
private PreferenceScreen createPreferenceHierarchy() PreferenceScreen root = getPreferenceScreen(); if (root != null) root.removeAll(); addPreferencesFromResource(R.xml.security_settings_fingerprint);//加载基础布局,实际上是一个空布局 root = getPreferenceScreen(); addFingerprintItemPreferences(root);//添加指纹条目,最多能够添加五个指纹 setPreferenceScreen(root); return root;
我们从security_settings_fingerprint.xml可以看到这是一个空的布局文件,里边的选项都是通过动态加载进去的,具体代码可以看方法addFingerprintItemPreferences(root),
private void addFingerprintItemPreferences(PreferenceGroup root) root.removeAll(); final List<Fingerprint> items = mFingerprintManager.getEnrolledFingerprints(mUserId); final int fingerprintCount = items.size();
//通过for循环进行指纹条目的添加,同时设置各个属性已经点击监听 for (int i = 0; i < fingerprintCount; i++) final Fingerprint item = items.get(i); FingerprintPreference pref = new FingerprintPreference(root.getContext()); pref.setKey(genKey(item.getFingerId())); pref.setTitle(item.getName()); pref.setFingerprint(item); pref.setPersistent(false); pref.setIcon(R.drawable.ic_fingerprint_24dp); root.addPreference(pref); pref.setOnPreferenceChangeListener(this); /*slt yangxinzhao added for lenovo UI 20170118*/ pref.setIcon(R.drawable.ic_fingerprint_list_icon); /*end of added*/
//添加指纹选项,并且设置对应的属性以及点击监听 Preference addPreference = new Preference(root.getContext()); addPreference.setKey(KEY_FINGERPRINT_ADD); addPreference.setTitle(R.string.fingerprint_add_title); addPreference.setIcon(R.drawable.ic_add_24dp); root.addPreference(addPreference); addPreference.setOnPreferenceChangeListener(this); updateAddPreference();
这部分其实主要也是分为两部分进行添加的,第一部分就是指纹条目,通过final List<Fingerprint> items = mFingerprintManager.getEnrolledFingerprints(mUserId);
将所有的指纹条目读取出来,使用for循环进行创建的条目,每一个条目包含了指纹条目的键,指纹的id,对应的图标等属性,同时为每个条目设置点击监听,pref.setOnPreferenceChangeListener(this);
同时在这个里边也添加了添加指纹选项,到此,整个指纹界面的的布局已经添加完成了,后边这个界面还会进行冬天更新,比如添加和删除指纹的操作都会更新这个界面,后面继续分析。
3,指纹的添加
我们前边说过为添加指纹选项设置了点击事件监听,我们看看这个点击事件:
@Override public boolean onPreferenceTreeClick(Preference pref) final String key = pref.getKey(); if (KEY_FINGERPRINT_ADD.equals(key)) Intent intent = new Intent(); intent.setClassName("com.android.settings", FingerprintEnrollEnrolling.class.getName()); intent.putExtra(Intent.EXTRA_USER_ID, mUserId); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); startActivityForResult(intent, ADD_FINGERPRINT_REQUEST); else if (pref instanceof FingerprintPreference) FingerprintPreference fpref = (FingerprintPreference) pref; final Fingerprint fp =fpref.getFingerprint(); showRenameDeleteDialog(fp); return super.onPreferenceTreeClick(pref); return true;
通过不同的Key判断,处理对应的事件,当点击添加指纹选项时,执行了如下代码:
Intent intent = new Intent();
intent.setClassName("com.android.settings",
FingerprintEnrollEnrolling.class.getName());
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
startActivityForResult(intent, ADD_FINGERPRINT_REQUEST);
我们可以看到是启动了FingerprintEnrollEnrolling这个类进行指纹的添加,并且给返回了
ADD_FINGERPRINT_REQUEST这个结果。这个指纹注册的过程我们暂时不作关注,只要知道注册完指纹之后返回了结果就可以了,有兴趣的可以继续研究一下指纹的注册。
当添加完指纹返回之后,重新回到onResume()方法,执行界面更新,这时候新添加的指纹就会出现在指纹界面。
4,指纹的删除
前边也说过,添加指纹条目的时候已经为指纹条目设置了点击事件监听,当点击指纹条目的时候直接调用了方法showRenameDeleteDialog(fp);参数为传入的指纹,具体方法如下:
private void showRenameDeleteDialog(final Fingerprint fp) RenameDeleteDialog renameDeleteDialog = new RenameDeleteDialog(); Bundle args = new Bundle(); args.putParcelable("fingerprint", fp); renameDeleteDialog.setArguments(args); renameDeleteDialog.setTargetFragment(this, 0); renameDeleteDialog.show(getFragmentManager(), RenameDeleteDialog.class.getName());
从代码中可以看到该方法主要是新建了一个RenameDeleteDialog,并且将指纹这个数据传进去了,那么我们就看看这个dialog,因为这个dialog的代码比较多,我们只关注他的删除按钮和确定按钮事件,先看确定按钮事件,也就是为指纹进行改名操作,其代码如下:
@Override public void onClick(DialogInterface dialog, int which) final 模块分析OpenCV和Zbar两个Python模块实现二维码和条形码识别