Creazione di servizi Android

Questa guida illustra i servizi Xamarin.Android, che sono componenti Android che consentono di lavorare senza un'interfaccia utente attiva. I servizi sono molto comunemente usati per le attività eseguite in background, ad esempio calcoli dispendiosi in termini di tempo, download di file, riproduzione di musica e così via. Illustra i diversi scenari per cui i servizi sono adatti e mostra come implementarli sia per l'esecuzione di attività in background a esecuzione prolungata sia per fornire un'interfaccia per le chiamate di procedura remota.

Panoramica di Servizi Android

Le app per dispositivi mobili non sono come le app desktop. I desktop hanno quantità copiose di risorse come lo schermo immobiliare, memoria, spazio di archiviazione e un alimentatore connesso, i dispositivi mobili non lo fanno. Questi vincoli forzano il comportamento delle app per dispositivi mobili in modo diverso. Ad esempio, lo schermo piccolo in un dispositivo mobile significa in genere che una sola app (ad esempio, l'attività) è visibile alla volta. Altre attività vengono spostate in background e inserite in uno stato sospeso in cui non possono eseguire alcun lavoro. Tuttavia, solo perché un'applicazione Android è in background non significa che è impossibile per l'app continuare a funzionare.

Le applicazioni Android sono costituite da almeno uno dei quattro componenti principali seguenti: Attività, Ricevitori broadcast, Provider di contenuti e Servizi. Le attività sono la pietra angolare di molte grandi applicazioni Android perché forniscono l'interfaccia utente che consente a un utente di interagire con l'applicazione. Tuttavia, quando si tratta di eseguire operazioni simultanee o in background, le attività non sono sempre la scelta migliore.

Il meccanismo principale per il lavoro in background in Android è il servizio . Un servizio Android è un componente progettato per eseguire alcune operazioni senza un'interfaccia utente. Un servizio può scaricare un file, riprodurre musica o applicare un filtro a un'immagine. I servizi possono essere usati anche per la comunicazione interprocesso (IPC) tra applicazioni Android. Ad esempio, un'app Android potrebbe usare il servizio lettore musicale proveniente da un'altra app o un'app potrebbe esporre i dati (ad esempio le informazioni di contatto di una persona) ad altre app tramite un servizio.

I servizi e la loro capacità di eseguire operazioni in background sono fondamentali per fornire un'interfaccia utente fluida e fluida. Tutte le applicazioni Android hanno un thread principale (noto anche come thread dell'interfaccia utente) in cui vengono eseguite le attività. Per mantenere reattivo il dispositivo, Android deve essere in grado di aggiornare l'interfaccia utente alla velocità di 60 fotogrammi al secondo. Se un'app Android esegue troppo lavoro sul thread principale, Android elimina i fotogrammi, che a sua volta fa sì che l'interfaccia utente venga visualizzata in modo insidioso (anche detta anche janky). Ciò significa che qualsiasi lavoro eseguito sul thread dell'interfaccia utente deve essere completato nell'intervallo di tempo tra due fotogrammi, circa 16 millisecondi (1 secondo ogni 60 fotogrammi).

Per risolvere questo problema, uno sviluppatore può usare thread in un'attività per eseguire alcune operazioni che bloccano l'interfaccia utente. Tuttavia, ciò potrebbe causare problemi. È molto possibile che Android elimini e ricrea le più istanze dell'attività. Tuttavia, Android non eliminerà automaticamente i thread, che potrebbero causare perdite di memoria. Un esempio principale di questo è quando il dispositivo viene ruotato : Android tenterà di distruggere l'istanza dell'attività e quindi ricreare una nuova:

When device rotates, instance 1 is destroyed and instance 2 is created

Si tratta di una potenziale perdita di memoria: il thread creato dalla prima istanza dell'attività sarà ancora in esecuzione. Se il thread ha un riferimento alla prima istanza dell'attività, ciò impedirà ad Android di eseguire il Garbage Collection dell'oggetto. Tuttavia, viene comunque creata la seconda istanza dell'attività , che a sua volta potrebbe creare un nuovo thread. La rotazione del dispositivo più volte in rapida successione può esaurire tutta la RAM e forzare Android a terminare l'intera applicazione per recuperare memoria.

Come regola generale, se il lavoro da eseguire deve avere una durata maggiore di un'attività, è necessario creare un servizio per eseguire tale lavoro. Tuttavia, se il lavoro è applicabile solo nel contesto di un'attività, la creazione di un thread per eseguire il lavoro potrebbe essere più appropriata. Ad esempio, la creazione di un'anteprima per una foto appena aggiunta a un'app della raccolta foto dovrebbe verificarsi in un servizio. Tuttavia, un thread potrebbe essere più appropriato per riprodurre una musica che deve essere ascoltata solo mentre un'attività è in primo piano.

Il lavoro in background può essere suddiviso in due ampie classificazioni:

  1. Attività a esecuzione prolungata: questo è il lavoro in corso fino a quando non viene arrestato in modo esplicito. Un esempio di attività a esecuzione prolungata è un'app che trasmette musica o che deve monitorare i dati raccolti da un sensore. Queste attività devono essere eseguite anche se l'applicazione non ha un'interfaccia utente visibile.
  2. Attività periodiche: (talvolta denominata processo) Un'attività periodica è una di durata relativamente breve (diversi secondi) e viene eseguita in base a una pianificazione (ovvero una volta al giorno per una settimana o forse una sola volta nei 60 secondi successivi). Un esempio è il download di un file da Internet o la generazione di un'anteprima per un'immagine.

Esistono quattro diversi tipi di servizi Android:

  • Servizio associato: un servizio associato è un servizio con un altro componente (in genere un'attività) associato. Un servizio associato fornisce un'interfaccia che consente al componente associato e al servizio di interagire tra loro. Una volta che non sono presenti altri client associati al servizio, Android arresterà il servizio.

  • IntentServiceIntentService: è una sottoclasse specializzata della Service classe che semplifica la creazione e l'utilizzo del servizio. Un IntentService oggetto è progettato per gestire singole chiamate autonome. A differenza di un servizio, che può gestire simultaneamente più chiamate, un è IntentService più simile a un processore della coda di lavoro: il lavoro viene accodato e un IntentService processo ogni processo uno alla volta in un singolo thread di lavoro. In genere, un oggettoIntentService non è associato a un'attività o a un frammento.

  • Servizio avviato: un servizio avviato è un servizio che è stato avviato da un altro componente Android (ad esempio un'attività) e viene eseguito continuamente in background fino a quando qualcosa non indica esplicitamente al servizio di arrestarsi. A differenza di un servizio associato, a un servizio avviato non è associato direttamente alcun client. Per questo motivo, è importante progettare i servizi avviati in modo che possano essere riavviati normalmente in base alle esigenze.

  • Servizio ibrido: un servizio ibrido è un servizio con le caratteristiche di un servizio avviato e di un servizio associato. Un servizio ibrido può essere avviato da quando un componente viene associato a esso o può essere avviato da un evento. Un componente client può essere associato o meno al servizio ibrido. Un servizio ibrido continuerà a essere in esecuzione fino a quando non viene indicato in modo esplicito di arrestare o fino a quando non sono presenti altri client associati.

Il tipo di servizio da usare dipende molto dai requisiti dell'applicazione. Come regola generale, un IntentService servizio associato o è sufficiente per la maggior parte delle attività che un'applicazione Android deve eseguire, quindi è consigliabile assegnare la preferenza a uno di questi due tipi di servizi. Un'opzione IntentService è una buona scelta per le attività "one-shot", ad esempio il download di un file, mentre un servizio associato sarebbe adatto quando sono necessarie interazioni frequenti con un'attività o un frammento.

Mentre la maggior parte dei servizi viene eseguita in background, esiste una sottocategoria speciale nota come servizio in primo piano. Si tratta di un servizio a cui viene assegnata una priorità più alta (rispetto a un servizio normale) per eseguire alcune operazioni per l'utente (ad esempio la riproduzione di musica).

È anche possibile eseguire un servizio nel proprio processo nello stesso dispositivo, a volte definito servizio remoto o come servizio out-of-process. Ciò richiede più impegno per la creazione, ma può essere utile per quando un'applicazione deve condividere funzionalità con altre applicazioni e, in alcuni casi, migliorare l'esperienza utente di un'applicazione.

Limiti di esecuzione in background in Android 8.0

A partire da Android 8.0 (livello API 26), un'applicazione Android non può più essere eseguita liberamente in background. Quando in primo piano, un'app può avviare ed eseguire servizi senza restrizioni. Quando un'applicazione si sposta in background, Android concederà all'app un certo periodo di tempo per l'avvio e l'uso dei servizi. Una volta trascorso il tempo, l'app non può più avviare alcun servizio e tutti i servizi avviati verranno terminati. A questo punto non è possibile che l'app esegua alcuna operazione. Android considera un'applicazione in primo piano se viene soddisfatta una delle condizioni seguenti:

  • È presente un'attività visibile (avviata o sospesa).
  • L'app ha avviato un servizio in primo piano.
  • Un'altra app è in primo piano e usa componenti di un'app che altrimenti si trova in background. Un esempio è se l'applicazione A, in primo piano, è associata a un servizio fornito dall'applicazione B. L'applicazione B verrà considerata in primo piano e non terminata da Android per essere in background.

Ci sono alcune situazioni in cui, anche se un'app è in background, Android riattiva l'app e riduce queste restrizioni per alcuni minuti, consentendo all'app di eseguire alcune operazioni:

  • Un messaggio cloud firebase ad alta priorità viene ricevuto dall'app.
  • L'app riceve una trasmissione.
  • L'applicazione riceve ed esegue un oggetto PendingIntent in risposta a una notifica.

Le applicazioni Xamarin.Android esistenti potrebbero dover modificare il modo in cui eseguono operazioni in background per evitare eventuali problemi che potrebbero verificarsi in Android 8.0. Ecco alcune alternative pratiche a un servizio Android:

  • Pianificare l'esecuzione in background usando l'Utilità di pianificazione processi Android o Firebase Job Dispatcher: queste due librerie forniscono un framework per le applicazioni per separare il lavoro in background in processi, un'unità di lavoro discreta. Le app possono quindi pianificare il processo con il sistema operativo insieme ad alcuni criteri relativi all'esecuzione del processo.
  • Avviare il servizio in primo piano: un servizio in primo piano è utile per quando l'app deve eseguire alcune attività in background e l'utente potrebbe dover interagire periodicamente con tale attività. Il servizio in primo piano visualizzerà una notifica permanente in modo che l'utente sappia che l'app esegue un'attività in background e fornisce anche un modo per monitorare o interagire con l'attività. Un esempio di questo sarebbe un'app podcasting che sta riproducendo un podcast all'utente o forse scaricando un episodio podcast in modo che possa essere apprezzato in seguito.
  • Usare un FCM (Firebase Cloud Message) con priorità alta: quando Android riceve un FCM con priorità alta per un'app, consentirà all'app di eseguire i servizi in background per un breve periodo di tempo. Questa è una buona alternativa alla presenza di un servizio in background che esegue il polling di un'app in background.
  • Rinviare il lavoro per quando l'app entra in primo piano : se nessuna delle soluzioni precedenti è valida, le app devono sviluppare il proprio modo per sospendere e riprendere il lavoro quando l'app diventa in primo piano.