Os apps Android podem enviar ou receber mensagens de transmissão do sistema Android e outros apps Android, assim como os publicar-inscrever-se padrão de design. Essas transmissões são enviadas quando ocorre um evento de interesse. Por exemplo, o sistema Android envia transmissões quando vários eventos do sistema quando o sistema é inicializado ou quando o dispositivo começa a carregar. Aplicativos também podem enviar transmissões personalizadas, por exemplo, para notificar outros apps sobre algo em que possam estar interessados (por exemplo, alguns dados novos têm após o download).
O sistema otimiza a entrega de transmissões para manter integridade ideal do sistema. Portanto, os tempos de entrega das transmissões não são garantida. Os aplicativos que precisam de comunicação entre processos de baixa latência devem Considere usar serviços vinculados.
Os apps podem se registrar para receber transmissões específicas. Quando uma transmissão é enviada, o sistema encaminha automaticamente as transmissões para os apps inscritos 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, tome cuidado para não abusar a oportunidade de responder a transmissões e executar jobs em segundo plano que podem contribuir para um desempenho lento do sistema.
Sobre transmissões do sistema
O sistema envia transmissões automaticamente quando ocorrem vários eventos, por exemplo, quando o sistema entra e sai do modo avião. Sistema transmissões são enviadas a todos os apps inscritos para receber as evento.
A mensagem de transmissão em si é agrupada em um Intent
.
objeto cuja string de ação identifica o evento que ocorreu (por exemplo,
android.intent.action.AIRPLANE_MODE
). A intent também pode incluir
informações adicionais agrupadas em seu campo extra. Por exemplo, o avião
a intent de modo inclui um booleano extra que indica se o modo avião
O modo está ativado.
Para mais informações sobre como ler intents e receber a string de ação de uma intent, consulte Intents e intents Filtros.
Para obter uma lista completa das ações de transmissão do sistema, consulte o
BROADCAST_ACTIONS.TXT
no SDK do Android. Cada ação de transmissão tem um
campo constante associado a ele. Por exemplo, o valor da constante
ACTION_AIRPLANE_MODE_CHANGED
é
android.intent.action.AIRPLANE_MODE
. Documentação de cada ação de transmissão
está disponível no campo de constante associado.
Mudanças em transmissões do sistema
À medida que a plataforma Android evolui, ela muda periodicamente a forma como o sistema transmite se comportar. Lembre-se das seguintes mudanças para oferecer suporte a todas as versões do Android.
Android 14
Enquanto os apps estiverem na pasta armazenada em cache,
estado, a entrega de transmissão será
otimizada para a integridade do sistema. Por exemplo, transmissões menos importantes do sistema, como
como ACTION_SCREEN_ON
estão
adiado enquanto o app está em cache. Quando o app sai da configuração
em um processo ativo
ciclo de vida, o sistema entrega
as transmissões adiadas.
Transmissões importantes que são declaradas no do app, remova temporariamente apps do cache o estado para a entrega.
Android 9
A partir do Android 9 (nível 28 da API), a
NETWORK_STATE_CHANGED_ACTION
transmissão não receba informações sobre a localização ou informações
e identificáveis.
Além disso, se o app estiver instalado em um dispositivo com o Android 9 ou mais recente,
as transmissões do sistema por Wi-Fi não contêm SSIDs, BSSIDs, conexão
informações ou resultados de verificação. Para obter essas informações, chame
getConnectionInfo()
como alternativa.
Android 8.0
A partir do Android 8.0 (API de nível 26), o sistema impõe novos restrições para receptores declarados pelo manifesto.
Se o app for direcionado ao Android 8.0 ou a uma versão mais recente, 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 seu app especificamente). Você ainda pode usar um receptor registrado pelo contexto quando o o usuário está usando seu app ativamente.
Android 7.0
O Android 7.0 (nível 24 da API) e versões mais recentes não enviam o seguinte sistema transmissões:
Além disso, os apps destinados ao Android 7.0 e versões mais recentes precisam registrar a transmissão CONNECTIVITY_ACTION
.
usando registerReceiver(BroadcastReceiver, IntentFilter)
.
A declaração de um receptor no manifesto não funcionará.
Como receber transmissões
Os apps podem receber transmissões de duas maneiras: por receptores declarados pelo manifesto e receptores registrados pelo contexto.
Receptores declarados pelo manifesto
Se você declarar um broadcast receiver no manifesto, o sistema inicia o (se o app ainda não estiver em execução) quando a transmissão for enviada.
Para declarar um broadcast receiver no manifesto, siga as seguintes etapas:
Especifique a classe
<receiver>
. no manifesto do seu 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="APP_SPECIFIC_BROADCAST" /> </intent-filter> </receiver>
Os filtros de intent especificam as ações de transmissão em que seu receptor está inscrito.
Coloque
BroadcastReceiver
em uma subclasse e implementeonReceive(Context, Intent)
. A o broadcast receiver nos registros de exemplo a seguir e exibe o conteúdo da transmissão:Kotlin
private const val TAG = "MyBroadcastReceiver" class MyBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { StringBuilder().apply { append("Action: ${intent.action}\n") append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n") toString().also { log -> Log.d(TAG, log) val binding = ActivityNameBinding.inflate(layoutInflater) val view = binding.root setContentView(view) Snackbar.make(view, log, Snackbar.LENGTH_LONG).show() } } } }
Java
public class MyBroadcastReceiver extends BroadcastReceiver { private static final String TAG = "MyBroadcastReceiver"; @Override public void onReceive(Context context, Intent intent) { StringBuilder sb = new StringBuilder(); sb.append("Action: " + intent.getAction() + "\n"); sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n"); String log = sb.toString(); Log.d(TAG, log); ActivityNameBinding binding = ActivityNameBinding.inflate(layoutInflater); val view = binding.root; setContentView(view); Snackbar.make(view, log, Snackbar.LENGTH_LONG).show(); } }
Para ativar a vinculação de visualizações, configure a viewBinding no nível do módulo. build.gradle do módulo.
O gerenciador de pacotes do sistema registra o receptor quando o app é instalado. O receptor se torna um ponto de entrada separado para o app, o que significa que que o sistema possa iniciar o aplicativo e entregar a transmissão se o aplicativo não for em execução no momento.
O sistema cria um novo componente BroadcastReceiver
.
para lidar com cada transmissão recebida. Este objeto é válido apenas
durante a chamada para onReceive(Context, Intent)
. Assim que seu código
retornar desse método, o sistema considerará que o componente não
ativos.
Receptores registrados pelo contexto
Receptores registrados em contexto recebem transmissões, contanto que o registro
contexto é válido. Por exemplo, se você se registrar em um
Activity
contexto, você recebe transmissões, desde que a atividade não seja destruída. Se você
se registrar com o contexto do aplicativo, receberá transmissões, desde que o aplicativo
está em execução.
Para registrar um receptor com um contexto, siga as seguintes etapas:
No arquivo de build do módulo do app, inclua a versão 1.9.0 ou mais recente da da biblioteca AndroidX Core:
Groovy
dependencies { def core_version = "1.13.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.0.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-alpha02" }
Kotlin
dependencies { val core_version = "1.13.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.0.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-alpha02") }
Crie uma instância de
BroadcastReceiver
:Kotlin
val br: BroadcastReceiver = MyBroadcastReceiver()
Java
BroadcastReceiver br = new MyBroadcastReceiver();
Crie uma instância de
IntentFilter
:Kotlin
val filter = IntentFilter(APP_SPECIFIC_BROADCAST)
Java
IntentFilter filter = new IntentFilter(APP_SPECIFIC_BROADCAST);
Escolha se o broadcast receiver deve ser exportado e ficar visível para outros apps no dispositivo. Se o receptor estiver ouvindo transmissões enviadas do sistema ou de outros aplicativos, até mesmo de seus aplicativos, use a sinalização
RECEIVER_EXPORTED
. Se, em vez disso, o receptor estiver ouvindo apenas transmissões enviadas pelo seu app, use a sinalizaçãoRECEIVER_NOT_EXPORTED
.Kotlin
val listenToBroadcastsFromOtherApps = false val receiverFlags = if (listenToBroadcastsFromOtherApps) { ContextCompat.RECEIVER_EXPORTED } else { ContextCompat.RECEIVER_NOT_EXPORTED }
Java
boolean listenToBroadcastsFromOtherApps = false; if (listenToBroadcastsFromOtherApps) { receiverFlags = ContextCompat.RECEIVER_EXPORTED; } else { receiverFlags = ContextCompat.RECEIVER_NOT_EXPORTED; }
Registre o receptor chamando
registerReceiver()
:Kotlin
ContextCompat.registerReceiver(context, br, filter, receiverFlags)
Java
ContextCompat.registerReceiver(context, br, filter, receiverFlags);
Para parar de receber transmissões, chame
unregisterReceiver(android.content.BroadcastReceiver)
. Cancele o registro do destinatário quando não precisar mais dele ou do não é mais válido.Saiba onde registrar e cancelar o registro do destinatário. Por Por exemplo, se você registrar um receptor em
onCreate(Bundle)
usando o contexto da atividade, deve cancelar o registro emonDestroy()
para evitam o vazamento do receptor do contexto da atividade. Se você se registrar um receptor emonResume()
, deverá cancele a inscrição emonPause()
para evitar registrá-la várias vezes (se não quiser receber transmissões quando pausado, e isso pode reduzir a sobrecarga desnecessária do sistema). Não cancelar o registro emonSaveInstanceState(Bundle)
, porque ele não é chamado se o usuário voltar para a pilha de histórico.
Efeitos no estado do processo
Não importa se o BroadcastReceiver
estiver em operação ou não afetar seu processo, o que pode alterar
a probabilidade de encerramento do sistema. Um processo em primeiro plano executa o método onReceive()
de um receptor. A
executa o processo, exceto sob pressão extrema de memória.
O BroadcastReceiver é desativado após onReceive()
. O host do destinatário
processo é tão importante quanto os componentes do aplicativo. Se esse processo hospedar apenas
um receptor declarado por manifesto (uma ocorrência frequente em apps em que o usuário nunca
ou não tenha interagido recentemente), o sistema poderá eliminá-lo após onReceive()
para tornar
recursos disponíveis para outros processos mais críticos.
Assim, os broadcast receivers não devem iniciar linhas de execução de longa duração em segundo plano.
O sistema pode interromper o processo a qualquer momento após onReceive()
para recuperar
memória, encerrando a thread criada. Para manter o processo ativo, agende uma
JobService
do receptor usando JobScheduler
.
para que o sistema saiba que o processo ainda está funcionando.
A Visão geral do trabalho em segundo plano fornece mais detalhes.
Como enviar transmissões
O Android oferece três maneiras para os apps enviarem transmissões:
- O
sendOrderedBroadcast(Intent, String)
envia transmissões para um receptor por vez. À medida que cada receptor é executado, por sua vez, pode propagar um resultado para o próximo receptor ou pode cancela completamente a transmissão para que ela não seja transmitida a outros receptores. Os receptores de pedidos executados podem ser controlados com o Atributo android:priority do filtro de intent correspondente com o valor com a mesma prioridade serão executados em ordem arbitrária. - O método
sendBroadcast(Intent)
envia transmite para todos os receptores em uma ordem indefinida. Isso é chamado de Transmissão. 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 chamar sendBroadcast(Intent)
.
Kotlin
Intent().also { intent -> intent.setAction("com.example.broadcast.MY_NOTIFICATION") intent.putExtra("data", "Nothing to see here, move along.") sendBroadcast(intent) }
Java
Intent intent = new Intent(); intent.setAction("com.example.broadcast.MY_NOTIFICATION"); intent.putExtra("data", "Nothing to see here, move along."); sendBroadcast(intent);
A mensagem de transmissão é agrupada em um objeto Intent
.
A string de ação da intent deve fornecer a sintaxe do nome do pacote Java do aplicativo e
identificam exclusivamente o evento de transmissão. Você pode anexar informações adicionais
à 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)
na intent.
Como restringir transmissões com permissões
Com as permissões, você pode restringir as transmissões ao conjunto de apps que contêm determinadas permissões. É possível aplicar restrições ao remetente ou receptor de uma transmissão.
Como enviar com permissões
Quando você ligar para sendBroadcast(Intent, String)
ou
sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
, é possível especificar
. Somente os receptores que solicitaram essa permissão com
a tag
Kotlin
sendBroadcast(Intent(BluetoothDevice.ACTION_FOUND), Manifest.permission.BLUETOOTH_CONNECT)
Java
sendBroadcast(new Intent(BluetoothDevice.ACTION_FOUND), Manifest.permission.BLUETOOTH_CONNECT)
Para receber a transmissão, o app de destino precisa solicitar a permissão como mostrados abaixo:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
É 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 a página do
Permissões.
Como receber com permissões
Se você especificar um parâmetro de permissão ao registrar um broadcast receiver
(com registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
ou em
tag <receiver>
na sua
manifesto), somente as emissoras que solicitaram a permissão com o
Tag <uses-permission>
em seu manifesto (e, subsequentemente, receber a permissão se for
perigoso) pode enviar uma intent ao destinatário.
Por exemplo, suponha que o app de recebimento tenha um receptor declarado pelo manifesto como mostrados abaixo:
<receiver android:name=".MyBroadcastReceiver"
android:permission="android.permission.BLUETOOTH_CONNECT">
<intent-filter>
<action android:name="android.intent.action.ACTION_FOUND"/>
</intent-filter>
</receiver>
Ou o app de recebimento tenha um receptor registrado pelo contexto, conforme mostrado abaixo:
Kotlin
var filter = IntentFilter(Intent.ACTION_FOUND) registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null )
Java
IntentFilter filter = new IntentFilter(Intent.ACTION_FOUND); registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null );
Então, para poder enviar transmissões para esses receptores, o app de envio precisa solicitar a permissão conforme mostrado abaixo:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
Considerações de segurança e práticas recomendadas
Aqui estão algumas considerações de segurança e práticas recomendadas para enviar e recebendo transmissões:
Se vários aplicativos estiverem registrados para receber a mesma transmissão em seu ele pode fazer com que o sistema inicie muitos aplicativos, causando uma impacto significativo no desempenho do dispositivo e na experiência do usuário. Para evitar isso, prefira usar o registro de contexto na declaração do manifesto. Às vezes, o próprio sistema Android aplica o uso de dados receptores. Por exemplo, a transmissão
CONNECTIVITY_ACTION
é entregue apenas para receptores registrados pelo contexto.Não transmita informações confidenciais usando um intent implícito. A informações podem ser lidas por qualquer aplicativo que se registre 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 e versões mais recentes,
package com
setPackage(String)
ao enviar uma transmissão. O sistema restringe a transmissão ao conjunto de aplicativos que corresponder ao pacote.
Quando você registra um receptor, qualquer app pode enviar transmite para o receptor do seu app. Há várias maneiras de limitar o 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 (link em inglês) atributo como "false" no manifesto. O destinatário não recebe transmissões de fontes externas ao app.
O namespace das ações de transmissão é global. Certifique-se de que os nomes de ação e outras strings sejam escritas em um namespace de sua propriedade. Caso contrário, você pode entrar em conflito inadvertidamente com outros aplicativos.
Como o método
onReceive(Context, Intent)
de um receptor é executado linha de execução principal, ele precisa ser executado e retornar rapidamente. Se você precisar executar trabalhos de longa duração, tome cuidado ao gerar linhas de execução ou serviços em segundo plano porque o sistema pode encerrar todo o processo apósonReceive()
retorna. Para mais informações, consulte Efeito no processo state Para realizar um trabalho de longa duração, recomendamos:- Ligando para
goAsync()
no seu métodoonReceive()
do receptor e transmitindo oBroadcastReceiver.PendingResult
para uma linha de execução em segundo plano. Isso mantém a transmissão ativa após retornar deonReceive()
. No entanto, mesmo com essa abordagem, o sistema espera que você termine com a transmissão muito rapidamente (menos de 10 segundos). Ele permite que você se mova trabalham em outra linha de execução para evitar falhas na linha de execução principal. - programar um trabalho com
JobScheduler
. Para mais informações, consulte Serviço inteligente de Agendamento.
- Ligando para
Não iniciar atividades de broadcast receivers porque a experiência do usuário é desagradável. especialmente se houver mais de um receptor. Em vez disso, considere exibindo uma notificação.