Android - 唤醒和解锁设备

Pau*_*ter 45 android android-wake-lock keyguard

应用程序描述: 该应用程序旨在作为特定客户端的安全程序(不公开部署).当应用程序在一段时间内未检测到移动时,如果应用程序处于后台或设备处于睡眠状态,应用程序应发出警报并将其置于前台.

问题: 如果设备处于睡眠状态并处于锁定状态,我们需要唤醒并解锁设备.使用SO和其他地方的各种技术,我们已经能够(部分地)唤醒和解锁设备,但是当设备物理插入计算机时,这只能正常运行.如果设备本身没有插上电源,我们测试了唤醒 - 解锁,没有任何反应; 设备似乎仍然处于睡眠状态,应用程序似乎什么都不做(没有警报).

我使用过这篇文章关于使用PowerManager和KeyguardManager,这篇文章使用了窗口标志.

这是目前用于唤醒设备的代码:

public void wakeDevice() {
    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    wakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "TAG");
    wakeLock.acquire();

    KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
    keyguardLock.disableKeyguard();
    runOnUiThread(new Runnable(){
        public void run(){
            getWindow().addFlags(
                      WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);                
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

从我看到/使用过的其他一些SO问题的评论和帖子中,似乎PowerManager/KeyguardManager代码应该已经完成​​了这个技巧.同样,正如我之前所说的,它在技术上工作,而设备通过USB插入到开发机器,但在设备分离时绝对没有任何作用.

另请注意,这是我们的第一个Android应用程序,所以我们完全清楚我们可能会完全关注我们正在尝试做的事情.欢迎任何建议.

所以简而言之,鉴于上面的代码,为什么设备根据它是否插入而表现得如此不同,以及为了唤醒和解锁设备,我们应该改变什么?提前感谢您的帮助!

Pau*_*ter 58

我解决了这个问题.我们在通过USB插入设备时观察到不同行为的原因是因为设备的CPU没有进入睡眠状态.我认为这可能是调试模式设置的结果,或者只是插入计算机时的行为,因为CPU睡眠的省电功能无关紧要.显然,当没有插入设备时,CPU会很乐意小睡,虽然我们确实观察到应用程序随机运行(它会随机唤醒),但时间会不一致.我进一步假设这是因为发生的少数CPU周期被谨慎地分配,并且我们的应用程序将在"随机"时间被给予非常少的周期.

因此,我们的解决方案是在设备进入后台时(在onPause方法中完成)获取部分唤醒锁定,并释放onResume方法中的锁定.这似乎可以防止CPU休眠.我们继续使用完整唤醒锁和键盘保护功能,以便在需要时唤醒设备.使用部分唤醒锁似乎可以防止CPU休眠,并且设备确实在预期时正常唤醒.以下是我们更新的代码,以防有人遇到此问题:

// Called from onCreate
protected void createWakeLocks(){
    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    fullWakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Loneworker - FULL WAKE LOCK");
    partialWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Loneworker - PARTIAL WAKE LOCK");
}

// Called implicitly when device is about to sleep or application is backgrounded
protected void onPause(){
    super.onPause();
    partialWakeLock.acquire();
}

// Called implicitly when device is about to wake up or foregrounded
protected void onResume(){
    super.onResume();
    if(fullWakeLock.isHeld()){
        fullWakeLock.release();
    }
    if(partialWakeLock.isHeld()){
        partialWakeLock.release();
    }
}

// Called whenever we need to wake up the device
public void wakeDevice() {
    fullWakeLock.acquire();

    KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
    keyguardLock.disableKeyguard();
}
Run Code Online (Sandbox Code Playgroud)

  • Teeg不确定是谁贬低了你,但它肯定不是我...昨晚在我的Light Alarm应用程序上实现了它今天早上起作用了 - 所有这些都正确地完成了.非常感谢您的解决方案!问答+1. (3认同)
  • @CharlieSeligman 很酷的人,非常感谢。没想到是你,但不知道是谁或为什么。我很高兴它也对你有用。也很高兴我不是世界上唯一一个在这个问题上挣扎的人。 (2认同)