Android: come attivare e disattivare lo schermo a livello di programmazione?


98

Prima di contrassegnare questo post come "duplicato", scrivo questo post perché nessun altro post contiene la soluzione al problema.

Sto provando a spegnere il dispositivo, quindi dopo alcuni minuti o dopo aver cambiato il sensore, riaccendilo.

Disattiva i test del display

Sono in grado di spegnere lo schermo utilizzando:

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

Non sono riuscito a spegnere lo schermo utilizzando il metodo wl.release ().

Attiva il test del display

La mia prima ipotesi, come segue, non funziona. Non succede niente, lo schermo rimane spento.

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

Ho anche provato a usare wakelocks, senza successo.

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

Finalmente ho provato quanto segue, senza risultato.

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

Tutto sommato, non ricevo alcun tipo di errore nella console per nessuno di questi metodi. Il testo di prova "Lo schermo dovrebbe essere acceso" viene visualizzato sullo schermo quando accendo il dispositivo utilizzando il pulsante di accensione. Questo mostra che il codice avrebbe dovuto essere eseguito. Per favore rispondi solo se hai testato il codice, sembra che molte delle funzioni come params.screenBrightness = -1, non funzionino come dovrebbero secondo sdk.


1
Il tuo metodo per spegnere lo schermo non ha funzionato per me. Hai impostato la bandiera per mantenere lo schermo sempre acceso, il che consumerà energia.
Kristy Welsh

L'hai mai capito? Ci sono alcune app su PlayStore che suggeriscono di farlo. Ho provato questo e funziona ma richiede l'amministrazione del dispositivo. play.google.com/store/apps/…
George,

hai raggiunto qualcosa in questo problema? !!
Muhammed Refaat

Risposte:


69

Presumo che tu voglia che questo sia attivo solo mentre la tua applicazione è in primo piano.

Questo codice:

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

Non spegne lo schermo nel senso tradizionale. Rende lo schermo il più scuro possibile. Nella piattaforma standard c'è un limite a quanto può essere debole; se il tuo dispositivo sta effettivamente permettendo allo schermo di spegnersi completamente, allora è una particolarità dell'implementazione di quel dispositivo e non un comportamento su cui puoi contare su tutti i dispositivi.

In effetti, l'utilizzo di questo in combinazione con FLAG_KEEP_SCREEN_ON significa che non consentirai mai che lo schermo si spenga (e quindi il dispositivo vada in modalità a basso consumo) anche se il particolare dispositivo ti consente di impostare la luminosità dello schermo al massimo. Tienilo ben presente. Userai molta più energia di quanto faresti se lo schermo fosse davvero spento.

Ora per riportare lo schermo alla luminosità normale, è sufficiente impostare il valore di luminosità:

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

Non riesco a spiegare perché questo non sostituirebbe il valore 0 che avevi impostato in precedenza. Come test, potresti provare a inserire una luminosità completa forzata per forzare quella luminosità specifica:

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

Funziona decisamente. Ad esempio, le app di Google Libri lo utilizzano per consentirti di impostare la luminosità dello schermo in modo che si attenui durante l'utilizzo di un libro e quindi tornare alla luminosità normale quando lo spegni.

Per aiutare il debug, puoi usare "adb shell dumpsys window" per vedere lo stato corrente della tua finestra. Nei dati per la tua finestra, ti dirà i LayoutParams correnti che sono stati impostati per essa. Assicurati che il valore che pensi sia effettivamente presente.

E ancora, FLAG_KEEP_SCREEN_ON è un concetto separato; esso e la luminosità non hanno alcun impatto diretto l'uno sull'altro. (E non ci sarebbe alcun motivo per impostare di nuovo il flag quando si annulla la luminosità, se lo si fosse già impostato quando si mette la luminosità a 0. Il flag rimarrà impostato fino a quando non lo si modifica.)


8
C'è un modo migliore per disattivare lo schermo?
akash

Come @hackbod ha affermato sopra, "params.screenBrightness = 0;" non spegne completamente lo schermo; invece, rende lo schermo il più scuro possibile. E "params.screenBrightness = -1;" riporta lo schermo al livello di luminosità precedente. Tuttavia, ci sono casi in cui dobbiamo spegnere completamente lo schermo. Potrebbero esserci altri metodi ...
jonathanzh

6
Quali sarebbero quegli altri metodi che effettivamente spengono lo schermo piuttosto che impostare semplicemente la luminosità minima che potrebbe o non potrebbe funzionare?
Michael

37

Avevo scritto questo metodo per accendere lo schermo dopo il blocco dello schermo. Funziona perfettamente per me. Provalo-

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

E chiama questo metodo da onResume().


1
Non utile se prevedi di accendere lo schermo quando vuoi terminare l'attività.
AndroidDev

7
Bene gente, suggerirò di non usare il mio metodo perché questo non ha funzionato per me su Micromax Canvas2 +. Utilizza invece questo collegamento .
Rajkiran

28

Suggerirei questo:

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

Il flag ACQUIRE_CAUSES_WAKEUP è spiegato così:

I normali wakelock in realtà non accendono l'illuminazione. Invece, fanno sì che l'illuminazione rimanga accesa una volta che si accende (ad esempio dall'attività dell'utente). Questo flag costringerà lo schermo e / o la tastiera ad accendersi immediatamente, quando il WakeLock viene acquisito. Un utilizzo tipico sarebbe per le notifiche che sono importanti per l'utente da vedere immediatamente.

Inoltre, assicurati di disporre della seguente autorizzazione nel file AndroidManifewst.xml:

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

3
Sfortunatamente, il flag SCREEN_BRIGHT_WAKE_LOCK è stato deprecato.
Camille Sévigny

20

Ciao, spero che questo ti aiuti:

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

Come spegnere lo schermo senza coinvolgere il sensore di prossimità?
Michael

Ciao @Michael, usi semplicemente solo la funzione public void turnOffScreen ()
mangu23

3
Sì, ma sembra che questa funzione utilizzi la funzione PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCKche spegne lo schermo solo quando il sensore di prossimità è nello stato "vicino".
Michael

Ahh ok ho capito, puoi usare questo PowerManager.SCREEN_DIM_WAKE_LOCK
mangu23

1
Problema: non appena rilascio il PROXIMITY_SCREEN_OFF_WAKE_LOCKwaitlock, lo schermo si riaccende. Come posso impedirlo?
Michael

7
     WakeLock screenLock =    ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(
    PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
    screenLock.acquire();

  //later
  screenLock.release();

// File manifest dell'utente


2
Questa dovrebbe essere la risposta corretta. Sto usando Android 5 e questa è l'unica cosa che funziona davvero. L'unica nota a margine è che SCREEN_BRIGHT_WAKE_LOCK è deprecato e non vedo una sostituzione immediata. Qualcuno?
HammerNL

Nessun problema, la tua risposta è perfettamente utilizzabile. Come ho detto: "è l'unica risposta che funziona davvero"
HammerNL

@HammerNL qual è la differenza tra questa risposta e la risposta fornita da ramdroid?
bug si verificano il

@BugsHappen Ramdroids uno è più elaborato :) Ma sì, è lo stesso. Non so perché Pir Fahim Shah ha pubblicato questa risposta, o perché non ne ho visto uno in quel momento.
HammerNL

6

Sei sicuro di aver richiesto l'autorizzazione appropriata nel tuo file Manifest?

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

Puoi utilizzare la classe AlarmManager 1 per attivare un intento che avvia la tua attività e acquisisce il wakelock. Questo accenderà lo schermo e lo manterrà acceso. Il rilascio del wakelock consentirà al dispositivo di andare a dormire da solo.

Puoi anche dare un'occhiata all'uso di PowerManager per impostare il dispositivo in modalità di sospensione: http://developer.android.com/reference/android/os/PowerManager.html#goToSleep(long)


1
Grazie per la risposta. Sì, sono sicuro. È nel mio manifest e non ci sono errori di debug. AlarmManager non mi aiuterà quando utilizzo i sensori per accendere lo schermo. Non ho avuto molta fortuna con goToSleep, ma questo non mi aiuta ancora ad accendere lo schermo. Al momento sono in grado di disattivare lo schermo
thegreyspot

5

Il modo migliore per farlo (utilizzando dispositivi rooted):

@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

   .
   .
   .
}

Ora abbiamo queste due funzioni:

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

E questo:

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

Scusa per il mio cattivo inglese.


Ciao, Rodrigo Gontijo Perché dobbiamo eseguire il root del dispositivo pl. Dimmi?
Kinjal

@Kinjal perché devi invocare la funzione ("goToSleep") e questa funzione richiede un'autorizzazione speciale, concessa solo alle app di sistema: <uses-permission android: name = "android.permission.DEVICE_POWER" />
Rodrigo Gontijo

ok grazie e per favore fornisci il link o passo come eseguire il root del dispositivo, se possibile. Grazie in anticipo.
Kinjal

4

Ecco un esempio riuscito di implementazione della stessa cosa, su un dispositivo che supportava valori di luminosità dello schermo inferiori (l'ho testato su un tablet Allwinner Chinese 7 "con 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);

Se qualcun altro lo prova, commenta di seguito se ha funzionato / non ha funzionato e il dispositivo, l'API Android.


2
Sul mio dispositivo, nexus 7, questo non funziona bene, lo schermo è ancora acceso, solo un po 'più scuro, ma non completamente nero.
JackWM

Quindi sicuramente questa implementazione non dovrebbe essere utilizzata per una versione pubblica, sebbene possa servire un'integrazione con un dispositivo specifico. Terrò il post in quanto potrebbe aiutare qualcuno per dopo.
ılǝ

3

Per mantenere lo schermo attivo:

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

Torna alla modalità predefinita dello schermo: basta cancellare il flag FLAG_KEEP_SCREEN_ON

getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

3

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

Sarebbe bello se spiegassi perché la tua risposta funziona, il che aiuterà il membro SO a capire meglio.
dkb

spegnere lo schermo non funziona così bene ... quando il sensore di prossimità va da vicino a lontano, lo schermo si riaccende ... e se rilasciare il blocco scia prima di quello, ancora si accende subito !
Michael


2

Se la tua app è un'app di sistema, puoi utilizzare PowerManager.goToSleep () per disattivare lo schermo, è necessaria un'autorizzazione speciale

prima di usare goToSleep (), devi usare la riflessione proprio come:

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

Ora puoi usare goToSleep () per disattivare lo schermo.

Questo è ciò che accade quando si preme il tasto di accensione per spegnere lo schermo.


2

Aggiungi semplicemente

android:keepScreenOn="true" 

oppure chiama

setKeepScreenOn(true) 

in vista genitore.


1

Non avrei speranza di "svegliare lo schermo" nell'attività. Se lo schermo è spento, l'attività è probabilmente in uno stato di pausa e non dovrebbe eseguire alcun codice.

Al risveglio, c'è il problema della schermata di blocco. Non so come qualsiasi app possa bypassare automaticamente la schermata di blocco.

Dovresti considerare di eseguire le tue attività in background in un servizio e quindi utilizzare il gestore delle notifiche per inviare una notifica quando viene rilevato qualsiasi cosa. La notifica dovrebbe fornire una sorta di avviso del dispositivo (attivazione dello schermo, icona di notifica, LED di notifica, ecc.). Quando si fa clic sulla notifica, è possibile avviare l'intento di avviare la propria attività.

Puoi anche tentare di avviare l'attività direttamente dal servizio, ma non so davvero se questo accenderà lo schermo o aggirerà la schermata di blocco.


Grazie per la risposta, ho inserito un codice di vibrazione e quando ho lo schermo spento e attivo uno dei miei sensori, vibra. Quindi il codice è sicuramente in esecuzione. La schermata di blocco non è un grosso problema, uso solo lo scudo tastiera.
thegreyspot

Anche se il codice viene eseguito, è al di fuori del ciclo di vita. Non puoi fidarti delle attività che sono fuori dallo schermo. Pensa ai downloader di giochi, la maggior parte sono scritti nell'attività e puoi lasciarli per circa 30 secondi a pochi minuti e continueranno a scaricarsi, ma di solito si interrompono perché il sistema operativo interrompe l'attività in base ai tuoi schemi di utilizzo.
HaMMeReD

1

In base all'API 28 di Android e versioni successive, è necessario eseguire le seguenti operazioni per accendere lo schermo

setShowWhenLocked(true); 
setTurnScreenOn(true); 
KeyguardManager keyguardManager = (KeyguardManager)
getSystemService(Context.KEYGUARD_SERVICE);
keyguardManager.requestDismissKeyguard(this, null);

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.