Android — Пробуждение и разблокировка устройства

Описание приложения: приложение предназначено в качестве программы безопасности для конкретного клиента (не для публичного развертывания). Когда приложение не обнаруживает движения в течение определенного периода времени, приложение должно подать сигнал тревоги и выйти на передний план, если оно находится в фоновом режиме или устройство спит.

Проблема: если устройство находится в спящем режиме и заблокировано, нам нужно вывести его из спящего режима и разблокировать. Используя различные методы, найденные здесь, в 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);                
        }
    });
}

Из комментариев и сообщений по некоторым другим вопросам SO, которые я видел/использовал, кажется, что код PowerManager/KeyguardManager должен был добиться цели. Опять же, как я уже говорил ранее, технически это работает, когда устройство подключено через USB к машине разработчика, но абсолютно ничего не делает, когда устройство отделено.

Также обратите внимание, что это наше первое приложение для Android, и поэтому мы полностью осознаем, что мы можем быть совершенно не в том, что пытаемся сделать. Любые предложения приветствуются.

Короче говоря, учитывая приведенный выше код, почему устройство ведет себя так по-разному в зависимости от того, подключено ли оно к сети, и что мы должны изменить, чтобы разбудить и разблокировать устройство, как описано? Спасибо заранее за вашу помощь!


person Paul Richter    schedule 07.02.2013    source источник


Ответы (1)


Я решил проблему. Причина, по которой мы наблюдали различное поведение при подключении устройства через USB, заключалась в том, что процессор устройства не переходил в спящий режим. Я предполагаю, что это либо результат настройки режима отладки, либо просто то, как он ведет себя при подключении к компьютеру, поскольку функция энергосбережения спящего процессора не имеет значения. Очевидно, что когда устройство не подключено к сети, процессор с удовольствием вздремнул бы, и хотя мы наблюдали случайный запуск приложения (оно просыпалось бы в случайное время), синхронизация была бы непостоянной. Я также предполагаю, что это связано с тем, что несколько циклов процессора распределяются экономно, и нашему приложению будет дано очень мало циклов в «случайное» время.

Таким образом, наше решение состояло в том, чтобы захватить частичную блокировку пробуждения, когда устройство переходит в фоновый режим (что делается в методе onPause), и снять блокировку в методе onResume. Кажется, это предотвращает сон процессора. Мы продолжаем использовать полную блокировку пробуждения и отключение защиты клавиатуры, чтобы разбудить устройство, когда это необходимо. Использование частичной блокировки пробуждения, по-видимому, не дает ЦП перейти в спящий режим, и устройство, по-видимому, просыпается должным образом, когда ожидается. Вот наш обновленный код на случай, если кто-то столкнется с этой проблемой:

// 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();
}
person Paul Richter    schedule 07.02.2013
comment
Вам нужен вызов super.onPause(), добавленный в начало метода onPause()? Были сбои, когда это было исключено. - person Charlie Seligman; 04.06.2013
comment
@CharlieSeligman Ах да, забыл добавить. Исправим. Спасибо! - person Paul Richter; 04.06.2013
comment
Тиг не уверен, кто вас минусовал, но это точно был не я... реализовал это прошлой ночью в моем приложении Light Alarm, и сегодня утром это сработало - все прошло правильно. Спасибо большое за это решение! +1 к вопросу и ответу. - person Charlie Seligman; 04.06.2013
comment
@CharlieSeligman Крутой парень, большое спасибо. Не думал, что это ты, но не знал, кто и почему. Я рад, что это сработало и для вас. Также рад, что я был не единственным в мире, кто боролся с этой проблемой. - person Paul Richter; 04.06.2013
comment
Была аналогичная проблема, спасибо. - person The Tokenizer; 03.02.2014
comment
Круто, после столь долгих поисков, ударил и попробовал, я наконец нашел идеальное решение, приветствую тебя, чувак - person Divyanshu Negi; 05.02.2015
comment
@PaulRichter Я поставил будильник, как только сработает будильник, я хочу разблокировать устройство и хочу показать активность моих приложений? буду ли я использовать тот же метод? где я буду вызывать wakeDevice? - person Erum; 19.02.2015
comment
@ErumHannan (извините за задержку) Да, похоже, вы использовали бы тот же метод, что описан здесь. Вы, вероятно, вызовете wakeDevice из обратного вызова или метода, который выполняется по истечении времени ожидания тревоги (зависит от того, как вы это делаете). - person Paul Richter; 05.03.2015
comment
@PaulRichter Я попробовал этот код, и он работает для меня наполовину - т.е. активность, отправленная в BroadcastReceiver, отображается, но только на одну секунду, а затем завершается без причины. Вот тема: stackoverflow.com/questions/ 29591199/ - person jean d'arme; 12.04.2015
comment
@jeand'arme Похоже, вы решили проблему. Я не видел, чтобы вы делали что-то особенное, что могло бы вызвать эту нечетную 1 секунду бодрствования-сна. Судя по вашему ответу, в конце концов это была проблема с флагом. - person Paul Richter; 14.04.2015
comment
@KamilKiełczewski Привет из Канады. Я рад, что это помогло. - person Paul Richter; 12.06.2017
comment
Почему у вас есть 2 вида wakelock в этом коде? Нужны ли они оба для запуска этого? Я не вижу, как эти двое связаны. - person Neon Warge; 16.07.2017
comment
@neonWarge Прошло очень много времени с тех пор, как я работал с этим материалом, но, насколько я знаю, в данном случае они оба необходимы. Частичная блокировка поддерживает работу процессора, даже когда устройство должно находиться в спящем режиме, а полная блокировка позволяет включать и разблокировать экран. - person Paul Richter; 17.07.2017
comment
@paulrichter хороший материал. Также ответил на мои давние сомнения по поводу приложения голосовой активации, которое будет работать во время моей отладки USB и во время зарядки, но никогда, когда его оставят в покое! Но сейчас вернусь и взломаю его. ;-) - person user3833732; 29.11.2017
comment
Работает в обычном режиме, но не работает при блокировке устройства паролем/шаблоном/отпечатком пальца. Любая идея, как я могу сделать с этим? - person RaRa; 29.12.2017
comment
@ RRR_1173 К сожалению, я так давно не работал с этим, что даже не могу догадаться, как это решить. Может быть, есть какой-то менеджер типов, который обходит защиту... но это маловероятно и небезопасно. Прости. - person Paul Richter; 17.01.2018