Visão geral das transmissões

Os apps Android enviam e recebem mensagens de transmissão do sistema Android e de outros apps Android, de maneira semelhante ao padrão de design de publicação-assinatura. O sistema e os apps geralmente enviam transmissões quando determinados eventos ocorrem. Por exemplo, o sistema Android envia transmissões quando vários eventos do sistema ocorrem, como a inicialização do sistema ou o carregamento do dispositivo. Os apps também enviam transmissões personalizadas, por exemplo, para notificar outros apps sobre algo que possa interessar a eles (por exemplo, um novo download de dados).

Os apps podem se registrar para receber transmissões específicas. Quando uma transmissão é enviada, o sistema a encaminha automaticamente para os apps que se inscreveram para receber esse tipo específico de transmissão.

De modo geral, as transmissões podem ser usadas como um sistema de mensagens entre apps e fora do fluxo normal do usuário. No entanto, é preciso ter cuidado para não abusar da oportunidade de responder a transmissões e executar jobs em segundo plano que possam contribuir para um desempenho lento do sistema.

Sobre transmissões do sistema

O sistema envia transmissões automaticamente quando vários eventos do sistema ocorrem, como quando o sistema entra e sai do modo avião. Todos os apps com assinatura recebem essas transmissões.

O objeto Intent envolve a mensagem de transmissão. A string action identifica o evento que ocorreu, como android.intent.action.AIRPLANE_MODE. A intent também pode incluir outras informações agrupadas no campo extra. Por exemplo, a intent do modo avião inclui um extra booleano que indica se o modo avião está ativado ou não.

Para mais informações sobre como ler intents e receber a string de ação de uma intent, consulte Intents e filtros de intent.

Ações de transmissão do sistema

Para conferir uma lista completa de ações de transmissão do sistema, consulte o arquivo BROADCAST_ACTIONS.TXT no SDK do Android. Cada ação de transmissão tem um campo constante associado a ela. Por exemplo, o valor da constante ACTION_AIRPLANE_MODE_CHANGED é android.intent.action.AIRPLANE_MODE. A documentação de cada ação de transmissão está disponível no campo constante associado.

Mudanças em transmissões do sistema

À medida que a plataforma Android evolui, ela muda periodicamente o comportamento das transmissões do sistema. Mantenha as seguintes mudanças em mente para oferecer suporte a todas as versões do Android.

Android 16

No Android 16, a ordem de entrega de transmissão usando o android:priority atributo ou IntentFilter.setPriority() em processos diferentes não será garantida. As prioridades de transmissão só são respeitadas no mesmo processo de aplicativo, e não em todos os processos.

Além disso, as prioridades de transmissão são automaticamente restritas ao intervalo (SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1). Somente os componentes do sistema podem definir SYSTEM_LOW_PRIORITY, SYSTEM_HIGH_PRIORITY como prioridade de transmissão.

Android 14

Enquanto os apps estão em um estado armazenado em cache, o sistema otimiza a entrega de transmissão para a integridade do sistema. Por exemplo, o sistema adia transmissões do sistema menos importantes, como ACTION_SCREEN_ON enquanto o app está em um estado armazenado em cache. Quando o app sai do estado armazenado em cache para um ciclo de vida de processo ativo, o sistema entrega todas as transmissões adiadas.

As transmissões importantes que são declaradas no manifesto removem temporariamente os apps do estado armazenado em cache para entrega.

Android 9

A partir do Android 9 (nível 28 da API), a NETWORK_STATE_CHANGED_ACTION transmissão não recebe informações sobre a localização do usuário ou dados de identificação pessoal.

Se o app estiver instalado em um dispositivo com o Android 9.0 (nível 28 da API) ou versões mais recentes, o sistema não vai incluir SSIDs, BSSIDs, informações de conexão ou resultados de verificação em transmissões Wi-Fi. Para receber essas informações, chame getConnectionInfo() em vez disso.

Android 8.0

A partir do Android 8.0 (nível 26 da API), o sistema impõe outras restrições aos receptores declarados pelo manifesto.

Se o app for destinado ao Android 8.0 ou versões mais recentes, não será possível usar o manifesto para declarar um receptor para a maioria das transmissões implícitas (transmissões que não são direcionadas especificamente ao seu app). Ainda é possível usar um receptor registrado no contexto quando o usuário está usando o app ativamente.

Android 7.0

O Android 7.0 (nível 24 da API) e versões mais recentes não enviam as seguintes transmissões do sistema:

Além disso, os apps destinados ao Android 7.0 e versões mais recentes precisam registrar a CONNECTIVITY_ACTION transmissão usando registerReceiver(BroadcastReceiver, IntentFilter). Declarar um receptor no manifesto não funciona.

Receber transmissões

Os apps podem receber transmissões de duas maneiras: por receptores registrados no contexto e receptores declarados pelo manifesto.

Receptores registrados pelo contexto

Os receptores registrados no contexto recebem transmissões enquanto o contexto de registro for válido. Isso geralmente ocorre entre as chamadas para registerReceiver e unregisterReceiver. O contexto de registro também se torna inválido quando o sistema destrói o contexto correspondente. Por exemplo, se você se registrar em um contexto Activity, vai receber transmissões enquanto a atividade permanecer ativa. Se você se registrar no contexto do aplicativo, vai receber transmissões enquanto o app estiver em execução.

Para registrar um receptor com um contexto, siga as seguintes etapas:

  1. No arquivo de build do módulo do app, inclua a versão 1.9.0 ou mais recente da biblioteca AndroidX Core:

    Groovy

    dependencies {
        def core_version = "1.19.1"
    
        // Java language implementation
        implementation "androidx.core:core:$core_version"
        // Kotlin
        implementation "androidx.core:core-ktx:$core_version"
    
        // To use RoleManagerCompat
        implementation "androidx.core:core-role:1.1.0"
    
        // To use the Animator APIs
        implementation "androidx.core:core-animation:1.0.0"
        // To test the Animator APIs
        androidTestImplementation "androidx.core:core-animation-testing:1.0.0"
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation "androidx.core:core-performance:1.0.0"
    
        // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google
        implementation "androidx.core:core-google-shortcuts:1.1.0"
    
        // Optional - to support backwards compatibility of RemoteViews
        implementation "androidx.core:core-remoteviews:1.1.0"
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation "androidx.core:core-splashscreen:1.2.0"
    }

    Kotlin

    dependencies {
        val core_version = "1.19.1"
    
        // Java language implementation
        implementation("androidx.core:core:$core_version")
        // Kotlin
        implementation("androidx.core:core-ktx:$core_version")
    
        // To use RoleManagerCompat
        implementation("androidx.core:core-role:1.1.0")
    
        // To use the Animator APIs
        implementation("androidx.core:core-animation:1.0.0")
        // To test the Animator APIs
        androidTestImplementation("androidx.core:core-animation-testing:1.0.0")
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation("androidx.core:core-performance:1.0.0")
    
        // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google
        implementation("androidx.core:core-google-shortcuts:1.1.0")
    
        // Optional - to support backwards compatibility of RemoteViews
        implementation("androidx.core:core-remoteviews:1.1.0")
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation("androidx.core:core-splashscreen:1.2.0")
    }
  2. Crie uma instância de BroadcastReceiver:

    Kotlin

    val myBroadcastReceiver = MyBroadcastReceiver()
    

    Java

    MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
    
  3. Crie uma instância de IntentFilter:

    Kotlin

    val filter = IntentFilter("com.example.snippets.ACTION_UPDATE_DATA")
    

    Java

    IntentFilter filter = new IntentFilter("com.example.snippets.ACTION_UPDATE_DATA");
    
  4. Escolha se o broadcast receiver precisa ser exportado e visível para outros apps no dispositivo. Se esse receptor estiver ouvindo transmissões enviadas pelo sistema ou por outros apps, mesmo outros apps que você possui, use a flag RECEIVER_EXPORTED. Se, em vez disso, esse receptor estiver ouvindo apenas transmissões enviadas pelo seu app, use a flag RECEIVER_NOT_EXPORTED.

    Kotlin

    val listenToBroadcastsFromOtherApps = false
    val receiverFlags = if (listenToBroadcastsFromOtherApps) {
        ContextCompat.RECEIVER_EXPORTED
    } else {
        ContextCompat.RECEIVER_NOT_EXPORTED
    }
    

    Java

    boolean listenToBroadcastsFromOtherApps = false;
    int receiverFlags = listenToBroadcastsFromOtherApps
            ? ContextCompat.RECEIVER_EXPORTED
            : ContextCompat.RECEIVER_NOT_EXPORTED;
    
  5. Registre o receptor chamando registerReceiver():

    Kotlin

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags)
    

    Java

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags);
    
  6. Para parar de receber transmissões, chame unregisterReceiver(android.content.BroadcastReceiver). Não deixe de cancelar o registro do receptor quando ele não for mais necessário ou o contexto não for mais válido.

Cancelar o registro do broadcast receiver

Enquanto o broadcast receiver estiver registrado, ele vai manter uma referência ao contexto em que você o registrou. Isso pode causar vazamentos se o escopo registrado do receptor exceder o escopo do ciclo de vida do contexto. Por exemplo, isso pode ocorrer quando você registra um receptor em um escopo de atividade, mas esquece de cancelar o registro quando o sistema destrói a atividade. Portanto, sempre cancele o registro do broadcast receiver.

Kotlin

class MyActivity : ComponentActivity() {
    private val myBroadcastReceiver = MyBroadcastReceiver()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags)
        setContent { MyApp() }
    }

    override fun onDestroy() {
        super.onDestroy()
        // When you forget to unregister your receiver here, you're causing a leak!
        this.unregisterReceiver(myBroadcastReceiver)
    }
}

Java

class MyActivity extends ComponentActivity {
    MyBroadcastReceiver myBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ...
        ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags);
        // Set content
    }
}

Registrar receptores no menor escopo

O broadcast receiver só precisa ser registrado quando você estiver realmente interessado no resultado. Escolha o menor escopo de receptor possível:

  • LifecycleResumeEffect ou métodos de ciclo de vida onResume/onPause da atividade: o broadcast receiver só recebe atualizações enquanto o app está no estado retomado.
  • LifecycleStartEffect ou métodos de ciclo de vida onStart/onStop da atividade: o broadcast receiver só recebe atualizações enquanto o app está no estado retomado.
  • DisposableEffect: o broadcast receiver só recebe atualizações enquanto o elemento combinável está na árvore de composição. Esse escopo não está anexado ao escopo do ciclo de vida da atividade. Considere registrar o receptor no contexto do aplicativo. Isso ocorre porque o elemento combinável pode, teoricamente, sobreviver ao escopo do ciclo de vida da atividade e vazar a atividade.
  • Atividade onCreate/onDestroy: o broadcast receiver recebe atualizações enquanto a atividade está no estado criado. Não deixe de cancelar o registro em onDestroy() e não em onSaveInstanceState(Bundle), porque isso pode não ser chamado.
  • Um escopo personalizado: por exemplo, você pode registrar um receptor no escopo ViewModel, para que ele sobreviva à recriação da atividade. Não deixe de usar o contexto do aplicativo para registrar o receptor, já que ele pode sobreviver ao escopo do ciclo de vida da atividade e vazar a atividade.

Criar elementos combináveis com e sem estado

O Compose tem elementos combináveis com e sem estado. Registrar ou cancelar o registro de um broadcast receiver dentro de um elemento combinável o torna com estado. O elemento combinável não é uma função determinística que renderiza o mesmo conteúdo quando os mesmos parâmetros são transmitidos. O estado interno pode mudar com base em chamadas para o broadcast receiver registrado.

Como prática recomendada no Compose, sugerimos que você divida os elementos combináveis em versões com e sem estado. Portanto, recomendamos que você eleve a criação do broadcast receiver de um elemento combinável para torná-lo sem estado:

@Composable
fun MyStatefulScreen() {
    val myBroadcastReceiver = remember { MyBroadcastReceiver() }
    val context = LocalContext.current
    LifecycleStartEffect(true) {
        // ...
        ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, flags)
        onStopOrDispose { context.unregisterReceiver(myBroadcastReceiver) }
    }
    MyStatelessScreen()
}

@Composable
fun MyStatelessScreen() {
    // Implement your screen
}

Receptores declarados pelo manifesto

Se você declarar um broadcast receiver no manifesto, o sistema vai iniciar o app quando a transmissão for enviada. Se o app ainda não estiver em execução, o sistema vai iniciá-lo.

Para declarar um broadcast receiver no manifesto, siga as seguintes etapas:

  1. Especifique o <receiver> elemento no manifesto do app.

    <!-- If this receiver listens for broadcasts sent from the system or from
         other apps, even other apps that you own, set android:exported to "true". -->
    <receiver android:name=".MyBroadcastReceiver" android:exported="false">
        <intent-filter>
            <action android:name="com.example.snippets.ACTION_UPDATE_DATA" />
        </intent-filter>
    </receiver>
    

    Os filtros de intent especificam as ações de transmissão a que o receptor se inscreve.

  2. Crie uma subclasse de BroadcastReceiver e implemente onReceive(Context, Intent). O broadcast receiver no exemplo a seguir registra e mostra o conteúdo da transmissão:

    Kotlin

    class MyBroadcastReceiver : BroadcastReceiver() {
    
        @Inject
        lateinit var dataRepository: DataRepository
    
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == "com.example.snippets.ACTION_UPDATE_DATA") {
                val data = intent.getStringExtra("com.example.snippets.DATA") ?: "No data"
                // Do something with the data, for example send it to a data repository:
                dataRepository.updateData(data)
            }
        }
    }
    

    Java

    public static class MyBroadcastReceiver extends BroadcastReceiver {
    
        @Inject
        DataRepository dataRepository;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Objects.equals(intent.getAction(), "com.example.snippets.ACTION_UPDATE_DATA")) {
                String data = intent.getStringExtra("com.example.snippets.DATA");
                // Do something with the data, for example send it to a data repository:
                if (data != null) { dataRepository.updateData(data); }
            }
        }
    }
    

O gerenciador de pacotes do sistema registra o receptor quando o app é instalado. O receptor se torna um ponto de entrada separado no app, o que significa que o sistema pode iniciar o app e entregar a transmissão se o app não estiver em execução.

O sistema cria um novo BroadcastReceiver objeto de componente para processar cada transmissão recebida. Esse objeto é válido apenas durante a duração de a chamada para onReceive(Context, Intent). Depois que o código retorna desse método, o sistema considera que o componente não está mais ativo.

Efeitos no estado do processo

Se o BroadcastReceiver está operando ou não, isso afeta o processo contido , o que pode alterar a probabilidade de encerramento do sistema. Um processo em primeiro plano executa o método onReceive() de um receptor. O sistema executa o processo, exceto em condições de pressão extrema de memória.

O sistema desativa o BroadcastReceiver após onReceive(). A importância do processo de host do receptor depende dos componentes do app. Se esse processo hospedar apenas um receptor declarado pelo manifesto, o sistema poderá encerrá-lo após onReceive() para liberar recursos para outros processos mais críticos. Isso é comum para apps com os quais o usuário nunca interagiu ou não interagiu recentemente.

Portanto, os broadcast receivers não devem iniciar linhas de execução em segundo plano de longa duração. O sistema pode interromper o processo a qualquer momento após onReceive() para recuperar a memória, encerrando a linha de execução criada. Para manter o processo ativo, programe um JobService do receptor usando o JobScheduler para que o sistema saiba que o processo ainda está funcionando. A visão geral do trabalho em segundo plano oferece mais detalhes.

Enviar transmissões

O Android oferece duas maneiras para os apps enviarem transmissões:

  • O método sendOrderedBroadcast(Intent, String) envia transmissões para um receptor por vez. À medida que cada receptor é executado, ele pode propagar um resultado para o próximo receptor. Ele também pode cancelar completamente a transmissão para que ela não chegue a outros receptores. É possível controlar a ordem em que os receptores são executados no mesmo processo do app. Para fazer isso, use o atributo android:priority do filtro de intent correspondente. Os receptores com a mesma prioridade são executados em uma ordem arbitrária.
  • O método sendBroadcast(Intent) envia transmissões para todos os receptores em uma ordem indefinida. Isso é chamado de transmissão normal. Isso é mais eficiente, mas significa que os receptores não podem ler resultados de outros receptores, propagar dados recebidos da transmissão ou cancelar a transmissão.

O snippet de código a seguir demonstra como enviar uma transmissão criando uma intent e chamando sendBroadcast(Intent).

Kotlin

val intent = Intent("com.example.snippets.ACTION_UPDATE_DATA").apply {
    putExtra("com.example.snippets.DATA", newData)
    setPackage("com.example.snippets")
}
context.sendBroadcast(intent)

Java

Intent intent = new Intent("com.example.snippets.ACTION_UPDATE_DATA");
intent.putExtra("com.example.snippets.DATA", newData);
intent.setPackage("com.example.snippets");
context.sendBroadcast(intent);

A mensagem de transmissão é encapsulada em um Intent objeto. A string action da intent precisa fornecer a sintaxe do nome do pacote Java do app e identificar exclusivamente o evento de transmissão. É possível anexar outras informações à intent com putExtra(String, Bundle). Também é possível limitar uma transmissão a um conjunto de apps na mesma organização chamando setPackage(String) em a intent.

Restringir transmissões com permissões

As permissões permitem restringir transmissões ao conjunto de apps que têm determinadas permissões. É possível aplicar restrições ao remetente ou ao receptor de uma transmissão.

Enviar transmissões com permissões

Ao chamar sendBroadcast(Intent, String) ou sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) , é possível especificar um parâmetro de permissão. Somente os receptores que solicitaram essa permissão com a tag <uses-permission> no manifesto podem receber a transmissão. Se a permissão for perigosa, você precisará conceder a permissão antes que o receptor possa receber a transmissão. Por exemplo, o código a seguir envia uma transmissão com uma permissão:

Kotlin

context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION)

Java

context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION);

Para receber a transmissão, o app receptor precisa solicitar a permissão da seguinte maneira:

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

É possível especificar uma permissão de sistema existente, como BLUETOOTH_CONNECT ou definir uma permissão personalizada com o elemento <permission>. Para informações sobre permissões e segurança em geral, consulte as permissões do sistema.

Receber transmissões com permissões

Se você especificar um parâmetro de permissão ao registrar um broadcast receiver (com registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) ou na <receiver> tag no manifesto), somente os transmissores que solicitaram a permissão com a <uses-permission> tag no manifesto poderão enviar uma intent ao receptor. Se a permissão for perigosa, o transmissor também precisará receber a permissão.

Por exemplo, suponha que o app receptor tenha um receptor declarado pelo manifesto da seguinte maneira:

<!-- If this receiver listens for broadcasts sent from the system or from
     other apps, even other apps that you own, set android:exported to "true". -->
<receiver
    android:name=".MyBroadcastReceiverWithPermission"
    android:permission="android.permission.ACCESS_COARSE_LOCATION"
    android:exported="true">
    <intent-filter>
        <action android:name="com.example.snippets.ACTION_UPDATE_DATA" />
    </intent-filter>
</receiver>

Ou o app receptor tem um receptor registrado no contexto da seguinte maneira:

Kotlin

ContextCompat.registerReceiver(
    context, myBroadcastReceiver, filter,
    android.Manifest.permission.ACCESS_COARSE_LOCATION,
    null, // scheduler that defines thread, null means run on main thread
    receiverFlags
)

Java

ContextCompat.registerReceiver(
        context, myBroadcastReceiver, filter,
        android.Manifest.permission.ACCESS_COARSE_LOCATION,
        null, // scheduler that defines thread, null means run on main thread
        receiverFlags
);

Em seguida, para poder enviar transmissões para esses receptores, o app de envio precisa solicitar a permissão da seguinte maneira:

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

Evitar transmissões no mesmo processo

As transmissões são projetadas como um mecanismo de comunicação entre processos (IPC, na sigla em inglês) para enviar mensagens entre diferentes apps ou entre o sistema e os apps. O envio de uma autotransmissão, que é uma transmissão para a qual todos os receptores são executados no mesmo processo que enviou a transmissão, é muito ineficiente, cria uma sobrecarga desnecessária do sistema e é fortemente desencorajado.

Dois cenários comuns em que os apps enviam transmissões para si mesmos incluem:

  • Comunicação entre componentes no mesmo processo: por exemplo, transmitir eventos ou dados entre atividades, fragmentos, serviços ou linhas de execução em segundo plano. Em vez de enviar transmissões, use mecanismos de comunicação padrão no processo , como o padrão observador ou fluxos reativos:

    • Fluxos Kotlin (SharedFlow e StateFlow): uma solução moderna, idiomática em Kotlin para emitir e observar fluxos de eventos ou atualizações de estado em corrotinas e componentes no app.
    • ViewModel compartilhado: facilita o compartilhamento de dados e eventos entre diferentes componentes da interface (como fragmentos ou elementos combináveis) na mesma atividade.
    • Callbacks e listeners: callbacks de interface padrão ou referências de função transmitidas diretamente entre componentes ou registradas com um repositório central ou controlador.
  • Processamento de eventos, jobs ou alarmes do sistema: por exemplo, receber um job programado, um alarme ou um callback do sistema e, em seguida, enviar uma transmissão para acionar o trabalho real. Em vez de enviar uma transmissão, conclua o trabalho diretamente nesse job (como um JobService ou WorkManager worker), um gerenciador de alarmes ou um componente de callback do sistema ou delegue diretamente às classes de lógica de negócios do app.

Em dispositivos com o Android 17 QPR2 ou versões mais recentes, o sistema entrega autotransmissões de maneira mais eficiente retornando-as ao processo de envio, que as entrega aos próprios receptores na linha de execução principal. O envio de uma autotransmissão não aumenta a importância do processo e não impede que um processo armazenado em cache seja congelado. Portanto, não confie em autotransmissões para manter o app em execução ou para trabalhar em segundo plano. Em vez disso, escolha a API apropriada para sua tarefa, conforme descrito na visão geral das tarefas em segundo plano. Mesmo com essa otimização, as autotransmissões são menos eficientes do que os mecanismos de comunicação no processo. Portanto, use essas alternativas.

Para mais informações sobre como projetar a comunicação entre componentes do app, consulte o Guia para a arquitetura do app.

Considerações sobre segurança

Confira algumas considerações de segurança para enviar e receber transmissões:

  • Se muitos apps tiverem se registrado para receber a mesma transmissão no manifesto, isso poderá fazer com que o sistema inicie muitos apps, causando um impacto substancial no desempenho do dispositivo e na experiência do usuário. Para evitar isso, prefira usar o registro de contexto em vez da declaração de manifesto. Às vezes, o próprio sistema Android exige o uso de receptores registrados no contexto. Por exemplo, a CONNECTIVITY_ACTION transmissão é entregue apenas a receptores registrados no contexto.

  • Não transmita informações sensíveis usando uma intent implícita. Qualquer app pode ler as informações se ele se registrar para receber a transmissão. Existem três maneiras de controlar quem pode receber suas transmissões:

    • Você pode especificar uma permissão enviando uma transmissão.
    • No Android 4.0 (nível 14 da API) e versões mais recentes, é possível especificar um pacote com setPackage(String) ao enviar uma transmissão. O sistema restringe a transmissão ao conjunto de apps que correspondem ao pacote.
  • Ao registrar um receptor, qualquer app pode enviar transmissões potencialmente maliciosas para o receptor do seu app. Há várias maneiras de limitar as transmissões que o app recebe:

    • Você pode especificar uma permissão registrando um broadcast receiver.
    • Para receptores declarados pelo manifesto, é possível definir o android:exported atributo como "false" no manifesto. O receptor não recebe transmissões de fontes fora do app.
  • O namespace das ações de transmissão é global. Verifique se os nomes de ações e outras strings estão gravados em um namespace de sua propriedade. Caso contrário, você poderá entrar em conflito inadvertidamente com outros apps.

  • Como o método onReceive(Context, Intent) de um receptor é executado na linha de execução principal, ele precisa ser executado e retornar rapidamente. Se você precisar realizar um trabalho de longa duração, tenha cuidado ao gerar linhas de execução ou iniciar serviços em segundo plano, porque o sistema pode encerrar todo o processo após o retorno de onReceive(). Para mais informações, consulte Efeito no estado do processo. Para realizar trabalhos de longa duração, recomendamos:

    • Chamar goAsync() no método onReceive() do receptor e transmitir o BroadcastReceiver.PendingResult para uma linha de execução em segundo plano. Isso mantém a transmissão ativa após o retorno de onReceive(). No entanto, mesmo com essa abordagem, o sistema espera que você termine a transmissão muito rapidamente (em menos de 10 segundos). Ele permite mover o trabalho para outra linha de execução para evitar falhas na linha de execução principal.
    • Programar um job com o JobScheduler. Para mais informações, consulte Programação inteligente de jobs.
  • Não inicie atividades de broadcast receivers, porque a experiência do usuário é instável, especialmente se houver mais de um receptor. Em vez disso, considere mostrar uma notificação.