Las aplicaciones de Android pueden enviar o recibir mensajes del sistema Android y otras apps para Android, al igual que la publicar-suscribirse patrón de diseño. Estas emisiones se envían cuando ocurre un evento de interés. Por ejemplo, el sistema Android envía emisiones cuando varios eventos del sistema como cuando se inicia el sistema o cuando el dispositivo comienza a cargarse. Aplicaciones también pueden enviar transmisiones personalizadas, por ejemplo, para notificar a otras apps sobre algo que podría interesarle (por ejemplo, algunos datos nuevos tienen que se haya descargado).
El sistema optimiza la entrega de transmisiones para mantener un buen estado óptimo del sistema. Por lo tanto, los tiempos de entrega de las transmisiones no son garantizada. Las apps que necesitan comunicación entre procesos de baja latencia considera usar servicios vinculados.
Las apps pueden registrarse para recibir emisiones específicas. Cuando se envía una transmisión, el sistema enruta automáticamente las transmisiones a las apps que se suscribieron recibir ese tipo particular de transmisión.
En términos generales, las emisiones pueden usarse como un sistema de mensajería entre apps. y fuera del flujo de usuarios normal. Sin embargo, debes tener cuidado de no abusar la oportunidad de responder a transmisiones y ejecutar trabajos en segundo plano que puede contribuir a un rendimiento lento del sistema.
Acerca de las emisiones del sistema
El sistema envía transmisiones automáticamente cuando ocurren varios eventos del sistema como cuando el sistema activa y desactiva el modo de avión. Sistema se envían a todas las apps que están suscritas para recibir el para cada evento.
El mensaje de emisión está envuelto en un Intent
.
objeto cuya cadena de acción identifica el evento que ocurrió (por ejemplo,
android.intent.action.AIRPLANE_MODE
). La intención también puede incluir
información adicional agrupada en su campo adicional. Por ejemplo, el avión
incluye un valor booleano adicional que indica si el
El modo está activado.
Para obtener más información sobre cómo leer intents y obtener la cadena de acción de un intent, consulta Cómo funcionan los intents Filtros.
Para obtener una lista completa de las acciones de emisión del sistema, consulta la
BROADCAST_ACTIONS.TXT
en el SDK de Android. Cada acción de transmisión tiene un
constante asociado a ella. Por ejemplo, el valor de la constante
ACTION_AIRPLANE_MODE_CHANGED
es
android.intent.action.AIRPLANE_MODE
Documentación para cada acción de transmisión
está disponible en su campo constante asociado.
Cambios en las emisiones del sistema
A medida que la plataforma de Android evoluciona, cambia periódicamente la forma en que las transmisiones y cómo se comportan. Ten en cuenta los siguientes cambios para brindar compatibilidad con todas las versiones de Android.
Android 14
Mientras las aplicaciones se encuentren en un almacenamiento
estado, la entrega de transmisiones es
están optimizados
para el estado del sistema. Por ejemplo, las transmisiones menos importantes del sistema, como
ya que ACTION_SCREEN_ON
son
se pospone mientras la app se encuentra en estado almacenado en caché. Cuando la app pase del estado
de estado en un proceso activo
ciclo de vida, el sistema entrega
las transmisiones diferidas.
Las transmisiones importantes que se declaran en el del contenedor quita temporalmente las apps del almacenamiento para la entrega.
Android 9
A partir de Android 9 (nivel de API 28), el
NETWORK_STATE_CHANGED_ACTION
no recibe información sobre la ubicación del usuario ni
datos identificables.
Además, si tu app está instalada en un dispositivo con Android 9 o versiones posteriores,
las transmisiones del sistema desde Wi-Fi no contienen SSID, BSSID, conexiones
o analizar los resultados. Para obtener esta información, llama a
getConnectionInfo()
en su lugar.
Android 8.0
A partir de Android 8.0 (nivel de API 26), el sistema impone restricciones restricciones en receptores declarados en el manifiesto.
Si tu app está orientada a Android 8.0 o versiones posteriores, no podrás usar el manifiesto para lo siguiente: declarar un receptor para la mayoría de las transmisiones implícitas (las que no se orientan específicamente en tu aplicación). Aún puedes usar una receptor registrado en el contexto cuando el usuario usa activamente la app.
Android 7.0
Android 7.0 (nivel de API 24) y las versiones posteriores no envían el siguiente sistema transmisiones:
Además, las apps orientadas a Android 7.0 y versiones posteriores deben registrar la transmisión de CONNECTIVITY_ACTION
usando registerReceiver(BroadcastReceiver, IntentFilter)
.
La declaración de un receptor en el manifiesto no funciona.
Cómo recibir emisiones
Las apps pueden recibir transmisiones de dos maneras: a través de receptores declarados en el manifiesto y receptores registrados en el contexto.
Receptores declarados en el manifiesto
Si declaras un receptor de emisión en tu manifiesto, el sistema inicia app (si aún no se está ejecutando) cuando se envía la transmisión.
Para declarar un receptor de emisión en el manifiesto, realiza los siguientes pasos:
Especifica el
<receiver>
. en el manifiesto de tu 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>
Los filtros de intents especifican las acciones de emisión a las que se suscribe tu receptor.
Crea la subclase
BroadcastReceiver
y, luego, implementaonReceive(Context, Intent)
. El el receptor de emisión en el siguiente ejemplo registra y muestra el contenido de la transmisión: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 habilitar la vinculación de vistas, configura viewBinding en el archivo. build.gradle.
El administrador de paquetes del sistema registra el receptor cuando se instala la app. El receptor se convierte en un punto de entrada separado a tu app. que el sistema pueda iniciar la app y entregar la transmisión si esta no en ejecución.
El sistema crea un nuevo componente BroadcastReceiver
.
para manejar cada emisión que recibe. Este objeto solo es válido
durante la llamada a onReceive(Context, Intent)
. Una vez que el código
que devuelve este método, el sistema considera que el componente ya no
activo.
Receptores registrados en el contexto
Los receptores registrados en el contexto reciben transmisiones siempre que su
contexto es válido. Por ejemplo, si te registras dentro de un
Activity
en otro contexto, recibirás transmisiones siempre que no se destruya la actividad. Si
te registres con el contexto de la Aplicación, recibirás transmisiones siempre que la app
se esté ejecutando.
Para registrar un receptor con un contexto, realiza los siguientes pasos:
En el archivo de compilación de nivel de módulo de tu app, incluye la versión 1.9.0 o posterior de la biblioteca de 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") }
Crea una instancia de
BroadcastReceiver
:Kotlin
val br: BroadcastReceiver = MyBroadcastReceiver()
Java
BroadcastReceiver br = new MyBroadcastReceiver();
Crea una instancia de
IntentFilter
:Kotlin
val filter = IntentFilter(APP_SPECIFIC_BROADCAST)
Java
IntentFilter filter = new IntentFilter(APP_SPECIFIC_BROADCAST);
Elige si el receptor de emisión se debe exportar y si es visible para otras apps en el dispositivo. Si este receptor está escuchando transmisiones enviadas desde el sistema o desde otras aplicaciones (incluso otras de tu propiedad), puedes utilizar la
RECEIVER_EXPORTED
. Si, en cambio, el receptor solo está escuchando transmitidas por tu app, usa la marcaRECEIVER_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; }
Registra el receptor llamando
registerReceiver()
:Kotlin
ContextCompat.registerReceiver(context, br, filter, receiverFlags)
Java
ContextCompat.registerReceiver(context, br, filter, receiverFlags);
Para dejar de recibir emisiones, llama a
unregisterReceiver(android.content.BroadcastReceiver)
. Asegúrate de cancelar el registro del receptor cuando ya no lo necesites o el contexto ya no es válido.Ten cuidado con dónde registrar y cancelar el registro del receptor, por Por ejemplo, si registras un receptor en
onCreate(Bundle)
usando el contexto de la actividad, debes cancelarlo enonDestroy()
para evitar que se filtre el receptor fuera del contexto de la actividad. Si te registras un receptor enonResume()
, deberías cancela el registro enonPause()
para evitar registrándolo varias veces (si no quieres recibir emisiones cuando se pausa, lo que puede reducir la sobrecarga innecesaria del sistema). Qué no debes hacer cancelar el registro enonSaveInstanceState(Bundle)
, porque no se llama si el usuario retrocede en la pila del historial.
Efectos en el estado del proceso
Si tu BroadcastReceiver
funciona o no afecta al proceso contenido, lo que puede alterar su
de matar el sistema. Un proceso en primer plano ejecuta el método onReceive()
de un receptor. El
el sistema ejecuta el proceso,
excepto bajo una presión de memoria extrema.
BroadcastReceiver se desactiva después de onReceive()
. El host del receptor
es tan importante como los componentes de su aplicación. Si ese proceso solo aloja
un receptor declarado en el manifiesto (un caso frecuente para las apps que el usuario nunca
o no haya interactuado recientemente), es posible que el sistema lo cierre después de onReceive()
para que
recursos disponibles para otros procesos más críticos.
Por lo tanto, los receptores de emisión no deben iniciar subprocesos en segundo plano de larga duración.
El sistema puede detener el proceso en cualquier momento después de onReceive()
para la recuperación.
memoria y finaliza el subproceso creado. Para mantener activo el proceso, programa una
JobService
del receptor con JobScheduler
para que el sistema sepa
que el proceso aún funciona.
En Descripción general del trabajo en segundo plano encontrarás más detalles.
Cómo enviar emisiones
Android ofrece tres maneras para que las apps envíen emisiones:
- El
sendOrderedBroadcast(Intent, String)
envía transmisiones a un receptor a la vez. A medida que se ejecuta cada receptor puede propagar un resultado al siguiente receptor, o puede anular por completo la transmisión para que no pase a otra receptores de llamadas de Google. El orden en el que se ejecutan los receptores puede controlarse con el Atributo android:priority del filtro de intents coincidente. con el la misma prioridad se ejecutará en un orden arbitrario. - El método
sendBroadcast(Intent)
envía a todos los receptores en un orden indefinido. Esto se llama Normal Transmitir. Esto es más eficiente, pero significa que los receptores no pueden leer resultados de otros receptores, propagar datos recibidos de la transmisión o anular la transmisión.
El siguiente fragmento de código demuestra cómo enviar una transmisión creando un
Intent y llamada a 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);
El mensaje de emisión está envuelto en un objeto Intent
.
La cadena de acción del intent debe proporcionar la sintaxis del nombre del paquete Java de la app y
identificar de manera exclusiva el evento de transmisión. Puedes adjuntar información adicional
al intent con putExtra(String, Bundle)
.
También puedes limitar una transmisión a un conjunto de aplicaciones de la misma organización al
llamando a setPackage(String)
en el intent.
Cómo restringir emisiones con permisos
Los permisos te permiten restringir emisiones a un conjunto de apps que tengan ciertos permisos. Puedes imponer restricciones en el remitente receptor de una transmisión.
Cómo enviar emisiones con permisos
Cuando llames a sendBroadcast(Intent, String)
o
sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
, puedes especificar un
permiso. Solo los destinatarios que solicitaron ese permiso con
la etiqueta
Kotlin
sendBroadcast(Intent(BluetoothDevice.ACTION_FOUND), Manifest.permission.BLUETOOTH_CONNECT)
Java
sendBroadcast(new Intent(BluetoothDevice.ACTION_FOUND), Manifest.permission.BLUETOOTH_CONNECT)
Para recibir la transmisión, la aplicación receptora debe solicitar el permiso como como se muestra a continuación:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
Puedes especificar un permiso del sistema existente, como
BLUETOOTH_CONNECT
o definir un permiso personalizado con el
<permission>
. Para
información sobre permisos y seguridad en general, consulta el Sistema de
Permisos.
Cómo recibir emisiones con permisos
Si especificas un parámetro de permiso cuando registras un receptor de emisión
(ya sea con registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
o en
<receiver>
en tu
manifiesto), solo podrán hacerlo las emisoras que hayan solicitado el permiso mediante
Etiqueta <uses-permission>
en su manifiesto (y posteriormente se le otorga el permiso si se
peligroso) pueden enviar un intent al receptor.
Por ejemplo, supongamos que tu app receptora tiene un receptor declarado en el manifiesto como como se muestra a continuación:
<receiver android:name=".MyBroadcastReceiver"
android:permission="android.permission.BLUETOOTH_CONNECT">
<intent-filter>
<action android:name="android.intent.action.ACTION_FOUND"/>
</intent-filter>
</receiver>
O bien la app receptora tiene un receptor registrado en el contexto, de la siguiente manera:
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 );
Luego, para poder enviar emisiones a esos receptores, la app que las envía solicita el permiso como se muestra a continuación:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
Consideraciones de seguridad y prácticas recomendadas
Estas son algunas consideraciones de seguridad y prácticas recomendadas para enviar recepción de emisiones:
Si se registraron muchas aplicaciones para recibir la misma transmisión en su puede provocar que el sistema inicie muchas apps, con lo cual un impacto significativo en el rendimiento del dispositivo y la experiencia del usuario. Para evitar es preferible usar el registro de contexto en lugar de la declaración en el manifiesto. A veces, el propio sistema Android impone el uso de registros receptores de llamadas de Google. Por ejemplo, se envía la transmisión
CONNECTIVITY_ACTION
solo a receptores registrados en el contexto.No emitas información sensible mediante un intent implícito, El cualquier app que se registre para recibir la transmisión puede leer la información. Existen tres maneras de controlar quién puede recibir tus emisiones:
- Puedes especificar un permiso cuando envías una emisión.
- En Android 4.0 y versiones posteriores, puedes especificar un
package con
setPackage(String)
cuando se envía un transmisión. El sistema restringe la transmisión al conjunto de apps que coincide con el paquete.
Cuando registras un receptor, cualquier app puede enviar al receptor de tu app. Existen varias formas de limitar el transmisiones que recibe tu app:
- Puedes especificar un permiso cuando registras un receptor de emisión.
- Para los receptores declarados en el manifiesto, puedes configurar el android:exportado atributo como "false" en el manifiesto. El receptor no recibe de fuentes externas a la app.
El espacio de nombres para las acciones de emisión es global. Asegúrate de que los nombres de las acciones y otras cadenas se escriben en un espacio de nombres propio; de lo contrario, involuntariamente, entran en conflicto con otras aplicaciones.
Debido a que el método
onReceive(Context, Intent)
de un receptor se ejecuta en el subproceso principal, debería ejecutarse y mostrarse rápidamente. Si necesitas realizar trabajos de larga duración, ten cuidado de no generar hilos o empezar servicios en segundo plano porque el sistema puede finalizar todo el proceso después Se muestraonReceive()
. Para obtener más información, consulte Efectos en el proceso Para realizar un trabajo de larga duración, recomendar:- Se llamará a
goAsync()
en tuonReceive()
del receptor y pasa elBroadcastReceiver.PendingResult
a un subproceso en segundo plano. De esta manera, la emisión se mantiene activa luego de que se muestra desdeonReceive()
. Sin embargo, incluso con este enfoque, el sistema espera que termines la transmisión muy rápido (menos de 10 segundos). Te permite mover en otro subproceso para evitar que se produzca un error en el subproceso principal. - Programa una tarea con
JobScheduler
. Para ver más información, consulta Tareas inteligentes Programación
- Se llamará a
No inicies actividades desde receptores de emisión es molesto; especialmente si hay más de un receptor. En cambio, considera mostrar una notificación