今天来到新公司接收到的第一个任务就是这个,调研有没有方式判断Android手机有没有锁屏密码,最初的想法是自己以前写过一下程序锁的实现原理,去监听历史任务栈,看第一个程序是不是就是程序锁,结果失败告终,问了一个以前的朋友,了解到keyguard这个类,Google一下,看Keyguard解锁屏机制这个介绍的比较详细。大概了解了锁屏的原理。不多说了,直接进入正题
Google有几种默认的锁屏方式
public static final int PASSWORD_QUALITY_ALPHABETIC = 262144;//字母密码
public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680;//字母数字密码
public static final int PASSWORD_QUALITY_BIOMETRIC_WEAK = 32768;
public static final int PASSWORD_QUALITY_COMPLEX = 393216;//复杂密码,我没有测试到
public static final int PASSWORD_QUALITY_NUMERIC = 131072;//数字密码
public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 196608; //复杂数字密码
public static final int PASSWORD_QUALITY_SOMETHING = 65536;//图案密码
public static final int PASSWORD_QUALITY_UNSPECIFIED = 0;//无密码
下面问题来了,如何获取这些状态呢,通过看KeyGuard类,了解到,这个类里面判断模式的都是通过LockPatternUtils
类去获取锁屏时的密码模式的,该类是在 frameworks 层的,Android内置的,无法直接访问。
找了一下资料,在stackoverflow上看到一个如下写的代码:
boolean isLock = android.provider.Settings.System.getInt(
getContentResolver(), Settings.System.LOCK_PATTERN_ENABLED, 0) == 1;
判断isLock真假来判断如否有屏幕锁,该方法经过测试,在无密码的状态是可以,在图案密码的情况下也是可以的,但是在数字密码的情况下不行,此方式行不通。还是换回第一种思路
在googlesources上查看LockPatternUtils代码
看到有好几个获取锁屏模式的方法:
getActivePasswordQuality():
/**
* Used by device policy manager to validate the current password
* information it has.
*/
public int getActivePasswordQuality() {
int activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
// Note we don't want to use getKeyguardStoredPasswordQuality() because we want this to
// return biometric_weak if that is being used instead of the backup
int quality =
(int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
switch (quality) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
if (isLockPatternEnabled()) {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
}
break;
case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
if (isBiometricWeakInstalled()) {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
}
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
if (isLockPasswordEnabled()) {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
}
break;
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
if (isLockPasswordEnabled()) {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
}
break;
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
if (isLockPasswordEnabled()) {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
}
break;
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
if (isLockPasswordEnabled()) {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
}
break;
}
return activePasswordQuality;
}
getKeyguardStoredPasswordQuality():
/**
* Retrieves the quality mode we're in.
* {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
*
* @return stored password quality
*/
public int getKeyguardStoredPasswordQuality() {
int quality =
(int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
// If the user has chosen to use weak biometric sensor, then return the backup locking
// method and treat biometric as a special case.
if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
quality =
(int) getLong(PASSWORD_TYPE_ALTERNATE_KEY,
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
}
return quality;
}
看注释,getKeyguardStoredPasswordQuality不建议使用,于是反射LockPatternUtils调用getActivePasswordQuality方法获取锁屏模式
代码如下:
private boolean isPhoneHasLock() {
String LOCKSCREEN_UTILS = "com.android.internal.widget.LockPatternUtils";
try {
Class> lockUtilsClass = Class.forName(LOCKSCREEN_UTILS);
Object lockUtils = lockUtilsClass.getConstructor(Context.class).newInstance(this);
try {
Method method = lockUtilsClass.getMethod("getActivePasswordQuality");
Integer mode = (Integer) method.invoke(lockUtils);
if (mode == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
return false;
} else {
return true;
}
} catch (Exception e) {
} catch (Exception e) {
Log.e("reflectInternalUtils", "ex:" + e);
}
return false;
}
通过该方法就可以判断Android手机是否有解屏密码了。
* 注意,该方法需要在屏幕点亮的广播中调用,才能及时判断用户是否有解屏密码。*
顺带把注册屏幕开关的代码也附上,以后查找方便
IntentFilter mScreenOnFilter = new IntentFilter("android.intent.action.SCREEN_ON");
this.registerReceiver(mScreenOReceiver, mScreenOnFilter);
private BroadcastReceiver mScreenOReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals("android.intent.action.SCREEN_ON")) {
isPhoneHasLock();
}
}
};
第一次用markdown写blog,写完啦。仅供同行学习,欢迎指导!