Ricevitori broadcast in Xamarin.Android

In questa sezione viene illustrato come usare un ricevitore di trasmissione.

Panoramica del ricevitore di trasmissione

Un ricevitore di trasmissione è un componente Android che consente a un'applicazione di rispondere ai messaggi (android Intent) trasmessi dal sistema operativo Android o da un'applicazione. Le trasmissioni seguono un modello di pubblicazione-sottoscrizione : un evento fa sì che una trasmissione venga pubblicata e ricevuta da tali componenti interessati all'evento.

Android identifica due tipi di trasmissioni:

  • Broadcast esplicito: questi tipi di trasmissioni sono destinati a un'applicazione specifica. L'uso più comune di una trasmissione esplicita consiste nell'avviare un'attività. Esempio di trasmissione esplicita quando un'app deve comporre un numero di telefono; invierà una finalità destinata all'app Telefono in Android e passerà il numero di telefono da comporre. Android instrada quindi la finalità all'app Telefono.
  • Trasmissione implicita: queste trasmissioni vengono inviate a tutte le app nel dispositivo. Un esempio di trasmissione implicita è la ACTION_POWER_CONNECTED finalità. Questa finalità viene pubblicata ogni volta che Android rileva che la batteria nel dispositivo viene ricaricata. Android instrada questa finalità a tutte le app registrate per questo evento.

Il ricevitore di trasmissione è una sottoclasse del BroadcastReceiver tipo e deve eseguire l'override del OnReceive metodo . Android verrà eseguito OnReceive sul thread principale, quindi questo metodo deve essere progettato per l'esecuzione rapida. Prestare attenzione quando si generano thread in OnReceive perché Android può terminare il processo al termine del metodo. Se un ricevitore di trasmissione deve eseguire un lavoro a esecuzione prolungata, è consigliabile pianificare un processo usando JobScheduler o Firebase Job Dispatcher. La pianificazione del lavoro con un processo verrà illustrata in una guida separata.

Un filtro finalità viene usato per registrare un ricevitore di trasmissione in modo che Android possa instradare correttamente i messaggi. Il filtro finalità può essere specificato in fase di esecuzione (a volte definito ricevitore registrato dal contesto o come registrazione dinamica) oppure può essere definito in modo statico nel manifesto Android (un ricevitore registrato dal manifesto). Xamarin.Android fornisce un attributo C#, IntentFilterAttribute, che registrerà in modo statico il filtro delle finalità ( questo verrà illustrato in modo più dettagliato più avanti in questa guida). A partire da Android 8.0, non è possibile che un'applicazione registri in modo statico per una trasmissione implicita.

La differenza principale tra il ricevitore registrato dal manifesto e il ricevitore registrato dal contesto è che un ricevitore registrato dal contesto risponderà solo alle trasmissioni mentre un'applicazione è in esecuzione, mentre un ricevitore registrato dal manifesto può rispondere alle trasmissioni anche se l'app potrebbe non essere in esecuzione.

Esistono due set di API per la gestione di un ricevitore di trasmissione e l'invio di trasmissioni:

  1. Context – La Android.Content.Context classe può essere usata per registrare un ricevitore di trasmissione che risponderà agli eventi a livello di sistema. Viene Context usato anche per pubblicare trasmissioni a livello di sistema.
  2. LocalBroadcastManager: si tratta di un'API disponibile tramite il pacchetto NuGet della libreria di supporto Xamarin v4. Questa classe viene usata per mantenere isolate le trasmissioni e i ricevitori di trasmissione nel contesto dell'applicazione che li usa. Questa classe può essere utile per impedire ad altre applicazioni di rispondere alle trasmissioni solo dell'applicazione o all'invio di messaggi a ricevitori privati.

Un ricevitore di trasmissione potrebbe non visualizzare i dialoghi ed è fortemente sconsigliato avviare un'attività dall'interno di un ricevitore di trasmissione. Se un ricevitore di trasmissione deve notificare all'utente, deve pubblicare una notifica.

Non è possibile associare o avviare un servizio dall'interno di un ricevitore di trasmissione.

Questa guida illustra come creare un ricevitore di trasmissione e come registrarlo in modo che possa ricevere trasmissioni.

Creazione di un ricevitore di trasmissione

Per creare un ricevitore di trasmissione in Xamarin.Android, un'applicazione deve sottoclassare la BroadcastReceiver classe , adornarla con e eseguire l'override BroadcastReceiverAttributedel OnReceive metodo :

[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");
    }
}

Quando Xamarin.Android compila la classe, aggiornerà anche AndroidManifest con i metadati necessari per registrare il ricevitore. Per un ricevitore di trasmissione registrato in modo statico, è Enabled necessario impostare correttamente su true, altrimenti Android non sarà in grado di creare un'istanza del ricevitore.

La Exported proprietà controlla se il ricevitore di trasmissione può ricevere messaggi dall'esterno dell'applicazione. Se la proprietà non è impostata in modo esplicito, il valore predefinito della proprietà viene determinato da Android in base a se sono presenti filtri finalità associati al ricevitore di trasmissione. Se è presente almeno un filtro finalità per il ricevitore di trasmissione, Android presuppone che la Exported proprietà sia true. Se al ricevitore di trasmissione non sono associati filtri finalità, Android presuppone che il valore sia false.

Il OnReceive metodo riceve un riferimento all'oggetto Intent inviato al ricevitore di trasmissione. Ciò consente al mittente della finalità di passare valori al ricevitore di trasmissione.

Registrazione statica di un ricevitore di trasmissione con un filtro finalità

Quando un oggetto BroadcastReceiver viene decorato con IntentFilterAttribute, Xamarin.Android aggiungerà l'elemento necessario <intent-filter> al manifesto Android in fase di compilazione. Il frammento di codice seguente è un esempio di ricevitore di trasmissione che verrà eseguito al termine dell'avvio di un dispositivo (se all'utente sono state concesse le autorizzazioni Android appropriate):

[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

In Android 8.0 (API 26 e versioni successive), Google ha posto limitazioni sulle operazioni che le app possono eseguire mentre gli utenti non interagiscono direttamente con loro. Queste limitazioni influiscono sui servizi in background e sui ricevitori di trasmissione implicita, Android.Content.Intent.ActionBootCompletedad esempio . A causa di queste limitazioni, potresti avere difficoltà a registrare un Boot Completed ricevitore di trasmissione in versioni più recenti di Android. In questo caso, si noti che queste restrizioni non si applicano ai servizi in primo piano, che possono essere chiamati dal ricevitore di trasmissione.

È anche possibile creare un filtro finalità che risponderà alle finalità personalizzate. Si consideri l'esempio seguente:

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "com.xamarin.example.TEST" })]
public class MySampleBroadcastReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        // Do stuff here
    }
}

Le app destinate ad Android 8.0 (livello API 26) o versioni successive potrebbero non eseguire la registrazione statica per una trasmissione implicita. Le app possono comunque eseguire la registrazione statica per una trasmissione esplicita. Esiste un piccolo elenco di trasmissioni implicite esentate da questa restrizione. Queste eccezioni sono descritte nella guida alle eccezioni di trasmissione implicita nella documentazione di Android. Le app interessate alle trasmissioni implicite devono farlo in modo dinamico usando il RegisterReceiver metodo . Questa operazione è descritta di seguito.

Registrazione del contesto di un ricevitore di trasmissione

La registrazione del contesto (nota anche come registrazione dinamica) di un ricevitore viene eseguita richiamando il RegisterReceiver metodo e il ricevitore di trasmissione deve essere annullata la registrazione con una chiamata al UnregisterReceiver metodo . Per evitare perdite di risorse, è importante annullare la registrazione del ricevitore quando non è più rilevante per il contesto (l'attività o il servizio). Ad esempio, un servizio può trasmettere una finalità per informare un'attività che gli aggiornamenti sono disponibili per essere visualizzati all'utente. All'avvio dell'attività, verrà registrata per tali finalità. Quando l'attività viene spostata in background e non è più visibile all'utente, deve annullare la registrazione del ricevitore perché l'interfaccia utente per la visualizzazione degli aggiornamenti non è più visibile. Il frammento di codice seguente è un esempio di come registrare e annullare la registrazione di un ricevitore di trasmissione nel contesto di un'attività:

[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();
    }
}

Nell'esempio precedente, quando l'attività entra in primo piano, registra un ricevitore di trasmissione che ascolterà una finalità personalizzata usando il metodo del OnResume ciclo di vita. Quando l'attività si sposta in background, il metodo annulla la OnPause() registrazione del ricevitore.

Pubblicazione di una trasmissione

Una trasmissione può essere pubblicata in tutte le app installate nel dispositivo creando un oggetto Intent e inviandolo con il SendBroadcast metodo o SendOrderedBroadcast .

  1. Metodi Context.SendBroadcast : esistono diverse implementazioni di questo metodo. Questi metodi trasmetteranno la finalità all'intero sistema. Ricevitori di trasmissione che riceveranno la finalità in un ordine indeterminato. Ciò offre una grande flessibilità, ma significa che è possibile che altre applicazioni registrino e ricevano la finalità. Ciò può comportare un potenziale rischio per la sicurezza. Le applicazioni potrebbero dover implementare una sicurezza aggiuntiva per impedire l'accesso non autorizzato. Una possibile soluzione consiste nell'usare che LocalBroadcastManager invierà solo i messaggi all'interno dello spazio privato dell'app. Questo frammento di codice è un esempio di come inviare una finalità usando uno dei SendBroadcast metodi seguenti:

    Intent message = new Intent("com.xamarin.example.TEST");
    // If desired, pass some values to the broadcast receiver.
    message.PutExtra("key", "value");
    SendBroadcast(message);
    

    Questo frammento di codice è un altro esempio di invio di una trasmissione usando il Intent.SetAction metodo per identificare l'azione:

    Intent intent = new Intent();
    intent.SetAction("com.xamarin.example.TEST");
    intent.PutExtra("key", "value");
    SendBroadcast(intent);
    
  2. Context.SendOrderedBroadcast : questo metodo è molto simile a Context.SendBroadcast, con la differenza che la finalità verrà pubblicata una alla volta nei ricevitori, nell'ordine in cui i ricevitori sono stati registrati.

LocalBroadcastManager

La libreria di supporto di Xamarin v4 fornisce una classe helper denominata LocalBroadcastManager. LocalBroadcastManager è destinato alle app che non vogliono inviare o ricevere trasmissioni da altre app nel dispositivo. Pubblicherà LocalBroadcastManager solo i messaggi all'interno del contesto dell'applicazione e solo per i ricevitori di trasmissione registrati con .LocalBroadcastManager Questo frammento di codice è un esempio di registrazione di un ricevitore di trasmissione con LocalBroadcastManager:

Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this). RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));

Altre app nel dispositivo non possono ricevere i messaggi pubblicati con .LocalBroadcastManager Questo frammento di codice illustra come inviare una finalità usando 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);