Android: jak programowo włączać i wyłączać ekran?

98

Przed oznaczeniem tego posta jako „duplikatu” piszę ten post, ponieważ żaden inny post nie zawiera rozwiązania problemu.

Próbuję wyłączyć urządzenie, to po kilku minutach lub wymianie czujnika włącz je ponownie.

Wyłącz testy wyświetlacza

Jestem w stanie wyłączyć ekran za pomocą:

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

Nie udało mi się wyłączyć ekranu za pomocą metody wl.release ().

Włącz test wyświetlacza

Moje pierwsze przypuszczenie, jak następuje, nie działa. Nic się nie dzieje, ekran pozostaje wyłączony.

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

Wtedy też próbowałem użyć wakelocków, ale bezskutecznie.

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

W końcu wypróbowałem następujące rozwiązania, ale bez rezultatu.

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

Podsumowując, nie pojawia się żaden błąd w konsoli dla żadnej z tych metod. Mój tekst testowy „Ekran powinien być włączony” pojawia się na ekranie, gdy włączam urządzenie przyciskiem zasilania. To pokazuje, że kod powinien był działać. Proszę o odpowiedź tylko wtedy, gdy przetestowałeś kod, wydaje się, że wiele funkcji, takich jak params.screenBrightness = -1, nie działa tak, jak powinny zgodnie z sdk.

thegreyspot
źródło
1
Twoja metoda wyłączania ekranu nie działa dla mnie. Ustawiasz flagę tak, aby ekran był cały czas włączony, co powoduje zużycie energii.
Kristy Welsh
Czy kiedykolwiek to rozgryzłeś? W PlayStore jest kilka aplikacji, które sugerują, że to robią. Wypróbowałem ten i działa, ale prosi o administrację urządzeniem. play.google.com/store/apps/…
George
osiągnąłeś coś w tym problemie? !!
Muhammed Refaat

Odpowiedzi:

69

Zakładam, że chcesz, aby działało to tylko wtedy, gdy Twoja aplikacja jest na pierwszym planie.

Ten kod:

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

Nie wyłącza ekranu w tradycyjnym sensie. Sprawia, że ​​ekran jest tak ciemny, jak to tylko możliwe. W standardowej platformie istnieje ograniczenie tego, jak słabo może być; jeśli twoje urządzenie faktycznie pozwala na całkowite wyłączenie ekranu, oznacza to pewną osobliwość implementacji tego urządzenia, a nie zachowanie, na które możesz liczyć na różnych urządzeniach.

W rzeczywistości używanie tego w połączeniu z FLAG_KEEP_SCREEN_ON oznacza, że ​​nigdy nie pozwolisz na wyłączenie ekranu (a tym samym na przejście urządzenia w tryb niskiego poboru mocy), nawet jeśli dane urządzenie pozwala ustawić jasność ekranu na pełne. Miej to na uwadze. Będziesz zużywał znacznie więcej energii, niż gdyby ekran był naprawdę wyłączony.

Teraz, aby przywrócić normalną jasność ekranu, wystarczy ustawić wartość jasności:

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

Nie potrafię wyjaśnić, dlaczego to nie zastąpiłoby wcześniej ustawionej wartości 0. W ramach testu możesz spróbować wprowadzić wymuszoną pełną jasność, aby wymusić tę konkretną jasność:

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

To zdecydowanie działa. Na przykład aplikacje Książki Google wykorzystują to, aby ustawić jasność ekranu na przyciemnienie podczas korzystania z książki, a następnie powrócić do normalnej jasności po wyłączeniu.

Aby ułatwić debugowanie, możesz użyć „adb shell dumpsys window”, aby zobaczyć aktualny stan okna. W danych dla twojego okna, pokaże ci bieżące LayoutParams, które zostały dla niego ustawione. Upewnij się, że wartość, o której myślisz, faktycznie istnieje.

I znowu FLAG_KEEP_SCREEN_ON to osobna koncepcja; to i jasność nie mają na siebie bezpośredniego wpływu. (I nie byłoby powodu, aby ponownie ustawiać flagę podczas cofania jasności, gdybyś już ją ustawił, ustawiając jasność na 0. Flaga pozostanie ustawiona, dopóki jej nie zmienisz).

hackbod
źródło
8
Czy jest lepszy sposób na wyłączenie ekranu?
akash
Jak @hackbod stwierdził powyżej, „params.screenBrightness = 0;” nie wyłącza całkowicie ekranu; zamiast tego sprawia, że ​​ekran jest tak ciemny, jak to tylko możliwe. Oraz "params.screenBrightness = -1;" przywraca ekran z powrotem do poprzedniego poziomu jasności. Są jednak przypadki, w których musimy całkowicie wyłączyć ekran. Mogą być inne metody ...
jonathanzh
6
Jakie byłyby te inne metody, które faktycznie wyłączają ekran, a nie tylko ustawiają minimalną jasność, która może działać lub nie?
Michael,
37

Napisałem tę metodę, aby włączyć ekran po zablokowaniu ekranu. U mnie działa idealnie. Spróbuj-

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

I wywołaj tę metodę z onResume().

Rajkiran
źródło
1
Nie jest to przydatne, jeśli planujesz włączyć ekran, gdy chcesz zakończyć działanie.
AndroidDev,
7
Cóż, ludzie, zasugeruję, aby nie używać mojej metody, ponieważ to nie działa dla mnie na Micromax Canvas2 +. Zamiast tego użyj tego linku .
Rajkiran
28

Sugerowałbym ten:

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

Flaga ACQUIRE_CAUSES_WAKEUP jest wyjaśniona w ten sposób:

Normalne blokady budzenia w rzeczywistości nie włączają oświetlenia. Zamiast tego powodują, że podświetlenie pozostaje włączone po włączeniu (np. Z powodu aktywności użytkownika). Ta flaga wymusza natychmiastowe włączenie ekranu i / lub klawiatury po uzyskaniu WakeLock. Typowym zastosowaniem byłyby powiadomienia, które są ważne, aby użytkownik mógł je natychmiast zobaczyć.

Upewnij się również, że masz następujące uprawnienia w pliku AndroidManifewst.xml:

<uses-permission android:name="android.permission.WAKE_LOCK" />
ramdroid
źródło
3
Niestety flaga SCREEN_BRIGHT_WAKE_LOCK została wycofana.
Camille Sévigny
20

Cześć, mam nadzieję, że to pomoże:

 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();
}
mangu23
źródło
Jak wyłączyć ekran bez angażowania czujnika zbliżeniowego?
Michael,
Cześć @Michael, po prostu używasz tylko funkcji public void turnOffScreen ()
mangu23
3
Tak, ale wygląda na to, że funkcja ta wykorzystuje, PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCKktóra wyłącza ekran tylko wtedy, gdy czujnik zbliżeniowy jest w stanie „blisko”.
Michael
Ahh ok, rozumiem, możesz użyć tego zamiast PowerManager.SCREEN_DIM_WAKE_LOCK
mangu23
1
Problem - gdy tylko PROXIMITY_SCREEN_OFF_WAKE_LOCKzwolnię blokadę oczekiwania, ekran ponownie się włączy. Jak temu zapobiec?
Michael
7
     WakeLock screenLock =    ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(
    PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
    screenLock.acquire();

  //later
  screenLock.release();

// Plik manifestu użytkownika

Pir Fahim Shah
źródło
2
To powinna być prawidłowa odpowiedź. Używam Androida 5 i to jedyna rzecz, która faktycznie działa. Jedyną uwagą jest to, że SCREEN_BRIGHT_WAKE_LOCK jest przestarzała i nie widzę zastępczej wersji. Ktoś?
HammerNL
Nie ma problemu, Twoja odpowiedź jest całkowicie użyteczna. Jak powiedziałem: „to jedyna odpowiedź, która faktycznie działa”
HammerNL
@HammerNL Jaka jest różnica między tą odpowiedzią a odpowiedzią udzieloną przez ramdroid?
Błędy wydarzyły się
@BugsHappen Ramdroids jeden jest bardziej rozbudowany :) Ale tak, to to samo. Nie wiem, dlaczego Pir Fahim Shah opublikował tę odpowiedź lub dlaczego nie widziałem wtedy Ramdroidów.
HammerNL
6

Czy na pewno poprosiłeś o odpowiednie pozwolenie w swoim pliku manifestu?

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

Możesz użyć klasy AlarmManager 1, aby odpalić intencję, która rozpoczyna twoją aktywność i uzyskuje blokadę wybudzenia . Spowoduje to włączenie ekranu i utrzymanie go. Zwolnienie wakelocka pozwoli urządzeniu na samodzielne zaśnięcie.

Możesz również rzucić okiem na użycie PowerManagera, aby ustawić urządzenie w tryb uśpienia: http://developer.android.com/reference/android/os/PowerManager.html#goToSleep(long)

Zambotron
źródło
1
Dzięki za odpowiedzi. Tak jestem pewna. Jest w moim manifeście i nie ma błędów debugowania. AlarmManager nie pomoże mi, gdy używam czujników do włączania ekranu. Nie miałem dużo szczęścia z goToSleep, ale nadal nie pomaga mi to w włączaniu ekranu. Obecnie jestem w stanie wyłączyć ekran
thegreyspot
5

Najlepszy sposób na zrobienie tego (przy użyciu zrootowanych urządzeń):

@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

   .
   .
   .
}

Teraz mamy dwie funkcje:

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){
  }
}

I to:

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

Przepraszam za mój zły angielski.

Rodrigo Gontijo
źródło
Witaj Rodrigo Gontijo Dlaczego musimy zrootować urządzenie pl. Powiedz mi?
Kinjal
@Kinjal, ponieważ musisz wywołać funkcję („goToSleep”), a ta funkcja wymaga specjalnego pozwolenia, przyznawanego tylko aplikacjom systemowym: <uses-Permissions android: name = "android.permission.DEVICE_POWER" />
Rodrigo Gontijo
ok, dziękuję i podaj link lub krok, jak zrootować urządzenie, jeśli to możliwe. Z góry dziękuję.
Kinjal
4

Oto udany przykład implementacji tego samego na urządzeniu obsługującym niższe wartości jasności ekranu (testowałem na 7-calowym tablecie Allwinner z chińskim interfejsem 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);

Jeśli ktoś inny to wypróbuje, proszę o komentarz poniżej, czy zadziałało / nie działało, a urządzenie, Android API.

ılǝ
źródło
2
Na moim urządzeniu Nexus 7 nie działa to dobrze, ekran nadal jest włączony, tylko trochę ciemniejszy, ale nie do końca czarny.
JackWM
Z pewnością ta implementacja nie powinna być używana do publicznego wydania, chociaż może służyć integracji z konkretnym urządzeniem. Zachowam post, bo może to komuś pomóc na później.
ılǝ
3

Aby ekran był włączony:

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

Powrót do domyślnego trybu ekranu: po prostu wyczyść flagę FLAG_KEEP_SCREEN_ON

getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Marco Aurelio Silva
źródło
3

To działa na 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
źródło
Byłoby wspaniale, gdybyś wyjaśnił, dlaczego twoja odpowiedź działa, co pomoże członkowi SO lepiej zrozumieć.
dkb
wyłączenie ekranu nie działa tak dobrze ... kiedy czujnik zbliżeniowy przesuwa się z bliska na daleki, ekran ponownie się włącza ... a jeśli wcześniej zwolnię blokadę wybudzenia, nadal włącza się natychmiast !
Michael
2

Jeśli chodzi o dokumentację Androida, można to osiągnąć za pomocą następującej linii kodu:

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

Dodałem to do mojej onCreatemetody i działa dobrze.

W linku znajdziesz różne sposoby osiągnięcia tego, a także ogólne wyjaśnienie.

Link do dokumentacji: https://developer.android.com/training/scheduling/wakelock.html

maytham-ɯɐɥʇʎɐɯ
źródło
2

Jeśli Twoja aplikacja jest aplikacją systemową, możesz użyć PowerManager.goToSleep (), aby wyłączyć ekran, potrzebujesz specjalnego pozwolenia

zanim użyjesz goToSleep (), musisz użyć refleksji, tak jak:

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

Teraz możesz użyć goToSleep (), aby wyłączyć ekran.

Dzieje się tak po naciśnięciu klawisza zasilania w celu wyłączenia ekranu.

Rickon Gao
źródło
2

Po prostu dodaj

android:keepScreenOn="true" 

albo zadzwoń

setKeepScreenOn(true) 

na widok rodziców.

mani
źródło
1

Nie miałbym nadziei na „przebudzenie ekranu” podczas zajęć. Jeśli ekran jest wyłączony, działanie jest prawdopodobnie wstrzymane i nie powinno uruchamiać żadnego kodu.

Po przebudzeniu pojawia się problem z blokadą ekranu. Nie wiem, jak jakakolwiek aplikacja może automatycznie ominąć blokadę ekranu.

Powinieneś rozważyć uruchomienie zadań w tle w usłudze, a następnie użycie menedżera powiadomień do wysłania powiadomienia, gdy cokolwiek zostanie wykryte. Powiadomienie powinno dostarczać pewnego rodzaju alertu urządzenia (wybudzenie ekranu, ikona powiadomienia, dioda powiadomienia itp.). Po kliknięciu powiadomienia może uruchomić chęć rozpoczęcia Twojej aktywności.

Możesz także spróbować rozpocząć aktywność bezpośrednio z usługi, ale naprawdę nie wiem, czy to włączy ekran, czy obejdzie blokadę ekranu.

HaMMeReD
źródło
Dziękuję za odpowiedź, wpisuję kod wibracyjny, a kiedy wyłączam ekran i aktywuję jeden z moich czujników, wibruje. Więc kod na pewno działa. Blokada ekranu to nic wielkiego, po prostu używam blokady klawiatury.
thegreyspot
Nawet jeśli kod działa, jest poza cyklem życia. Nie możesz ufać działaniom poza ekranem. Pomyśl o programach do pobierania gier, większość z nich jest zapisana w działaniu i możesz zostawić je na około 30 sekund do kilku minut, a one nadal będą pobierać, ale zwykle się psują, ponieważ system operacyjny zabija aktywność w oparciu o twoje wzorce użytkowania.
HAMMERED
1

Zgodnie z Android API 28 i nowszym, musisz wykonać następujące czynności, aby włączyć ekran

setShowWhenLocked(true); 
setTurnScreenOn(true); 
KeyguardManager keyguardManager = (KeyguardManager)
getSystemService(Context.KEYGUARD_SERVICE);
keyguardManager.requestDismissKeyguard(this, null);
Axesh Ajmera
źródło