Manter o dispositivo ativo

Para evitar o consumo da bateria, um dispositivo Android que fica inativo rapidamente entra em suspensão. No entanto, há momentos em que um aplicativo precisa ativar a tela ou a CPU e mantê-la ativa para concluir algum trabalho.

A abordagem adotada depende das necessidades do app. No entanto, uma regra geral é que você precisa usar a abordagem mais leve possível para o app, minimizando o impacto dele nos recursos do sistema. As seções a seguir descrevem como lidar com os casos em que o comportamento de suspensão padrão do dispositivo é incompatível com os requisitos do app.

Alternativas ao uso de wake locks

Antes de adicionar suporte a wake lock, confira se os casos de uso do app oferecem suporte a uma das soluções alternativas abaixo:

Manter a tela ativada

Alguns apps precisam manter a tela ativada, por exemplo, os apps de jogos ou filmes. A melhor maneira de fazer isso é usando o FLAG_KEEP_SCREEN_ON na sua atividade, e somente em uma atividade, nunca em um serviço ou outro componente do app. Por exemplo:

Kotlin

class MainActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    }
}

Java

public class MainActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  }
}

A vantagem dessa abordagem é que, ao contrário dos wake locks (discutidos em Manter a CPU ativada), ela não exige uma permissão especial, e a plataforma gerencia corretamente a movimentação do usuário entre os aplicativos, sem que o app precise se preocupar com a liberação de recursos não utilizados.

Outra maneira de implementar isso é no arquivo XML de layout do aplicativo, usando o atributo android:keepScreenOn:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:keepScreenOn="true">
    ...
</RelativeLayout>

Usar android:keepScreenOn="true" é equivalente a usar FLAG_KEEP_SCREEN_ON. Você pode usar a abordagem que for melhor para seu app. A vantagem de definir a flag de maneira programática na atividade é que ela oferece a opção de limpar programaticamente a flag mais tarde e, assim, permitir que a tela seja desativada.

Modo ambiente para TV

Na TV, FLAG_KEEP_SCREEN_ON precisa ser usado para evitar que o dispositivo entre no Modo ambiente durante a reprodução de vídeo ativa. Quando FLAG_KEEP_SCREEN_ON não for definido pela atividade em primeiro plano, o dispositivo entrará automaticamente no Modo ambiente após um período de inatividade.

Manter a CPU ligada

Se você precisa manter a CPU em execução para concluir algum trabalho antes que o dispositivo entre no modo de suspensão, use um recurso de serviço do sistema PowerManager chamado wake locks. Os wake locks permitem que o aplicativo controle o estado de energia do dispositivo host.

Criar e manter wake locks pode ter um impacto drástico na duração da bateria do dispositivo host. Portanto, use wake locks apenas quando estritamente necessário e os mantenha pelo menor tempo possível. Por exemplo, você nunca precisa usar um wake lock em uma atividade. Conforme descrito acima, se você quiser manter a tela ativada durante a atividade, use FLAG_KEEP_SCREEN_ON.

Um caso legítimo de uso de um wake lock pode ser um serviço em segundo plano que precisa usar um wake lock para manter a CPU funcionando enquanto a tela está desativada. No entanto, essa prática precisa ser minimizada devido ao impacto na duração da bateria.

Para usar um wake lock, a primeira etapa é adicionar a permissão WAKE_LOCK ao arquivo de manifesto do app:

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

Caso seu app inclua um broadcast receiver que use um serviço para realizar tarefas, veja como definir um wake lock diretamente:

Kotlin

val wakeLock: PowerManager.WakeLock =
        (getSystemService(Context.POWER_SERVICE) as PowerManager).run {
            newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyWakelockTag").apply {
                acquire()
            }
        }

Java

PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
        "MyApp::MyWakelockTag");
wakeLock.acquire();

Para liberar o wake lock, chame wakelock.release(). Isso libera sua reivindicação sobre a CPU. É importante liberar um wake lock assim que o app terminar de usá-lo para evitar o consumo da bateria.