Receptores de difusión en Xamarin.Android
En esta sección se describe cómo usar un receptor de difusión.
Información general sobre el receptor de difusión
Un receptor de difusión es un componente de Android que permite a una aplicación responder a mensajes (android) que son difundidos por el sistema operativo Android o por una aplicación. Las difusión siguen un modelo de publicación y suscripción: un evento hace que los componentes interesados en el evento publiquen y reciban una difusión.
Android identifica dos tipos de difusión:
- Difusión explícita: estos tipos de difusión tienen como destino una aplicación específica. El uso más común de una difusión explícita es iniciar una actividad. Un ejemplo de una difusión explícita cuando una aplicación necesita marcar un número de teléfono; enviará una intención dirigida a la aplicación Teléfono en Android y pasará el número de teléfono que se va a marcar. A continuación, Android enruta la intención a Teléfono aplicación.
- Difusión implícita: estas difusiones se envían a todas las aplicaciones del dispositivo. Un ejemplo de difusión implícita es la
ACTION_POWER_CONNECTEDintención. Esta intención se publica cada vez que Android detecta que la batería del dispositivo se está cargando. Android enruta esta intención a todas las aplicaciones que se han registrado para este evento.
El receptor de difusión es una subclase del BroadcastReceiver tipo y debe invalidar el método OnReceive . Android se ejecutará en el subproceso principal, por lo OnReceive que este método debe diseñarse para ejecutarse rápidamente. Se debe tener cuidado al generar subprocesos en OnReceive porque Android puede finalizar el proceso cuando el método finaliza. Si un receptor de difusión debe realizar un trabajo de larga duración, se recomienda programar un trabajo mediante o firebase Job Dispatcher. La programación del trabajo con un trabajo se analizará en una guía independiente.
Un filtro de intención se usa para registrar un receptor de difusión para que Android pueda enrutar correctamente los mensajes. El filtro de intención se puede especificar en tiempo de ejecución (a veces se conoce como receptor registrado en contexto o como registro dinámico)o se puede definir estáticamente en el manifiesto de Android (un receptor registrado en el manifiesto). Xamarin.Android proporciona un atributo de C#, , que registrará estáticamente el filtro de intención (esto se analizará con más detalle más adelante IntentFilterAttribute en esta guía). A partir de Android 8.0, no es posible que una aplicación se registre estáticamente para una difusión implícita.
La diferencia principal entre el receptor registrado en el manifiesto y el receptor registrado en el contexto es que un receptor registrado en contexto solo responderá a las difusiones mientras se ejecuta una aplicación, mientras que un receptor registrado en el manifiesto puede responder a las difusiones aunque la aplicación no se esté ejecutando.
Hay dos conjuntos de API para administrar un receptor de difusión y enviar difusión:
Context: laAndroid.Content.Contextclase se puede usar para registrar un receptor de difusión que responderá a eventos de todo el sistema. tambiénContextse usa para publicar difusión en todo el sistema.LocalBroadcastManager: se trata de una API que está disponible a través de la biblioteca de compatibilidad deLocalBroadcastManager. Esta clase se usa para mantener las difusión y los receptores de difusión aislados en el contexto de la aplicación que los usa. Esta clase puede ser útil para evitar que otras aplicaciones respondan a difusiones solo de aplicación o envíen mensajes a receptores privados.
Es posible que un receptor de difusión no muestre diálogos y se desaconseja iniciar una actividad desde dentro de un receptor de difusión. Si un receptor de difusión debe notificar al usuario, debe publicar una notificación.
No es posible enlazar o iniciar un servicio desde dentro de un receptor de difusión.
En esta guía se explica cómo crear un receptor de difusión y cómo registrarlo para que pueda recibir difusión.
Creación de un receptor de difusión
Para crear un receptor de difusión en Xamarin.Android, una aplicación debe crear subclases de la clase , adornar con BroadcastReceiver e invalidar el método BroadcastReceiverAttributeOnReceive :
[BroadcastReceiver(Enabled = true, Exported = false)]
public class SampleReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Do stuff here.
String value = intent.GetStringExtra("key");
}
}
Cuando Xamarin.Android compila la clase , también actualizará AndroidManifest con los metadatos necesarios para registrar el receptor. En el caso de un receptor de difusión registrado estáticamente, debe establecerse correctamente en ; de lo contrario, Android no podrá crear una Enabledtrue instancia del receptor.
La Exported propiedad controla si el receptor de difusión puede recibir mensajes desde fuera de la aplicación. Si la propiedad no se establece explícitamente, Android determina el valor predeterminado de la propiedad en función de si hay algún filtro de intención asociado al receptor de difusión. Si hay al menos un filtro de intención para el receptor de difusión, Android asumirá que la Exported propiedad es true . Si no hay ningún filtro de intención asociado al receptor de difusión, Android asumirá que el valor es false .
El OnReceive método recibe una referencia a que se envió al receptor de Intent difusión. Esto permite que el remitente de la intención pase valores al receptor de difusión.
Registro estático de un receptor de difusión con un filtro de intención
Cuando se BroadcastReceiver decora con , Xamarin.Android agregará el elemento necesario al IntentFilterAttribute manifiesto de Android en tiempo de <intent-filter> compilación. El fragmento de código siguiente es un ejemplo de un receptor de difusión que se ejecutará cuando un dispositivo haya terminado de arrancar (si el usuario concedió los permisos adecuados de Android):
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
public class MyBootReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Work that should be done when the device boots.
}
}
Nota:
En Android 8.0 (API 26 y versiones posteriores), Google colocó limitaciones en lo que las aplicaciones pueden hacer mientras los usuarios no interactúan directamente con ellas. Estas limitaciones afectan a los servicios en segundo plano y a los receptores de difusión implícitos, como Android.Content.Intent.ActionBootCompleted . Debido a estas limitaciones, es posible que tenga dificultades para registrar un receptor Boot Completed de difusión en versiones más recientes de Android. Si este es el caso, tenga en cuenta que estas restricciones no se aplican a los servicios en primer plano, a los que se puede llamar desde el receptor de difusión.
También es posible crear un filtro de intención que responda a intenciones personalizadas. Considere el ejemplo siguiente:
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "com.xamarin.example.TEST" })]
public class MySampleBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Do stuff here
}
}
Es posible que las aplicaciones destinadas a Android 8.0 (nivel de API 26) o superior no se registren estáticamente para una difusión implícita. Las aplicaciones todavía pueden registrarse estáticamente para una difusión explícita. Hay una pequeña lista de difusiones implícitas que están exentas de esta restricción. Estas excepciones se describen en la guía excepciones de difusión implícitas de la documentación de Android. Las aplicaciones que están interesadas en difusión implícita deben hacerlo dinámicamente mediante el RegisterReceiver método . Esto se describe a continuación.
Context-Registering receptor de difusión
El registro de contexto (también denominado registro dinámico) de un receptor se realiza invocando el método y el receptor de difusión debe anularse del registro con una llamada RegisterReceiver al UnregisterReceiver método . Para evitar la pérdida de recursos, es importante anular el registro del receptor cuando ya no sea relevante para el contexto (la actividad o el servicio). Por ejemplo, un servicio puede difundir una intención para informar a una actividad de que las actualizaciones están disponibles para mostrarse al usuario. Cuando se inicia la actividad, se registraría para esas intenciones. Cuando la actividad se mueve a segundo plano y ya no es visible para el usuario, debe anular el registro del receptor porque la interfaz de usuario para mostrar las actualizaciones ya no está visible. El siguiente fragmento de código es un ejemplo de cómo registrar y anular el registro de un receptor de difusión en el contexto de una actividad:
[Activity(Label = "MainActivity", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity: Activity
{
MySampleBroadcastReceiver receiver;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
receiver = new MySampleBroadcastReceiver();
// Code omitted for clarity
}
protected override void OnResume()
{
base.OnResume();
RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));
// Code omitted for clarity
}
protected override void OnPause()
{
UnregisterReceiver(receiver);
// Code omitted for clarity
base.OnPause();
}
}
En el ejemplo anterior, cuando la actividad entra en primer plano, registrará un receptor de difusión que escuchará una intención personalizada mediante el método de ciclo OnResume de vida. A medida que la actividad se mueve a segundo plano, OnPause() el método anulará el registro del receptor.
Publicación de una difusión
Se puede publicar una difusión en todas las aplicaciones instaladas en el dispositivo creando un objeto Intent y distribuyendolo con SendBroadcast el método SendOrderedBroadcast o .
Métodos Context.SendBroadcast: hay varias implementaciones de este método. Estos métodos difundirán la intención a todo el sistema. Receptores de difusión que recibirán la intención en un orden indeterminado. Esto proporciona una gran flexibilidad, pero significa que es posible que otras aplicaciones se registren y reciban la intención. Esto puede suponer un riesgo de seguridad potencial. Es posible que las aplicaciones necesiten implementar seguridad adicional para evitar el acceso no autorizado. Una posible solución es usar ,
LocalBroadcastManagerque solo enviará mensajes dentro del espacio privado de la aplicación. Este fragmento de código es un ejemplo de cómo enviar una intención mediante uno de losSendBroadcastmétodos :Intent message = new Intent("com.xamarin.example.TEST"); // If desired, pass some values to the broadcast receiver. message.PutExtra("key", "value"); SendBroadcast(message);Este fragmento de código es otro ejemplo de envío de una difusión mediante
Intent.SetActionel método para identificar la acción:Intent intent = new Intent(); intent.SetAction("com.xamarin.example.TEST"); intent.PutExtra("key", "value"); SendBroadcast(intent);Context.SendOrderedBroadcast: este método es muy similar a , con la diferencia de que la intención se publicará de uno en uno para los receptores, en el orden en que se registraron los receptores.
LocalBroadcastManager
La biblioteca de compatibilidad de Xamarin v4 proporciona una clase auxiliar denominada . está destinado a aplicaciones que no desean enviar o recibir LocalBroadcastManager difusión de otras aplicaciones en el dispositivo. solo publicará mensajes en el contexto de la aplicación y solo en los receptores de difusión LocalBroadcastManager registrados con LocalBroadcastManager . Este fragmento de código es un ejemplo de registro de un receptor de difusión con LocalBroadcastManager :
Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this). RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));
Otras aplicaciones del dispositivo no pueden recibir los mensajes publicados con LocalBroadcastManager . Este fragmento de código muestra cómo enviar una intención mediante LocalBroadcastManager :
Intent message = new Intent("com.xamarin.example.TEST");
// If desired, pass some values to the broadcast receiver.
message.PutExtra("key", "value");
Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this).SendBroadcast(message);