Android: Как программно включать и выключать экран?

98

Прежде чем пометить этот пост как «дублирующий», я пишу его, потому что никакое другое сообщение не содержит решения проблемы.

Я пытаюсь выключить устройство, затем через несколько минут или смены датчика снова включаю.

Отключить тесты дисплея

Я могу выключить экран, используя:

params.flags |= LayoutParams.FLAG_KEEP_SCREEN_ON;
params.screenBrightness = 0;
getWindow().setAttributes(params);

Мне не удалось выключить экран с помощью метода wl.release ().

Включите тест дисплея

Моя первая догадка, как следует, не работает. Ничего не происходит, экран остается выключенным.

params.flags |= LayoutParams.FLAG_KEEP_SCREEN_ON;
params.screenBrightness = -1f;
getWindow().setAttributes(params);

Я также попытался использовать wakelocks, но безуспешно.

PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "tag");
wl.acquire();

Наконец, я попробовал следующее, но безрезультатно.

getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);

В общем, я не получаю никаких ошибок в консоли ни для одного из этих методов. Мой тестовый текст «Экран должен быть включен» появляется на экране, когда я включаю устройство с помощью кнопки питания. Это показывает, что код должен был работать. Пожалуйста, отвечайте только в том случае, если вы протестировали код, похоже, что многие функции, такие как params.screenBrightness = -1, не работают должным образом согласно sdk.

серое пятно
источник
1
Ваш способ выключения экрана у меня не сработал. Вы устанавливаете флаг, чтобы экран оставался включенным все время, что истощает энергию.
Кристи Уэлш,
Вы когда-нибудь понимали это? В PlayStore есть несколько приложений, предлагающих им это сделать. Пробовал, и он работает, но требует администрирования устройства. play.google.com/store/apps/…
Джордж,
Вы что-то достигли в этой проблеме? !!
Мухаммед Рефаат

Ответы:

69

Я предполагаю, что вы хотите, чтобы это действовало только тогда, когда ваше приложение находится на переднем плане.

Этот код:

params.flags |= LayoutParams.FLAG_KEEP_SCREEN_ON;
params.screenBrightness = 0;
getWindow().setAttributes(params);

Не выключает экран в традиционном понимании. Это делает экран максимально тусклым. В стандартной платформе есть ограничение на то, насколько тусклым он может быть; Если ваше устройство действительно позволяет экрану полностью отключиться, то это некоторая особенность реализации этого устройства, а не поведение, на которое вы можете рассчитывать на разных устройствах.

Фактически, использование этого в сочетании с FLAG_KEEP_SCREEN_ON означает, что вы никогда не позволите экрану выключиться (и, следовательно, устройству перейти в режим низкого энергопотребления), даже если конкретное устройство позволяет вам установить яркость экрана на полную. Имейте это в виду. Вы будете использовать гораздо больше энергии, чем если бы экран был действительно выключен.

Теперь, чтобы вернуть экран к нормальной яркости, достаточно установить значение яркости:

WindowManager.LayoutParams params = getWindow().getAttributes();
params.screenBrightness = -1;
getWindow().setAttributes(params);

Я не могу объяснить, почему это не заменит ранее установленное вами значение 0. В качестве теста вы можете попробовать установить принудительную полную яркость, чтобы добиться этой конкретной яркости:

WindowManager.LayoutParams params = getWindow().getAttributes();
params.screenBrightness = 1;
getWindow().setAttributes(params);

Это определенно работает. Например, приложения Google Книги используют это, чтобы вы могли настроить яркость экрана на затемнение при использовании книги, а затем вернуться к обычной яркости при выключении.

Чтобы облегчить отладку, вы можете использовать "adb shell dumpsys window", чтобы увидеть текущее состояние вашего окна. В данных для вашего окна он сообщит вам текущие LayoutParams, которые были установлены для него. Убедитесь, что ценность, которую вы думаете, действительно существует.

И снова FLAG_KEEP_SCREEN_ON - это отдельная концепция; он и яркость не влияют друг на друга напрямую. (И не было бы причин снова устанавливать флаг при отмене яркости, если вы уже установили его при установке яркости на 0. Флаг останется установленным, пока вы его не измените.)

хакбод
источник
8
Есть ли лучший способ отключить экран?
akash
Как указано выше в @hackbod, params.screenBrightness = 0; не выключает полностью экран; вместо этого он делает экран максимально тусклым. И «params.screenBrightness = -1;» возвращает экран к предыдущему уровню яркости. Однако есть случаи, когда нам нужно полностью выключить экран. Могут быть и другие методы ...
jonathanzh
6
Какими будут другие методы, которые фактически отключают экран, а не просто устанавливают минимальную яркость, которая может работать или не работать?
Майкл
37

Я написал этот метод для включения экрана после блокировки экрана. У меня он отлично работает. Попытайся-

    private void unlockScreen() {
        Window window = this.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
        window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
        window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
    }

И вызовите этот метод из onResume().

Rajkiran
источник
1
Бесполезно, если вы планируете включать экран, когда хотите прекратить действие.
AndroidDev
7
Что ж, народ, я предлагаю не использовать мой метод, так как он не работал у меня на Micromax Canvas2 +. Используйте вместо этого эту ссылку .
Rajkiran
28

Я бы предложил это:

PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "tag");
wl.acquire();

Флаг ACQUIRE_CAUSES_WAKEUP объясняется так:

Обычная блокировка пробуждения фактически не включает освещение. Вместо этого они заставляют освещение оставаться включенным после включения (например, из-за активности пользователя). Этот флаг заставит экран и / или клавиатуру немедленно включиться при срабатывании WakeLock. Типичное использование - уведомления, которые важны для немедленного просмотра пользователем.

Также убедитесь, что у вас есть следующие разрешения в файле AndroidManifewst.xml:

<uses-permission android:name="android.permission.WAKE_LOCK" />
баран
источник
3
К сожалению, флаг SCREEN_BRIGHT_WAKE_LOCK устарел.
Camille Sévigny
20

Привет, надеюсь, это поможет:

 private PowerManager mPowerManager;
 private PowerManager.WakeLock mWakeLock;

 public void turnOnScreen(){
     // turn on screen
     Log.v("ProximityActivity", "ON!");
     mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "tag");
     mWakeLock.acquire();
}

 @TargetApi(21) //Suppress lint error for PROXIMITY_SCREEN_OFF_WAKE_LOCK
 public void turnOffScreen(){
     // turn off screen
     Log.v("ProximityActivity", "OFF!");
     mWakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "tag");
     mWakeLock.acquire();
}
мангу23
источник
Как выключить экран, не задействуя датчик приближения?
Майкл
Привет, @Michael, вы просто используете только функцию public void turnOffScreen ()
mangu23
3
Да, но похоже, что эта функция использует PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCKотключение экрана только тогда, когда датчик приближения находится в "ближнем" состоянии.
Майкл
Ах, хорошо, я понимаю, вы можете использовать это вместо PowerManager.SCREEN_DIM_WAKE_LOCK
mangu23
1
Проблема - как только я PROXIMITY_SCREEN_OFF_WAKE_LOCKснимаю блокировку ожидания, экран снова включается. Как мне предотвратить это?
Майкл
7
     WakeLock screenLock =    ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(
    PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
    screenLock.acquire();

  //later
  screenLock.release();

// Файл манифеста пользователя

Пир Фахим Шах
источник
2
Это должен быть правильный ответ. Я использую Android 5, и это единственное, что действительно работает. Единственное замечание - SCREEN_BRIGHT_WAKE_LOCK устарел, и я не вижу заменяющих его. Кто угодно?
HammerNL
Нет проблем, ваш ответ вполне применим. Как я уже сказал: «это единственный ответ, который действительно работает»
HammerNL
@HammerNL в чем разница между этим ответом и ответом ramdroid?
Bugs Happen
@BugsHappen Ramdroids более продуманный :) Но да, это то же самое. Не знаю, почему Пир Фахим Шах опубликовал этот ответ, или почему я не видел Рамдроидов в то время.
HammerNL
6

Вы уверены, что запросили надлежащее разрешение в своем файле манифеста?

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

Вы можете использовать класс AlarmManager 1, чтобы запустить намерение, которое запускает вашу активность и получает блокировку пробуждения. Это включит экран и оставит его включенным. Снятие блокировки пробуждения позволит устройству перейти в спящий режим самостоятельно.

Вы также можете использовать PowerManager для перевода устройства в спящий режим: http://developer.android.com/reference/android/os/PowerManager.html#goToSleep(long)

Замботрон
источник
1
Спасибо за ответ. Да, я уверен. Это в моем манифесте, и ошибок отладки нет. AlarmManager мне не поможет, когда я использую датчики для включения экрана. Мне не очень повезло с goToSleep, но это все еще не помогает мне включить экран. В настоящее время я могу выключить экран
thegreyspot
5

Лучший способ сделать это (используя рутированные устройства):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    .
    .
    .

    int flags = WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
    getWindow().addFlags(flags); // this is how your app will wake up the screen
    //you will call this activity later

   .
   .
   .
}

Теперь у нас есть две функции:

private void turnOffScreen(){

  try{
     Class c = Class.forName("android.os.PowerManager");
     PowerManager  mPowerManager = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
     for(Method m : c.getDeclaredMethods()){
        if(m.getName().equals("goToSleep")){
          m.setAccessible(true);
          if(m.getParameterTypes().length == 1){
            m.invoke(mPowerManager,SystemClock.uptimeMillis()-2);
          }
        }
     } 
  } catch (Exception e){
  }
}

И это:

public void turnOnScreen(){
  Intent i = new Intent(this,YOURACTIVITYWITHFLAGS.class);
  startActivity(i);
}

Извините за мой плохой английский.

Родриго Гонтихо
источник
Здравствуйте, Родриго Гонтихо. Зачем нам рутировать устройство pl. скажи-ка?
Kinjal
@Kinjal, потому что вам нужно вызвать функцию ("goToSleep"), а для этой функции требуется специальное разрешение, предоставляемое только системным приложениям: <uses-permission android: name = "android.permission.DEVICE_POWER" />
Родриго Гонтихо,
Хорошо, спасибо, и, если возможно, предоставьте ссылку или шаг, как рутировать устройство. Заранее спасибо.
Kinjal 03
4

Вот успешный пример реализации того же самого на устройстве, которое поддерживает более низкие значения яркости экрана (я тестировал на китайском 7-дюймовом планшете Allwinner под управлением API15).

WindowManager.LayoutParams params = this.getWindow().getAttributes();

/** Turn off: */
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
//TODO Store original brightness value
params.screenBrightness = 0.1f;
this.getWindow().setAttributes(params);

/** Turn on: */
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
//TODO restoring from original value
params.screenBrightness = 0.9f;
this.getWindow().setAttributes(params);

Если кто-то еще попробует это сделать, пожалуйста, прокомментируйте ниже, если это сработало / не сработало и устройство, Android API.

ılǝ
источник
2
На моем устройстве nexus 7 это не работает, экран все еще включен, только немного темнее, но не полностью черный.
JackWM
Конечно, эту реализацию не следует использовать для общедоступной версии, хотя она может служить для интеграции с конкретным устройством. Я сохраню этот пост, так как он может кому-то помочь в будущем.
ılǝ
3

Чтобы экран оставался включенным:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

Вернуться в режим экрана по умолчанию: просто снимите флаг FLAG_KEEP_SCREEN_ON

getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Марко Аурелио Силва
источник
3

Это работает на Marshmallow

private final String TAG = "OnOffScreen";
private PowerManager _powerManager;
private PowerManager.WakeLock _screenOffWakeLock;

public void turnOnScreen() {
    if (_screenOffWakeLock != null) {
        _screenOffWakeLock.release();
    }
}

public void turnOffScreen() {
    try {
        _powerManager = (PowerManager) this.getSystemService(POWER_SERVICE);
        if (_powerManager != null) {
            _screenOffWakeLock = _powerManager.newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
            if (_screenOffWakeLock != null) {
                _screenOffWakeLock.acquire();
            }
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}
mbsysd
источник
Было бы здорово, если бы вы объяснили, почему ваш ответ работает, что поможет членам SO лучше понять.
dkb
выключение экрана работает не так хорошо ... когда датчик приближения перемещается от близкого к дальнему, экран снова включается ... и если я снимаю блокировку слежения до этого, он все равно сразу включается !
Майкл
2

Что касается документации Android, этого можно достичь, используя следующую строку кода:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

Я добавил это в свой onCreate метод, и он отлично работает.

По ссылке вы найдете различные способы достижения этого, а также общее объяснение.

Ссылка на документацию: https://developer.android.com/training/scheduling/wakelock.html

Maytham-ɯɐɥʇʎɐɯ
источник
2

Если ваше приложение является системным, вы можете использовать PowerManager.goToSleep () для выключения экрана, вам требуется специальное разрешение

прежде чем использовать goToSleep (), вам нужно использовать отражение, например:

public static void goToSleep(Context context) {
    PowerManager powerManager= (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    try {
        powerManager.getClass().getMethod("goToSleep", new Class[]{long.class}).invoke(powerManager, SystemClock.uptimeMillis());
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
}

Теперь вы можете использовать goToSleep (), чтобы выключить экран.

Вот что происходит, когда нажимается клавиша включения, чтобы выключить экран.

Рикон Гао
источник
2

Просто добавьте

android:keepScreenOn="true" 

или позвоните по телефону

setKeepScreenOn(true) 

на родительском представлении.

мани
источник
1

У меня не было бы надежды "разбудить экран" в этом занятии. Если экран выключен, действие, вероятно, находится в приостановленном состоянии и не должно выполняться какой-либо код.

При пробуждении проблема с блокировкой экрана. Я не знаю, как любое приложение может автоматически обходить экран блокировки.

Вам следует рассмотреть возможность запуска фоновых задач в службе, а затем использовать диспетчер уведомлений для отправки уведомления при обнаружении чего-либо. Уведомление должно содержать какое-то предупреждение устройства (пробуждение экрана, значок уведомления, индикатор уведомления и т. Д.). При нажатии на уведомление он может запустить намерение начать вашу деятельность.

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

ХАММЕРЕД
источник
Спасибо за ответ, я ввел код вибрации, и когда у меня выключен экран и я активирую один из своих датчиков, он вибрирует. Так что код определенно работает. Экран блокировки не имеет большого значения, я просто использую блокировку клавиатуры.
thegreyspot
Даже если код запускается, он выходит за пределы жизненного цикла. Вы не можете доверять действиям, которые выходят за рамки экрана. Подумайте о загрузчиках игр, большинство из них написано в действии, и вы можете оставить, может быть, от 30 секунд до нескольких минут, и они все равно будут загружаться, но обычно они ломаются, потому что ОС убивает активность в зависимости от ваших шаблонов использования.
HaMMeReD
1

В соответствии с Android API 28 и выше вам необходимо сделать следующее, чтобы включить экран.

setShowWhenLocked(true); 
setTurnScreenOn(true); 
KeyguardManager keyguardManager = (KeyguardManager)
getSystemService(Context.KEYGUARD_SERVICE);
keyguardManager.requestDismissKeyguard(this, null);
Аксеш Аджмера
источник