Проверьте, была ли включена блокировка или нет.
Мне нужно проверить, была ли включена блокировка системы или нет.
Я использовал ниже код строки
boolean b = android.provider.Settings.System.getInt(
getContentResolver(),Settings.System.LOCK_PATTERN_ENABLED, 0)==1;
Возвращает true, если я устанавливаю блокировку pattern
, а false, если я устанавливаю пароль pin/password
.
Мне нужно проверить, была ли блокировка включена или нет, либо она pattern/pin/password
заблокирована в настройках.
Мой код работает только с pattern
блокировкой не pin/password
блокировки.
Итак, скажите, пожалуйста, как проверить все типы блокировок.
Ответы
Ответ 1
Итак, этот вопрос довольно старый, но, похоже, пока нет хорошего ответа. После некоторого исходного кода (из ссылка Рамакришны) исследования и самостоятельные эксперименты Я написал простой класс, который выполняет эту работу.
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.
Если вы хотите проверить некоторый набор типов блокировок, просто используйте оператор switch
switch (lockType)
{
case LockType.FACE_WITH_PATTERN:
case LockType.FACE_WITH_PIN:
case LockType.PATTERN:
/* do something */
break;
}
или если вы хотите только "Face Unlock" независимо от того, какой дополнительный метод
if (lockType >= LockType.FACE_WITH_PATTERN && lockType <= LockType.FACE_WITH_SOMETHING_ELSE)
{
/* do something */
}
EDIT: так, я тестирую этот класс на 3 телефонах, и кажется, что не все телефоны правильно определяют способ разблокировки лица. На некоторых телефонах PASSWORD_QUALITY_BIOMETRIC_WEAK возвращается и PASSWORD_QUALITY_SOMETHING на чужих. Я думаю, что мы можем проверить, что файл, содержащий информацию для разблокировки лица, существует, а не пуст, подобно методам паролей/выводов и шаблонов. Но пока я не знаю, где именно находится этот файл.
EDIT2: Похоже, что я нашел проблему после исследования кода sordes android 4.3. Это потому, что параметры блокировки были перемещены в новое место (/data/system/locksettings.db), и, похоже, нет способа получить эти настройки из этой базы данных (rw-rw ---- permissions и "system" owner and group, поэтому только корень может выполнять эту работу).
Ответ 2
Будьте осторожны, этот метод также устарел! Спасибо 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;
}
Ответ 3
Начиная с 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
...
}
Ответ 4
@Peter Pint и esme_louise
Спасибо, ваше решение заставил меня идти. Чтобы узнать, включена ли блокировка экрана, я мог бы еще больше упростить ваш метод. Это возвращает false для прокрутки или правильной блокировки (PIN, PW, Face unlock и т.д.) И возвращает 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;
}
UPDATE:
Я адаптировал код для android M, используя новый метод isDeviceSecure(). Однако это не позволяет больше различать "None" и "Swipe".
Кроме того, метод уже начал сбой в 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;
}
И это метод, использующий его: он определяет, отсутствует ли пользователь таким образом, что при следующем включении экрана (если настройка экрана не установлена) или устройство разблокировано (включая прокрутку) 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;
}
}
Ответ 5
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();
Ответ 6
Вышеупомянутый трудный путь. Используйте KeyguardManager.isKeyguardSecure()
Ответ 7
Это также может быть достигнуто с помощью политик администратора устройства http://developer.android.com/guide/topics/admin/device-admin.html
Ответ 8
@Peter Pint
int lockProtectionLevel = (int)method.invoke(lockUtils);
... должен быть...
int lockProtectionLevel = Integer.valueOf(String.valueOf(method.invoke(lockUtils)));
Но в остальном, прямо сейчас! Я подтвердил ваш ответ.
Ответ 9
Если вы говорите о блокировке экрана, вы можете попытаться настроить конкретный BroadcastReceiver и прослушать определенные Intents из системы.
Надеюсь, поможет. Извините, если я вас не поняла :)