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 Books Books використовує це, щоб дозволити налаштувати яскравість екрана затемненим під час використання книги, а потім повернутись до звичайної яскравості, коли її вимикаєте.

Щоб допомогти у налагодженні, ви можете скористатися "adb shell dumpsys window", щоб побачити поточний стан вашого вікна. У даних для вашого вікна він покаже вам поточні LayoutParams, які для нього були встановлені. Переконайтесь, що значення, яке, на вашу думку, насправді є.

І знову FLAG_KEEP_SCREEN_ON - це окреме поняття; це і яскравість не мають прямого впливу один на одного. (І не було б жодної причини встановлювати прапор знову при скасуванні яскравості, якщо ви вже встановили його при встановленні яскравості на 0. Прапор залишатиметься встановленим, доки ви його не зміните.)


8
Чи є кращий спосіб вимкнути екран?
akash

Як уже зазначав @hackbod, "params.screenBrightness = 0;" не вимикає екран повністю; натомість це робить екран максимально тьмяним. І "params.screenBrightness = -1;" повертає екран до попереднього рівня яскравості. Однак бувають випадки, коли нам потрібно повністю вимкнути екран. Можуть бути й інші методи ...
Джонатанж

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().


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 застарілий.
Каміль Севіньї,

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();
}

Як вимкнути екран, не залучаючи датчик наближення?
Майкл

Привіт @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?
Помилки трапляються

@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);
}

Вибачте за мою погану англійську.


Привіт, Родріго Гонтійо Чому нам потрібен пристрій root pl. скажи мені?
Кінджал

@Kinjal, оскільки вам потрібно викликати функцію ("goToSleep"), і для цієї функції потрібен спеціальний дозвіл, який надається лише системним додаткам: <
koristi

добре, дякую, будь ласка, надайте посилання або крок, як викорінити пристрій, якщо це можливо. Заздалегідь спасибі.
Кінджал 03.03.17

4

Ось успішний приклад реалізації того самого, на пристрої, який підтримував нижчі значення яскравості екрану (я тестував на 7-дюймовому планшеті Allwinner Chinese з 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.


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

Це працює над Зефіром

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();
    }
}

Було б чудово, якби ви пояснили, чому ваша відповідь працює, що допоможе члену SO зрозуміти краще.
dkb

вимкнення екрана працює не так добре ... коли датчик наближення переходить зблизька на далеко, екран знову включається ... і якщо я відпустив блокування будильника до цього, він все одно включається негайно !
Майкл

2

Щодо документації Android, цього можна досягти, використовуючи такий рядок коду:

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

Я додав це у свій onCreateметод, і він працює нормально.

За посиланням ви знайдете різні способи досягнення цього, а також загальні пояснення.

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


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);

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.