检查锁是否启用

我必须检查系统锁是否启用或不在设置。

我使用下面的行代码

boolean b = android.provider.Settings.System.getInt( getContentResolver(),Settings.System.LOCK_PATTERN_ENABLED, 0)==1; 

如果我设置了patternlocking,则返回true,如果我设置了密码pin/password ,则返回false。

我需要检查锁是否启用,或者是设置中的pattern/pin/password锁。

我的代码只是patternlocking而不是pin/passwordlocking。

所以请告诉我如何检查所有types的锁。

Solutions Collecting From Web of "检查锁是否启用"

所以这个问题是相当古老的,但似乎没有一些好的答案呢。 在一些源代码(来自Ramakrishna的链接 )研究和自我实验之后,我写了一个简单的课程来完成这项工作。

 public class LockType { private final static String PASSWORD_TYPE_KEY = "lockscreen.password_type"; /** * This constant means that android using some unlock method not described here. * Possible new methods would be added in the future releases. */ public final static int SOMETHING_ELSE = 0; /** * Android using "None" or "Slide" unlock method. It seems there is no way to determine which method exactly used. * In both cases you'll get "PASSWORD_QUALITY_SOMETHING" and "LOCK_PATTERN_ENABLED" == 0. */ public final static int NONE_OR_SLIDER = 1; /** * Android using "Face Unlock" with "Pattern" as additional unlock method. Android don't allow you to select * "Face Unlock" without additional unlock method. */ public final static int FACE_WITH_PATTERN = 3; /** * Android using "Face Unlock" with "PIN" as additional unlock method. Android don't allow you to select * "Face Unlock" without additional unlock method. */ public final static int FACE_WITH_PIN = 4; /** * Android using "Face Unlock" with some additional unlock method not described here. * Possible new methods would be added in the future releases. Values from 5 to 8 reserved for this situation. */ public final static int FACE_WITH_SOMETHING_ELSE = 9; /** * Android using "Pattern" unlock method. */ public final static int PATTERN = 10; /** * Android using "PIN" unlock method. */ public final static int PIN = 11; /** * Android using "Password" unlock method with password containing only letters. */ public final static int PASSWORD_ALPHABETIC = 12; /** * Android using "Password" unlock method with password containing both letters and numbers. */ public final static int PASSWORD_ALPHANUMERIC = 13; /** * Returns current unlock method as integer value. You can see all possible values above * @param contentResolver we need to pass ContentResolver to Settings.Secure.getLong(...) and * Settings.Secure.getInt(...) * @return current unlock method as integer value */ public static int getCurrent(ContentResolver contentResolver) { long mode = android.provider.Settings.Secure.getLong(contentResolver, PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); if (mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { if (android.provider.Settings.Secure.getInt(contentResolver, Settings.Secure.LOCK_PATTERN_ENABLED, 0) == 1) { return LockType.PATTERN; } else return LockType.NONE_OR_SLIDER; } else if (mode == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) { String dataDirPath = Environment.getDataDirectory().getAbsolutePath(); if (nonEmptyFileExists(dataDirPath + "/system/gesture.key")) { return LockType.FACE_WITH_PATTERN; } else if (nonEmptyFileExists(dataDirPath + "/system/password.key")) { return LockType.FACE_WITH_PIN; } else return FACE_WITH_SOMETHING_ELSE; } else if (mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC) { return LockType.PASSWORD_ALPHANUMERIC; } else if (mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC) { return LockType.PASSWORD_ALPHABETIC; } else if (mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { return LockType.PIN; } else return LockType.SOMETHING_ELSE; } private static boolean nonEmptyFileExists(String filename) { File file = new File(filename); return file.exists() && file.length() > 0; } } 

现在你只需要做

 int lockType = LockType.getCurrent(getContentResolver()); 

从你的Activity类。 如果你想检查一些锁的types,那么只需使用switch语句

 switch (lockType) { case LockType.FACE_WITH_PATTERN: case LockType.FACE_WITH_PIN: case LockType.PATTERN: /* do something */ break; } 

或者如果你只想要“面部解锁”,不pipe用哪一种附加的方法

 if (lockType >= LockType.FACE_WITH_PATTERN && lockType <= LockType.FACE_WITH_SOMETHING_ELSE) { /* do something */ } 

编辑:所以,我在3手机上testing这个类,它似乎并不是所有的手机正确检测脸部解锁方法。 在某些电话上, PASSWORD_QUALITY_BIOMETRIC_WEAK返回并且在另一个电话上返回PASSWORD_QUALITY_SOMETHING 。 我想我们可以检查一些包含脸部信息的文件解锁是否存在而不是空的,类似于密码/ PIN和图案方法。 但现在我不知道这个文件在哪里。

EDIT2:看起来像我发现后,Android 4.3的代码研究的问题。 这是因为锁设置被移动到新的位置(/data/system/locksettings.db),似乎没有办法从这个数据库(rw-rw —-权限和“系统”所有者和组只有root可以做这个工作)。

小心,这个方法好像也过时了! 谢谢Dantalian的提示!

LockPatternUtils是一个私人类。 但是你可以通过一些思考来阅读locking模式:(适用于Nexus5,Android 4.4.4)

 private boolean isDeviceSecured() { String LOCKSCREEN_UTILS = "com.android.internal.widget.LockPatternUtils"; try { Class<?> lockUtilsClass = Class.forName(LOCKSCREEN_UTILS); // "this" is a Context, in my case an Activity Object lockUtils = lockUtilsClass.getConstructor(Context.class).newInstance(this); Method method = lockUtilsClass.getMethod("getActivePasswordQuality"); int lockProtectionLevel = (Integer)method.invoke(lockUtils); // Thank you esme_louise for the cast hint if(lockProtectionLevel >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { return true; } } catch (Exception e) { Log.e("reflectInternalUtils", "ex:"+e); } return false; } 

@Peter Pint和esme_louise

谢谢,你的解决scheme让我走了。 要找出是否启用了屏幕locking,我可以进一步简化您的方法。 对于刷卡或正确locking(PIN,PW,面部解锁等),这将返回false,并为“None”选项返回false。 为了区分滑动和正确的locking方法之一,我使用KeyguardManager.isKeyguardSecure()

它应该与API等级14+一起工作:

 private boolean isLockScreenDisabled(Context context) { String LOCKSCREEN_UTILS = "com.android.internal.widget.LockPatternUtils"; try { Class<?> lockUtilsClass = Class.forName(LOCKSCREEN_UTILS); // "this" is a Context, in my case an Activity Object lockUtils = lockUtilsClass.getConstructor(Context.class).newInstance(context); Method method = lockUtilsClass.getMethod("isLockScreenDisabled"); boolean isDisabled = Boolean.valueOf(String.valueOf(method.invoke(lockUtils))); return isDisabled; } catch (Exception e) { Log.e("reflectInternalUtils", "ex:"+e); } return false; } 

更新:我使用新的方法isDeviceSecure()将代码调整为android M。 但是,这不能区分“无”和“滑动”。 此外,该方法已经开始在5.x(我认为5.1.1)与SecurityException失败。 这需要在catch块中额外的破解。

为了检测用户是否不在,USER_PRESTENT将会在设备被激活/解锁时被广播isDeviceSecure()已经足够好了,我很高兴摆脱了将来发布的易碎reflection的东西。

 private boolean isLockScreenDisabled(Context context) { // Starting with android 6.0 calling isLockScreenDisabled fails altogether because the // signature has changed. There is a new method isDeviceSecure which, however, does // not allow the differentiation between lock screen 'None' and 'Swipe. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ KeyguardManager keyguardMgr = (KeyguardManager) context .getSystemService(Context.KEYGUARD_SERVICE); // But luckily there is no 'Automatically lock x minutes after sleep' option when // 'Swipe' is set which means that as soon as the screen is off, switching back on // requires a swipe which results in a USER_PRESENT broadcast. return !keyguardMgr.isDeviceSecure(); } String LOCKSCREEN_UTILS = "com.android.internal.widget.LockPatternUtils"; try { Class<?> lockUtilsClass = Class.forName(LOCKSCREEN_UTILS); Object lockUtils = lockUtilsClass.getConstructor(Context.class).newInstance(context); Method method = lockUtilsClass.getMethod("isLockScreenDisabled"); // Starting with android 5.x this fails with InvocationTargetException // (caused by SecurityException - MANAGE_USERS permission is required because // internally some additional logic was added to return false if one can switch between several users) // if (Screen Lock is None) { // ... exception caused by getting all users (if user count) // } else { // return false; // } // -> therefore if no exception is thrown, we know the screen lock setting is // set to Swipe, Pattern, PIN/PW or something else other than 'None' boolean isDisabled; try { isDisabled = Boolean.valueOf(String.valueOf(method.invoke(lockUtils))); } catch (InvocationTargetException ex) { Log.w(TAG, "Expected exception with screen lock type equals 'None': " + ex); isDisabled = true; } return isDisabled; } catch (Exception e) { Log.e(TAG, "Error detecting whether screen lock is disabled: " + e); e.printStackTrace(); } return false; } 

这是使用它的方法:它决定了用户是否缺席的方式下次打开屏幕(如果没有设置屏幕locking)或设备解锁(包括滑动)广播USER_PRESENT_ACTION。

 public boolean isUserAbsent(Context context) { KeyguardManager kgMgr = (KeyguardManager) context .getSystemService(Context.KEYGUARD_SERVICE); boolean isDeviceLocked = kgMgr.inKeyguardRestrictedInputMode(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { // there was no 'None' option for screen lock in the olden days return isDeviceLocked; } PowerManager powerManager = (PowerManager) context .getSystemService(Context.POWER_SERVICE); if (isLockScreenDisabled(context)) { // Lock Type 'None' (USER_PRESENT is broadcast when screen comes on) if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { // android 3.0 - 4.1: we have a problem with 'None' because // user_present is never broadcast! UserLog.log(TAG, context, "No screen lock on android 3.0 - 4.1: User-presence will not be detected! Please switch to 'Swipe'"); } return !powerManager.isInteractive(); } else { // Lock Type 'Swipe' or proper lock (USER_PRESENT is broadcast when device is unlocked) return isDeviceLocked; } } 

从Android 6.0 Marshmallow(SDK 23)开始,有一个新的方法来完成这个任务。 检查这个

http://developer.android.com/reference/android/app/KeyguardManager.html#isDeviceSecure(&#xFF09;

用法:

 public static boolean isDeviceSecure(Context context) { if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { KeyguardManager manager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); return manager.isDeviceSecure(); } // reflection code from the other answers here ... } 

以上是困难的方法。 使用KeyguardManager.isKeyguardSecure()

 KeyguardManager km = (KeyguardManager)getApplicationContext().getSystemService(Context.KEYGUARD_SERVICE); if(km.isKeyguardSecure()) Toast.makeText(getApplicationContext(), "locked", Toast.LENGTH_LONG).show(); else Toast.makeText(getApplicationContext(), "Unlocked", Toast.LENGTH_LONG).show(); 

@Peter Pint

 int lockProtectionLevel = (int)method.invoke(lockUtils); 

应该是…

 int lockProtectionLevel = Integer.valueOf(String.valueOf(method.invoke(lockUtils))); 

但是,否则,就在! 我已经提出了你的答案。

如果你谈论屏幕locking,你可以尝试设置特定的BroadcastReceiver并从Android系统听特定的Itents。

希望,它可以帮助你。 对不起,如果我不明白你:)