I servizi in Android

Un servizio è un task che gira in background per eseguire operazioni senza una interfaccia utente e sono utilizzati per eseguire operazioni di lunga durata e con un rilevante impegno di risorse evitando rallentamenti nell’utilizzo del dispositivo.
I servizi possono appartenere a una o entrambe le seguenti categorie:

  • started: il servizio è lanciato usando il metodo startService()
  • bound: il servizio è lanciato usando il metodo bindService() e i componenti dell’applicazione che ha lanciato il servizio possono comunicare con il servizio stesso


Riporto qui una semplice app per confrontare questi due tipi di servizio:

  1. crea un progetto Android senza Activity iniziale
  2. modifica il file AndroidManifest.xml

    nota la presenza delle due righe con il tag service, necessarie per abilitare i servizi ad essere eseguiti e, per il servizio .MyStartedService, è stata impostata l’attributo android:process=”:started” per specificare un processo associato al servizio, questo ti permetterà più avanti in fase di test di fermare il servizio senza chiudere anche l’activity principale
  3. modifica i file nella cartella res/values/, nulla di importante qui
    • dimens.xml
    • strings.xml
    • styles.xml
  4. crea il file res/layout/activity_main.xml

    questa risorsa definisce un layout con i seguenti controlli:

    • Started service:
      • opzione onDestroy: se spuntata l’istruzione stopSelf() è eseguita e quindi anche il metodo onDestroy della classe MyStartedService
      • opzioni START_STICKY e START_NOT_STICK: per impostare il valore restituito dal metodo onStartCommand della classe MyStartedService
      • un pulsante per lanciare il servizio “started”
    • Bound service:
      • un pulsante per lanciare il servizio “bound”
      • una casella di testo per mostrare l’output del servizio “bound”
  5. crea il file eu/lucazanini/service/MainActivity.java

    questa è l’attività principale, in particolare nota:

    • l’evento onClick per gestire i pulsanti, btn1 per il servizio “started” e btn2 per il servizio “bound”
    • il codice relativo alle classi MyHandler, ServiceConnection e separateThread è necessario solo per il servizio “bound”
  6. crea il file eu/lucazanini/service/MyStartedService.java

    questa classe è il servizio di tipo “started” ed è chiamato dall’attività principale utilizzando il metodo startService(); estendendo la classe Service tu devi implementare il metodo onBind ma nel caso di servizio “started” è sufficiente l’istruzione “return null;” in quanto questo metodo di fatto non è mai chiamato; il lavoro svolto dal servizio è nel metodo onStartCommand(), istruzione “Utils.test(TAG);”
  7. crea il file eu/lucazanini/service/MyBoundService.java

    questa classe è il servizio di tipo “Bound” ed è chiamato dall’attività principale utilizzando l’istruzione bindService nel metodo doBindService(); il metodo onBind è stato sovrascritto per restituire l’oggetto mBinder della classe interna LocalBinder che estende Binder
  8. crea il file eu/lucazanini/service/Utils.java

    questa è una classe con metodi static che fanno il lavoro dei servizi

service

Ora possiamo testare l’app, cominciando con il servzio Started:

  1. lancia l’app
  2. lasciando i valori di default lancia il servizio “started” con il primo pulsante “Launch”
  3. osserva nella vista LogCat l’output che mostra il tempo per 10 secondi e la chiamata a onDestroy
    il servizio è lanciato con l’istruzione startService() nell’Activity principale, l’argomento in startService è un Intent per la classe MyStartedService che estende la classe Service, il lavoro svolto dal servizio è contenuto nel metodo onStartCommand()
  4. deseleziona onDestroy e rilancia il servizio “started”, la chiamata a onDestroy non avviene, questo significa che, anche se il servizio ha completato la visualizzazione del tempo per 10 secondi, il servizio non è stato distrutto
  5. ferma il servizio, questo può essere fatto in due modi:
    • da shell: con il comando “adb shell kill [PID]” dove [PID] è il PID legato al servizio e che puoi leggere nella view LogCatin Eclipse
    • dalla view Devices in Eclipse: selezionando il processo eu.lucazanini.service:started e fermadolo con l’icona “Stop Process”
  6. attendi qualche secondo e verifica che il servizio riparte
  7. seleziona START_NOT_STICKY e rilancia il servizio
  8. ferma il servizio e verifica che il servizio non riparte

Questo test dovrebbe rendere evidente la differenza fra START_STICKY e START_NOT_STICKY nel caso in cui il servizio è fermato:

  • START_STICKY: il servizio riparte se è fermato prima della chiamata a onDestroy
  • START_NOT_STICKY: il servizio non riparte se è fermato prima della chiamata a onDestroy ma può essere fatto ripartire con l’istruzione startService()

Per ulteriori informazioni sulle differenze fra i due parametri puoi leggere Service API changes starting with Android 2.0.

Ora testiamo l’app per il servizio “bound”:

  1. lancia l’app
  2. premi il secondo pulsante per lanciare il servizio “bound”
  3. osserva l’output nella casella di testo; la casella di testo è aggiornata ogni secondo per 10 secondi con l’ora corrente e senza bloccare il dispositivo

Puoi scaricare il progetto qui.

Referenze:
Android Developers: Service
Android Developers: Services
Android Developers: Bound Services

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.