Serviços em primeiro plano

Os serviços em primeiro plano executam operações perceptíveis pelo usuário.

Os serviços em primeiro plano mostram uma notificação na barra de status para informar aos usuários que o app está realizando uma tarefa em primeiro plano e consumindo recursos do sistema.

Confira alguns exemplos de apps que usam serviços em primeiro plano:

  • Um app de reprodução de música que toca músicas em um serviço em primeiro plano. A notificação pode mostrar a música que está tocando no momento.
  • Um app fitness que registra a corrida de um usuário em um serviço em primeiro plano após receber a permissão dele. A notificação pode mostrar a distância que o usuário percorreu durante a sessão de condicionamento físico atual.

Use um serviço em primeiro plano somente quando o app precisar realizar uma tarefa que seja perceptível pelo usuário, mesmo que ele não esteja interagindo diretamente com o app. Se a ação for de importância baixa o suficiente para que você queira usar uma notificação de prioridade mínima, crie uma tarefa em segundo plano.

Este documento descreve a permissão necessária para usar serviços em primeiro plano e como iniciar um serviço desse tipo e removê-lo do segundo plano. Ela também descreve como associar determinados casos de uso a tipos de serviço em primeiro plano e as restrições de acesso que entram em vigor quando você inicia um serviço desse tipo de um app em execução em segundo plano.

O usuário pode dispensar a notificação por padrão

No Android 13 (nível 33 da API) e versões mais recentes, os usuários podem dispensar a notificação associada a um serviço em primeiro plano por padrão. Para fazer isso, os usuários executam um gesto de deslizar na notificação. Tradicionalmente, a notificação não é dispensada, a menos que o serviço em primeiro plano seja interrompido ou removido do primeiro plano.

Se você quiser que a notificação não possa ser dispensada pelo usuário, transmita true para o método setOngoing() ao criar sua notificação usando Notification.Builder.

Serviços que mostram uma notificação imediatamente

Se um serviço em primeiro plano tiver pelo menos uma das características abaixo, o sistema vai mostrar a notificação associada imediatamente após o início do serviço, mesmo em dispositivos com o Android 12 ou versões mais recentes:

No Android 13 (nível 33 da API) ou versões mais recentes, se o usuário negar a permissão de notificação, ele ainda vai receber avisos relacionados a serviços em primeiro plano no Gerenciador de tarefas, mas não na gaveta de notificações.

Declarar serviços em primeiro plano no manifesto

No manifesto do app, declare cada um dos serviços em primeiro plano com um elemento <service>. Para cada serviço, use um atributo android:foregroundServiceType para declarar o tipo de trabalho que ele faz.

Por exemplo, se o app cria um serviço em primeiro plano que toca música, você pode declarar o serviço desta forma:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>

    <service
        android:name=".MyMediaPlaybackService"
        android:foregroundServiceType="mediaPlayback"
        android:exported="false">
    </service>
</manifest>

Se vários tipos se aplicarem ao seu serviço, separe-os com o operador |. Por exemplo, um serviço que usa a câmera e o microfone o declararia da seguinte maneira:

android:foregroundServiceType="camera|microphone"

Solicitar as permissões de serviço em primeiro plano

Os apps direcionados ao Android 9 (API de nível 28) ou versões mais recentes que usam serviços em primeiro plano precisam solicitar o FOREGROUND_SERVICE no manifesto do app, conforme mostrado no snippet de código abaixo. Essa é uma permissão normal, portanto, o sistema a concede automaticamente ao app solicitante.

Além disso, se o app for direcionado ao nível 34 da API ou mais recente, ele precisará solicitar o tipo de permissão adequado para o tipo de trabalho que o serviço em primeiro plano vai fazer. Cada tipo de serviço em primeiro plano tem um tipo de permissão correspondente. Por exemplo, se um app inicia um serviço em primeiro plano que usa a câmera, é necessário solicitar as permissões FOREGROUND_SERVICE e FOREGROUND_SERVICE_CAMERA. Essas são permissões normais. Portanto, o sistema as concede automaticamente se estiverem listadas no manifesto.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>

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

    <application ...>
        ...
    </application>
</manifest>

Pré-requisitos de serviços em primeiro plano

No Android 14 (nível 34 da API) e versões mais recentes, ao iniciar um serviço em primeiro plano, o sistema verifica se há pré-requisitos específicos com base no tipo de serviço. Por exemplo, se você tentar iniciar um serviço em primeiro plano do tipo location, o sistema vai verificar se o app já tem a permissão ACCESS_COARSE_LOCATION ou ACCESS_FINE_LOCATION. Caso contrário, o sistema vai gerar uma SecurityException.

Por isso, confirme se os pré-requisitos necessários foram atendidos antes de iniciar um serviço em primeiro plano. A documentação do tipo de serviço em primeiro plano lista os pré-requisitos necessários para cada tipo.

Iniciar um serviço em primeiro plano

Antes de solicitar que o sistema execute um serviço como primeiro plano, inicie o próprio serviço:

Kotlin

val intent = Intent(...) // Build the intent for the service
context.startForegroundService(intent)

Java

Context context = getApplicationContext();
Intent intent = new Intent(...); // Build the intent for the service
context.startForegroundService(intent);

No serviço, geralmente em onStartCommand(), é possível solicitar que ele seja executado em primeiro plano. Para fazer isso, chame ServiceCompat.startForeground(), disponível no androidx-core 1.12 e em versões mais recentes. Esse método usa os seguintes parâmetros:

Eles podem ser um subconjunto dos tipos declarados no manifesto, dependendo do caso de uso específico. Em seguida, se você precisar adicionar mais tipos de serviço, chame startForeground() novamente.

Por exemplo, suponha que um app fitness execute um serviço de rastreador de corrida que sempre precisa de informações de location, mas pode ou não abrir mídia. Você precisaria declarar location e mediaPlayback no manifesto. Se um usuário iniciar uma execução e quiser apenas rastrear a localização, o app precisará chamar startForeground() e transmitir apenas a permissão ACCESS_FINE_LOCATION. Em seguida, se o usuário quiser começar a tocar áudio, chame startForeground() novamente e transmita a combinação bit a bit de todos os tipos de serviço em primeiro plano (neste caso, ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK).

Confira um exemplo que inicia um serviço em primeiro plano da câmera:

Kotlin

class MyCameraService: Service() {

  private fun startForeground() {
    // Before starting the service as foreground check that the app has the
    // appropriate runtime permissions. In this case, verify that the user has
    // granted the CAMERA permission.
    val cameraPermission =
            ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
    if (cameraPermission == PackageManager.PERMISSION_DENIED) {
        // Without camera permissions the service cannot run in the foreground
        // Consider informing user or updating your app UI if visible.
        stopSelf()
        return
    }

    try {
        val notification = NotificationCompat.Builder(this, "CHANNEL_ID")
            // Create the notification to display while the service is running
            .build()
        ServiceCompat.startForeground(
            /* service = */ this,
            /* id = */ 100, // Cannot be 0
            /* notification = */ notification,
            /* foregroundServiceType = */
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA
            } else {
                0
            },
        )
    } catch (e: Exception) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
                && e is ForegroundServiceStartNotAllowedException) {
            // App not in a valid state to start foreground service
            // (e.g. started from bg)
        }
        // ...
    }
  }
}

Java

public class MyCameraService extends Service {

    private void startForeground() {
        // Before starting the service as foreground check that the app has the
        // appropriate runtime permissions. In this case, verify that the user
        // has granted the CAMERA permission.
        int cameraPermission =
            ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
        if (cameraPermission == PackageManager.PERMISSION_DENIED) {
            // Without camera permissions the service cannot run in the
            // foreground. Consider informing user or updating your app UI if
            // visible.
            stopSelf();
            return;
        }

        try {
            Notification notification =
                new NotificationCompat.Builder(this, "CHANNEL_ID")
                    // Create the notification to display while the service
                    // is running
                    .build();
            int type = 0;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                type = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
            }
            ServiceCompat.startForeground(
                    /* service = */ this,
                    /* id = */ 100, // Cannot be 0
                    /* notification = */ notification,
                    /* foregroundServiceType = */ type
            );
        } catch (Exception e) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
                    e instanceof ForegroundServiceStartNotAllowedException
            ) {
                // App not in a valid state to start foreground service
                // (e.g started from bg)
            }
            // ...
        }
    }

    //...
}

Remover um serviço do primeiro plano

Para remover o serviço do primeiro plano, chame stopForeground(). Esse método usa um booleano, que indica se a notificação da barra de status também será removida. O serviço continua em execução.

Se você interromper o serviço enquanto ele for executado em primeiro plano, a notificação será removida.

Processar a parada iniciada pelo usuário de apps que executam serviços em primeiro plano

Na parte de baixo da gaveta de notificações, há um botão que indica o
    número de apps sendo executados em segundo plano. Quando você pressiona
    esse botão, uma caixa de diálogo é exibida, listando os nomes de diferentes apps. O
    botão &quot;Parar&quot; fica à direita de cada app
Figura 1. Fluxo de trabalho do gerenciador de tarefas em dispositivos com o Android 13 ou versões mais recentes.

No Android 13 (nível 33 da API) e versões mais recentes, os usuários podem concluir um fluxo de trabalho na gaveta de notificações para interromper um app que tenha serviços em primeiro plano em andamento, independente da versão do SDK de destino do app. Essa funcionalidade, chamada de gerenciador de tarefas, mostra uma lista de apps que estão executando um serviço em primeiro plano.

A lista mostrada é Apps ativos. Ao lado de cada app há um botão Parar. A Figura 1 ilustra o fluxo de trabalho do gerenciador de tarefas em um dispositivo com o Android 13.

Quando o usuário pressiona o botão Stop ao lado do app no gerenciador de tarefas, as seguintes ações ocorrem:

  • O sistema remove seu app da memória. Portanto, todo o app é interrompido, não apenas o serviço em primeiro plano em execução.
  • O sistema remove a backstack de atividades do app.
  • Todas as reproduções de mídia são interrompidas.
  • A notificação associada ao serviço em primeiro plano é removida.
  • Seu app permanece no histórico.
  • Os jobs programados são executados no horário programado.
  • Os alarmes disparam no horário ou na janela de tempo programados.

Para testar se o app se comporta como esperado quando um usuário interrompe o app, execute o seguinte comando ADB em uma janela de terminal:

adb shell cmd activity stop-app PACKAGE_NAME

Isenções

O sistema oferece vários níveis de isenção para determinados tipos de apps, apresentados nas seções abaixo.

As isenções são aplicadas por app, e não por processo. Se o sistema isentar um processo em um app, todos os outros processos nesse app também vão ser isentos.

Isenções de exibição no Gerenciador de tarefas

Os apps abaixo podem executar um serviço em primeiro plano e não aparecer no gerenciador de tarefas:

Isenções para que o app não possa ser interrompido pelo usuário

Quando os tipos de apps abaixo executam um serviço em primeiro plano, eles aparecem no gerenciador de tarefas, mas não há um botão Stop ao lado do nome do app para o usuário tocar:

Usar APIs específicas em vez de serviços em primeiro plano

Para muitos casos de uso, existem APIs de plataforma ou Jetpack que podem ser usadas para trabalhos em que você poderia usar um serviço em primeiro plano. Se houver uma API personalizada adequada, use-a quase sempre em vez de um serviço em primeiro plano. As APIs personalizadas geralmente oferecem outros recursos específicos para casos de uso que, de outra forma, você precisaria criar por conta própria. Por exemplo, a API Bubbles processa a lógica complexa da interface para apps de mensagens que precisam implementar recursos de balão de chat.

A documentação dos tipos de serviço em primeiro plano lista boas alternativas a serem usadas em vez dos serviços em primeiro plano.

Restrições para iniciar um serviço em primeiro plano em segundo plano

Os apps destinados ao Android 12 ou versões mais recentes não podem iniciar serviços em primeiro plano enquanto estão sendo executados em segundo plano, exceto em alguns casos especiais. Se um app tentar iniciar um serviço em primeiro plano enquanto estiver em segundo plano e o serviço em primeiro plano não se enquadrar em um dos casos excepcionais, o sistema vai gerar uma ForegroundServiceStartNotAllowedException.

Além disso, se um app quiser iniciar um serviço em primeiro plano que precise de permissões durante o uso (por exemplo, permissões de sensor corporal, câmera, microfone ou localização), ele não poderá criar o serviço enquanto estiver em segundo plano, mesmo que o app se enquadra em uma das isenções de restrições de inicialização em segundo plano. O motivo é explicado na seção Restrições para iniciar serviços em primeiro plano que precisam de permissões durante o uso.

Isenções de restrições de início em segundo plano

Nas situações abaixo, seu app pode iniciar serviços em primeiro plano mesmo quando está sendo executado em segundo plano:

Restrições para iniciar serviços em primeiro plano que precisam de permissões durante o uso

No Android 14 (nível 34 da API) ou versões mais recentes, há situações especiais que você precisa conhecer se estiver iniciando um serviço em primeiro plano que precise de permissões durante o uso.

Caso o app seja destinado ao Android 14 ou versões mais recentes, o sistema operacional vai conferir quando você criar um serviço em primeiro plano para garantir que o app tenha todas as permissões apropriadas para esse tipo de serviço. Por exemplo, quando você cria um serviço em primeiro plano do tipo microfone, o sistema operacional verifica se o app tem a permissão RECORD_AUDIO no momento. Se você não tiver essa permissão, o sistema vai gerar uma SecurityException.

Para permissões em uso, isso causa um possível problema. Se o app tiver uma permissão durante o uso, ele só terá essa permissão enquanto estiver em primeiro plano. Isso significa que, se o app estiver em segundo plano e tentar criar um serviço em primeiro plano do tipo câmera, localização ou microfone, o sistema detectará que o app não tem atualmente as permissões necessárias e vai gerar uma SecurityException.

Da mesma forma, se o app estiver em segundo plano e criar um serviço de saúde que precisa da permissão BODY_SENSORS_BACKGROUND, ele não terá essa permissão, e o sistema vai gerar uma exceção. Isso não se aplica se for um serviço de saúde que precisa de permissões diferentes, como ACTIVITY_RECOGNITION. Chamar ContextCompat.checkSelfPermission() não evita esse problema. Se o app tiver uma permissão durante o uso e chamar checkSelfPermission() para verificar se tem essa permissão, o método retornará PERMISSION_GRANTED mesmo que o app esteja em segundo plano. Quando o método retorna PERMISSION_GRANTED, informa que "seu app tem essa permissão enquanto o app está em uso".

Por esse motivo, se o serviço em primeiro plano precisar de uma permissão durante o uso, chame Context.startForegroundService() ou Context.bindService() enquanto o app tiver uma atividade visível, a menos que o serviço se encaixe em uma das isenções definidas.

Isenções de restrições em permissões em uso

Em algumas situações, mesmo que um serviço em primeiro plano seja iniciado enquanto o app for executado em segundo plano, ele ainda poderá acessar informações de localização, câmera e microfone enquanto o app estiver sendo executado em primeiro plano ("durante o uso").

Nessas mesmas situações, se o serviço declarar um tipo de serviço em primeiro plano de location e for iniciado por um app que tem a permissão ACCESS_BACKGROUND_LOCATION, esse serviço poderá acessar informações de localização o tempo todo, mesmo quando o app for executado em segundo plano.

A lista a seguir contém estas situações:

  • Um componente do sistema inicia o serviço.
  • O serviço começa interagindo com widgets de apps.
  • O serviço começa interagindo com uma notificação.
  • O serviço começa como uma PendingIntent enviada de um app visível diferente.
  • O serviço é iniciado por um app que é um controlador de política de dispositivo executado no modo de proprietário do dispositivo.
  • O serviço começa por um app que fornece a VoiceInteractionService.
  • O serviço é iniciado por um app que tem a permissão privilegiada START_ACTIVITIES_FROM_BACKGROUND.
Determinar quais serviços são afetados no seu app

Ao testar seu app, inicie os serviços em primeiro plano. Se um serviço iniciado tiver acesso restrito à localização, ao microfone e à câmera, a seguinte mensagem será exibida no Logcat:

Foreground service started from background can not have \
location/camera/microphone access: service SERVICE_NAME