检查锁是否已启用

Ram*_*hna 29 android

我必须检查设置中是否启用了系统锁定.

我使用下面的行代码

boolean b = android.provider.Settings.System.getInt(
                        getContentResolver(),Settings.System.LOCK_PATTERN_ENABLED, 0)==1;
Run Code Online (Sandbox Code Playgroud)

如果我设置了pattern锁,则返回true,如果设置了密码,则返回false pin/password.

我需要检查锁是否已启用它是否pattern/pin/password锁定设置.

我的代码只能pattern锁定不pin/password锁定.

所以请告诉我如何检查所有类型的锁.

s.m*_*aks 19

所以这个问题已经很老了,但似乎还没有一些好的答案.在一些源代码(来自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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你只需要做

int lockType = LockType.getCurrent(getContentResolver());
Run Code Online (Sandbox Code Playgroud)

来自您的Activity类.如果要检查一些锁类型,请使用switch语句

switch (lockType) 
{
    case LockType.FACE_WITH_PATTERN:
    case LockType.FACE_WITH_PIN:
    case LockType.PATTERN:
        /* do something */
        break;
}
Run Code Online (Sandbox Code Playgroud)

或者如果您只想要"面部解锁",无论使用哪种附加方法

if (lockType >= LockType.FACE_WITH_PATTERN && lockType <= LockType.FACE_WITH_SOMETHING_ELSE)
{
    /* do something */
}
Run Code Online (Sandbox Code Playgroud)

编辑:所以,我在3部手机上测试这个类,似乎并非所有手机都能正确检测到面部解锁方法.在某些手机上PASSWORD_QUALITY_BIOMETRIC_WEAK回报和PASSWORD_QUALITY_SOMETHING上anothers.我想我们可以检查一些包含面部解锁信息的文件是否存在而不是空的,类似于密码/引脚和模式方法.但是现在我不知道这个文件到底在哪里.

EDIT2:看起来我在android 4.3 sorce代码研究后发现了问题.那是因为锁定设置被移动到新位置(/data/system/locksettings.db)并且似乎没有办法从这个数据库获取这些设置(rw-rw ----权限和"系统"所有者和组所以只有root才能完成这项工作).

  • 据我所知,这种方法不适用于某些三星和索尼设备.至少PIN锁定返回NONE_OR_SLIDER.其他人遇到过这个问题吗? (2认同)

Pet*_*int 13

小心,这种方法似乎也已经过时了!谢谢Dantalian的暗示!

LockPatternUtils是一个私有类.但你可以通过一些反思阅读锁定模式:(适用于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;
}
Run Code Online (Sandbox Code Playgroud)

  • 它不适用于Android 6.0,方法不存在.小心这个 (4认同)

And*_*dyB 11

从Android 6.0 Marshmallow(SDK 23)开始,有一种新方法可以完成此任务.检查一下

http://developer.android.com/reference/android/app/KeyguardManager.html#isDeviceSecure()

用法:

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
...
}
Run Code Online (Sandbox Code Playgroud)


小智 7

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();
Run Code Online (Sandbox Code Playgroud)


Man*_*ani 6

@Peter Pint和esme_louise

谢谢,你的解决方案让我走了.要确定是否启用了屏幕锁定,我可以进一步简化您的方法.滑动或正确锁定(PIN,PW,面部解锁等)返回false,对"选项"选项返回false.为了区分滑动和正确的锁定方法之一,我使用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;
}
Run Code Online (Sandbox Code Playgroud)

更新:我使用新方法isDeviceSecure()将代码改编为android M. 但是,这不允许区分"无"和"滑动".此外,该方法已经开始在5.x(我认为5.1.1)失败,带有SecurityException.这需要在catch块中额外进行攻击.

为了检测用户是否缺席以及当设备被激活/解锁时将播放USER_PRESTENT isDeviceSecure()已经足够好了,我很高兴为将来的版本摆脱脆弱的反射内容.

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;
}
Run Code Online (Sandbox Code Playgroud)

这是使用它的方法:它确定用户是否以下次打开屏幕的方式缺席(如果没有设置屏幕锁定)或者设备解锁(包括轻扫),则广播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;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

以上是艰难的方式.使用KeyguardManager.isKeyguardSecure()

  • 如果设置了 Pin 或密码,而不是模式等,这将是正确的。见 http://blog.learningtree.com/of-pins-and-passwords-and-jelly-bean/ (2认同)

ihr*_*pin 0

如果您谈论屏幕锁定,您可能会尝试设置特定的 BroadcastReceiver 并监听来自系统的特定 Intents。

希望能帮助到你。抱歉,如果我没听懂你的话:)