6

我想控制设备上的启用/禁用键盘保护。为此,我使用 Android SDK 的 DevicePolicyManager 和 KeyguardLock API。

下面是我管理这个的实现:

public class DeviceLocker {

private static DeviceLocker instance;

public static synchronized DeviceLocker getInstance(Context context) {
    if(instance==null) {
        instance = new DeviceLocker(context);
    }
    return instance;
}

private Context context;
private KeyguardLock lock;

private DeviceLocker(Context context) {
    this.context = context;
}

public void lock() {
    lock(true);
}

public void lock(boolean lockNow) {
    getLock().reenableKeyguard();
    DevicePolicyManager devicePolicyManager = getDevicePolicyManager();
    if(devicePolicyManager==null) {
        return;
    }
    LocalStorage storage = LocalStorage.from(context);
    
    boolean result = devicePolicyManager.resetPassword(storage.getPassword(),
            DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY);
    
    if(lockNow) {
        devicePolicyManager.lockNow();
    }
    storage.setDeviceLocked(true);
}

public void unlock() {
    DevicePolicyManager devicePolicyManager = getDevicePolicyManager();
    if(devicePolicyManager==null) {
        return;
    }
    devicePolicyManager.resetPassword("",0);
    getLock().disableKeyguard();
    LocalStorage.from(context).setDeviceLocked(false);
}

private KeyguardLock getLock() {
    if(lock==null){
        KeyguardManager kgManager = (KeyguardManager)context.getSystemService(Activity.KEYGUARD_SERVICE);
        lock = kgManager.newKeyguardLock(Context.KEYGUARD_SERVICE);
    }
    return lock;
}

private DevicePolicyManager getDevicePolicyManager() {
    DevicePolicyManager devicePolicyManager =
        (DevicePolicyManager)context.getSystemService(Context.DEVICE_POLICY_SERVICE);
    ComponentName deviceAdmin = new ComponentName(context, WatchGuardDeviceAdminReceiver.class);
    LocalStorage storage = LocalStorage.from(context);
    if(!devicePolicyManager.isAdminActive(deviceAdmin)) {
        return null;
    }
    if(!storage.isPasswordSet()) {
        UIUtils.showMessage(context, R.string.password_not_set);
        return null;
    }
    devicePolicyManager.setPasswordQuality(deviceAdmin,DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
    
    return devicePolicyManager;
}

}

它在屏幕锁定方面工作正常,但解锁功能可以解决一些问题:有时它可以按我的意愿工作(完全删除任何类型的键盘保护屏幕),但有时它会显示“滑动解锁”键盘保护屏幕。

你知道这里有什么问题吗?如何使其稳定工作(至少在所有情况下都显示“解锁以滑动”或完全移除键盘保护)?

在此先感谢您的帮助。

编辑

只想指出我的解决方案有效,但问题是它工作不稳定(有时会完全移除键盘保护,有时会显示“滑动”键盘保护)。而且我不仅在显示某些活动时使用它来禁用键盘保护,而且还用于控制通用设备的锁定/解锁,因此我在服务中使用此代码,因此我无法调用,getWindow().addFlags(..)因为我没有窗口申请。

只是想知道也许有人处理过这种不稳定的行为。

4

4 回答 4

5

您需要添加以下代码:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED|WindowManager.LayoutParams.FLAG_FULLSCREEN|
                WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.lockscreen);

        startService(new Intent(this,LockService.class).setAction(Intent.ACTION_SCREEN_OFF));
    }

使用以下命令创建 LockService:

@Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {

        if(intent == null || intent.getAction() == null)
            return START_NOT_STICKY;

        String action = intent.getAction();

        if(action.equals(ACTION_SCREEN_OFF))
        {
           KeyguardManager.KeyguardLock k1;
           KeyguardManager km =(KeyguardManager)getSystemService(KEYGUARD_SERVICE);
           k1= km.newKeyguardLock("IN");
           k1.disableKeyguard();  
        }

        return START_NOT_STICKY;
    }

实际上,我不知道为什么,但k1.disableKeyguard();仅适用于服务。

于 2014-03-13T07:20:38.120 回答
4

AFAIK 这不是普遍可能的,否则,这将是一个重大的安全漏洞。

在非 root 手机上,您最多只能关闭非安全键盘保护或在安全键盘保护上方显示您的应用程序。

这是一个组合来做到这一点:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);

在有根手机上,您可以尝试删除安全键盘保护(尽管您可能必须在设备真正消失之前重新启动设备)。

这是一个组合(我自己还没有尝试过,但我很确定 Play 商店中的几个“解锁手机”应用程序使用了这个技巧)

Runtime.getRuntime().exec("sudo rm /data/system/gesture.key");

我建议你先通过 adb 试试这个。此外,这是一个 XDA 线程,其中包含更多信息:http: //forum.xda-developers.com/showthread.php?t=1800799

于 2014-02-18T12:16:39.727 回答
1
KeyguardManager keyguardManager = (KeyguardManager)getSystemService(Activity.KEYGUARD_SERVICE);
KeyguardLock lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);
lock.disableKeyguard();

<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>

or 

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
于 2014-02-18T11:24:18.910 回答
0

我建议使用窗口标志dismiss_keyguard 或show_when_locked,如果您有一个需要在唤醒时越过锁屏顶部的窗口。

http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_SHOW_WHEN_LOCKED

你如何使用它如下(在设置布局之前在 onCreate 中调用)

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
于 2014-02-18T11:26:32.770 回答