Android: como ligar e desligar a tela de maneira programática?

98

Antes de marcar este post como "duplicado", estou escrevendo este post porque nenhum outro post contém a solução para o problema.

Estou tentando desligar o dispositivo e, após alguns minutos ou troca de sensor, ligue-o novamente.

Desligue os testes de exibição

Consigo desligar a tela usando:

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

Não consigo desligar a tela usando o método wl.release ().

Ativar teste de exibição

Meu primeiro palpite, como segue, não funciona. Nada acontece, a tela permanece desligada.

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

Também tentei usar wakelocks, sem sucesso.

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

Finalmente tentei o seguinte, sem resultado.

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

Resumindo, não recebo nenhum tipo de erro no console para nenhum desses métodos. Meu texto de teste "A tela deve estar ligada" aparece na tela quando ligo o dispositivo usando o botão liga / desliga. Isso mostra que o código deveria ter sido executado. Por favor, responda somente se você testou o código, parece que muitas das funções, como params.screenBrightness = -1, não funcionam como deveriam de acordo com o SDK.

thegreyspot
fonte
1
Seu método para desligar a tela não funcionou para mim. Você define o sinalizador para manter a tela ligada o tempo todo, o que consumirá energia.
Kristy Welsh de
Você já descobriu isso? Existem alguns aplicativos na PlayStore sugerindo que eles façam isso. Tentei este e funciona, mas pede a administração de dispositivos. play.google.com/store/apps/…
George
você chegou a algo neste problema? !!
Muhammed Refaat

Respostas:

69

Vou presumir que você só deseja que isso entre em vigor enquanto seu aplicativo estiver em primeiro plano.

Este código:

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

Não desliga a tela no sentido tradicional. Isso torna a tela o mais escura possível. Na plataforma padrão, há um limite para a intensidade da luz; se o seu dispositivo está realmente permitindo que a tela desligue completamente, então é alguma peculiaridade da implementação desse dispositivo e não um comportamento com o qual você pode contar em todos os dispositivos.

Na verdade, usar isso em conjunto com FLAG_KEEP_SCREEN_ON significa que você nunca permitirá que a tela se apague (e, portanto, o dispositivo entre no modo de baixo consumo de energia), mesmo se o dispositivo específico estiver permitindo que você defina o brilho da tela para totalmente desligado. Tenha isso em mente. Você usará muito mais energia do que se a tela estivesse realmente desligada.

Agora, para retornar a tela ao brilho normal, basta definir o valor do brilho:

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

Não consigo explicar por que isso não substituiria o valor 0 que você definiu anteriormente. Como teste, você pode tentar colocar um brilho total forçado ali para forçar esse brilho específico:

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

Isso definitivamente funciona. Por exemplo, os aplicativos de livros do Google usam isso para permitir que você defina o brilho da tela para diminuir ao usar um livro e, em seguida, retornar ao brilho normal ao desligar.

Para ajudar a depurar, você pode usar "adb shell dumpsys window" para ver o estado atual de sua janela. Nos dados de sua janela, ele informará os LayoutParams atuais que foram definidos para ela. Certifique-se de que o valor que você acha que está realmente lá.

E, novamente, FLAG_KEEP_SCREEN_ON é um conceito separado; ele e o brilho não têm impacto direto um no outro. (E não haveria razão para definir o sinalizador novamente ao desfazer o brilho, se você já o tivesse definido ao colocar o brilho em 0. O sinalizador permanecerá definido até que você o altere.)

hackbod
fonte
8
Existe uma maneira melhor de desligar a tela?
Akash
Como @hackbod afirmou acima, "params.screenBrightness = 0;" não desliga a tela completamente; em vez disso, torna a tela o mais escura possível. E "params.screenBrightness = -1;" volta a tela ao nível de brilho anterior. No entanto, há casos em que precisamos desligar a tela completamente. Pode haver outros métodos ...
jonathanzh
6
Quais seriam esses outros métodos que realmente desligam a tela em vez de apenas definir o brilho mínimo que pode ou não funcionar?
Michael
37

Eu escrevi esse método para ligar a tela após o bloqueio da tela. Funciona perfeitamente para mim. Tente-

    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 chame esse método de onResume().

Rajkiran
fonte
1
Não é útil se você planeja ligar a tela quando quiser encerrar a atividade.
AndroidDev
7
Bem pessoal, vou sugerir não usar o meu método, pois isso não funcionou para mim no Micromax Canvas2 +. Use este link .
Rajkiran,
28

Eu sugeriria este:

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

A sinalização ACQUIRE_CAUSES_WAKEUP é explicada assim:

Os wake locks normais não ativam a iluminação. Em vez disso, eles fazem com que a iluminação permaneça acesa depois de ligada (por exemplo, pela atividade do usuário). Este sinalizador forçará a tela e / ou teclado a ligar imediatamente, quando o WakeLock for adquirido. Um uso típico seria para notificações que são importantes para o usuário ver imediatamente.

Além disso, certifique-se de ter a seguinte permissão no arquivo AndroidManifewst.xml:

<uses-permission android:name="android.permission.WAKE_LOCK" />
ramdroid
fonte
3
Infelizmente, o sinalizador SCREEN_BRIGHT_WAKE_LOCK foi preterido.
Camille Sévigny
20

Olá, espero que ajude:

 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
fonte
Como desligar a tela sem envolver o sensor de proximidade?
Michael
Olá @Michael, você simplesmente usa a função public void turnOffScreen ()
mangu23 de
3
Sim, mas parece que esta função usa o PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCKque só desliga a tela quando o sensor de proximidade está no estado "próximo".
Michael
Ahh ok, eu entendo, você pode usar este PowerManager.SCREEN_DIM_WAKE_LOCK
mangu23
1
Problema - assim que eu liberar o PROXIMITY_SCREEN_OFF_WAKE_LOCKwaitlock, a tela voltará. Como faço para evitar isso?
Michael
7
     WakeLock screenLock =    ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(
    PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
    screenLock.acquire();

  //later
  screenLock.release();

// Arquivo de manifesto do usuário

Pir Fahim Shah
fonte
2
Esta deve ser a resposta correta. Estou usando o Android 5 e essa é a única coisa que realmente funciona. A única nota é que SCREEN_BRIGHT_WAKE_LOCK está obsoleto e não vejo uma substituição imediata. Qualquer um?
HammerNL de
Não há problema, sua resposta é perfeitamente utilizável. Como eu disse: "é a única resposta que realmente funciona"
HammerNL
@HammerNL qual é a diferença entre esta resposta e a resposta fornecida pelo ramdroid?
Bugs acontecem em
@BugsHappen Ramdroids um é mais elaborado :) Mas sim, é o mesmo. Não sei por que Pir Fahim Shah postou essa resposta, ou por que eu não vi Ramdroids naquele momento.
HammerNL
6

Tem certeza de que solicitou a permissão adequada em seu arquivo de manifesto?

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

Você pode usar o AlarmManager 1 classe para disparar um intent que inicia sua atividade e adquire o wake lock. Isso ligará a tela e a manterá ligada. Liberar o wakelock permitirá que o dispositivo entre no modo de espera por conta própria.

Você também pode dar uma olhada em usar o PowerManager para configurar o dispositivo para hibernar: http://developer.android.com/reference/android/os/PowerManager.html#goToSleep(long)

Zambotron
fonte
1
Obrigado pela resposta. Sim eu tenho certeza. Está no meu manifesto e não há erros de depuração. AlarmManager não vai me ajudar quando eu uso sensores para ligar a tela. Não tive muita sorte com goToSleep, mas isso ainda não me ajuda a ligar a tela. No momento, consigo desligar a tela
thegreyspot
5

A melhor maneira de fazer isso (usando dispositivos com acesso root):

@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

   .
   .
   .
}

Agora temos essas duas funções:

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 isto:

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

Desculpe pelo meu péssimo inglês.

Rodrigo Gontijo
fonte
Olá, Rodrigo Gontijo Por que precisamos fazer root no dispositivo pl. Conte-me?
Kinjal
@Kinjal porque você precisa invocar a função ("goToSleep") e esta função requer uma permissão especial, concedida apenas a aplicativos do sistema: <uses-permission android: name = "android.permission.DEVICE_POWER" />
Rodrigo Gontijo
ok, obrigado e forneça um link ou passo como fazer root no dispositivo, se possível. Desde já, obrigado.
Kinjal,
4

Aqui está um exemplo bem-sucedido de uma implementação da mesma coisa, em um dispositivo que suportava valores de brilho de tela mais baixos (testei em um tablet Allwinner chinês 7 "executando 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 alguém tentar fazer isso, por favor, comente abaixo se funcionou / não funcionou e o dispositivo, API Android.

ılǝ
fonte
2
No meu aparelho, nexo 7, isso não funciona bem, a tela continua ligada, só um pouco mais escura, mas não totalmente preta.
JackWM
Certamente, essa implementação não deve ser usada para um lançamento público, embora possa servir uma integração com um dispositivo específico. Vou manter o post, pois pode ajudar alguém depois.
ılǝ
3

Para manter a tela ligada:

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

Voltar ao modo padrão da tela: basta limpar o sinalizador FLAG_KEEP_SCREEN_ON

getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Marco Aurelio Silva
fonte
3

Isso é trabalhado em 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
fonte
Seria ótimo se você explicasse por que sua resposta funciona, o que ajudará o membro do SO a entender melhor.
dkb
desligar a tela não funciona tão bem ... quando o sensor de proximidade vai de perto para longe, a tela volta a ligar ... e se eu liberar o wake lock antes disso, ele ainda liga imediatamente !
Michael
2

Com relação à documentação do Android, isso pode ser obtido usando a seguinte linha de código:

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

Eu adicionei isso no meu onCreate método e funciona bem.

No link, você encontrará diferentes maneiras de fazer isso e também uma explicação geral.

Link para a documentação: https://developer.android.com/training/scheduling/wakelock.html

maytham-ɯɐɥʇʎɐɯ
fonte
2

Se seu aplicativo for um aplicativo de sistema, você pode usar PowerManager.goToSleep () para desligar a tela, você requer uma permissão especial

antes de usar goToSleep (), você precisa usar reflexão, assim como:

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

Agora, você pode usar goToSleep () para desligar a tela.

Isso é o que acontece quando a tecla liga / desliga é pressionada para desligar a tela.

Rickon Gao
fonte
2

Basta adicionar

android:keepScreenOn="true" 

ou chamar

setKeepScreenOn(true) 

na visão dos pais.

mani
fonte
1

Eu não teria esperança de "acordar a tela" na atividade. Se a tela estiver desligada, a atividade provavelmente está em um estado de pausa e não deve estar executando nenhum código.

Ao acordar, surge a questão da tela de bloqueio. Não sei como qualquer aplicativo pode ignorar automaticamente a tela de bloqueio.

Você deve considerar a execução de suas tarefas em segundo plano em um serviço e, em seguida, usar o gerenciador de notificações para enviar uma notificação quando o que for detectado. A notificação deve fornecer algum tipo de alerta do dispositivo (tela de ativação, ícone de notificação, led de notificação, etc). Ao clicar na notificação, ele pode lançar a intenção de iniciar sua atividade.

Você também pode tentar iniciar a atividade direto do serviço, mas realmente não sei se isso ligará a tela ou ignorará a tela de bloqueio.

HaMMeReD
fonte
Obrigado pela resposta, coloquei um código de vibração e, quando desligo a tela e ativo um dos meus sensores, ele vibra. Portanto, o código está definitivamente em execução. A tela de bloqueio não é grande coisa, eu apenas uso a proteção do teclado.
thegreyspot
Mesmo que o código seja executado, ele está fora do ciclo de vida. Você não pode confiar em atividades que estão fora da tela. Pense em downloaders de jogos, a maioria é escrita na atividade e você pode sair por talvez 30 segundos a alguns minutos e eles ainda farão o download, mas geralmente quebram porque o sistema operacional mata a atividade com base em seus padrões de uso.
HaMMeReD
1

De acordo com a API 28 do Android e acima, você precisa fazer o seguinte para ligar a tela

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