Ogni applicazione Android, indipendentemente dalla finalità che si prefigge, affida le sue funzionalità a quattro tipi di componenti. Si tratta di Activity, Service, Content Provider e BroadcastReceiver ed esistono affinchè la nostra applicazione possa integrarsi alla perfezione nell'ecosistema Android.
Prima di addentrarci nella spiegazione di ognuna di esse, è utile concentrarsi un attimo su due principi ispiratori che, tra gli altri, sono alla base della maggior parte delle scelte progettuali operate dai creatori di Android. Tenerli a mente ci permetterà di comprendere meglio ciò che del sistema verrà illustrato nei prossimi capitoli:
- la salvaguardia delle risorse: essendo progettato per sistemi embedded, storicamente dotati di poche risorse di memoria, Android ha avuto sin da subito uno spirito parsimonioso. Vedremo che, senza far perdere fluidità alla user-experience, Android è particolarmente bravo nel distruggere e ricreare parti dell'applicazione in maniera del tutto impercettibile all'utente. Chi dovrà fronteggiare questo atteggiamento sarà il programmatore, ovviamente. Per fortuna, ciò non costerà grandi fatiche ma solo particolare cura nel prendere determinati accorgimenti da applicare con la necessaria consapevolezza. Vale la pena sottolineare che quando si parla di esiguità di risorse in Android, l'obiezione mossa più comunemente ruota attorno alla recente commercializzazione di smartphone che possono contare anche su 12 GB di memoria RAM. Ciò è vero ma non bisogna dimenticare che Android si propone lo scopo di animare qualunque dispositivo in cui riesca a vivere. Il sistema vincerà quindi la sfida di sopravvivenza solo se saprà adattarsi anche a contesti che offrono condizioni molto più disagiate di quelle che può prospettare un nuovissimo device Samsung;
- sicurezza: Android è figlio di Linux, come già ricordato, quindi ha nel DNA la ricerca della stabilità. Ogni applicazione è un utente a sé stante e vive in un proprio processo in cui viene allocata una nuova istanza della virtual machine, ciò per evitare che il crash di un'applicazione propaghi instabilità alle altre app in esecuzione. Questa forma di “isolamento” viene riflessa anche sulla memoria di massa in quanto ogni applicazione ha un suo spazio in cui lavorare e custodire i propri dati. In merito, è assolutamente sconsigliata qualsiasi pratica che porti un'app ad invadere lo spazio riservato ad un'altra. Nonostante ciò le nostre applicazioni non sono costrette a vivere in assenza di comunicazione tra loro, anzi Android favorisce un dialogo “sano” tra di esse mettendo a disposizione meccanismi agevoli per la condivisione di contenuti e funzionalità tra componenti del sistema.
In questo discorso, si innesta la tematica delle permission che
qualsiasi utente Android conosce come l'insieme delle facoltà di azione che vengono concesse ad una nuova app installata. Anche il loro
regime è stato negli anni rafforzato rendendo sempre più conscio l'utilizzatore del device di cosa effettivamente un'applicazione
può fare nel sistema e del momento esatto in cui viene concessa tale possibilità.
È arrivato il momento quindi di presentare più da vicino i blocchi costitutivi di un'applicazione.
Le fondamenta di Android
Activity
Un'Activity è un'interfaccia utente. Ogni volta che si usa un'app generalmente si interagisce con una o più "pagine" mediante le quali si consultano dati o si immettono input. Ovviamente la realizzazione di Activity è il punto di partenza di ogni corso di programmazione Android visto che è il componente con cui l'utente ha il contatto più diretto.
Le Activity nel loro complesso costituiscono il flusso in cui l'utente si inoltra per sfruttare le funzionalità messe a disposizione. Questo richiede pertanto
non solo la realizzazione delle interfacce in sé stesse, ma anche una corretta progettazione della navigazione tra di esse
offrendo la possibilità di sfogliarne i contenuti e risalirli gerarchicamente in maniera coerente.
Service
Un Service svolge un ruolo, se vogliamo, opposto all'Activity (sebbene, a livello di ereditarietà di classe siano imparentati). Infatti rappresenta un lavoro – generalmente lungo e continuato - che viene svolto interamente in background senza bisogno di interazione diretta con l'utente. Ad esempio, un'app che permette di avviare un audio che non si interrompe alla chiusura della sua interfaccia con tutta probabilità basa il suo funzionamento su un Service.
I loro usi sono dei più disparati e, a seconda dei casi, l'utente potrebbe anche non notare il loro avvio ottenendone però i benefici. Da una punto di vista strutturale, i Service
sono di due tipologie: started e bounded. L'esempio della musica in background rientra nella prima casistica: un Service è started quando
un'app ha bisogno di svolgere attività in background, mirate ad uno scopo specifico, fino al loro completamento. I Service del secondo genere, i bounded,
vengono attivati solo nel caso in cui un'altra app abbia bisogno di connettersi a loro. Si tratta di un tipo di Service che permette l'interazione tra processi differenti
e risponde ad una logica simile a quella delle API nei servizi web.
Si noti inoltre che anche questo settore è stato rivoluzionato negli anni, in particolare con la nascita dei JobScheduler che permettono
lavori in background con un uso parsimonioso della batteria.
Content Provider
Un Content Provider nasce con lo scopo della condivisione di dati tra applicazioni. La sua finalità richiama quel principio di sicurezza dell'applicazione di cui si è trattato poco fa. Questi componenti permettono di condividere, nell'ambito del sistema, contenuti custoditi in un database, su file o reperibili mediante accessi in Rete. Tali contenuti potranno essere usati da altre applicazioni senza invadere lo spazio di memoria ma stabilendo quel dialogo “sano” cui si è accennato
Broadcast Receiver
Un Broadcast Receiver è un componente che reagisce ad un invio di messaggi a livello di sistema – appunto in broadcast – con cui Android notifica l'avvenimento di un determinato evento, ad esempio l'arrivo di un SMS o di una chiamata o sollecita l'esecuzione di azioni. Questi componenti come si può immaginare sono particolarmente utili per la gestione istantanea di determinate circostanze speciali.
I Broadcast Receiver non utilizzano interfaccia grafica sebbene possano inoltrare notifiche alla barra di stato per avvisare l'utente dell'avvenimento.
Inoltre la loro esecuzione dovrebbe essere istantanea delegando a Service o JobScheduler eventuali operazioni da attivare.
Intent
Molto importante ricordare che una componente può attivarne un'altra mediante apposite invocazioni di sistema. Questa intenzione viene codificata con un Intent utilizzabile come normale classe Java ma che sottintende un potentissimo strumento di comunicazione di Android. Anche degli Intent faremo uso sin dai prossimi articoli.