Nella precedente puntata abbiamo presentato tutti gli strumenti per iniziare a creare applicazioni Android ed abbiamo cominciato con l’allestire l’interfaccia della prima “app”, la classica “CiaoMondo“.
Questa volta analizzeremo l’anatomia delle applicazioni Android presentando anche attività, frammenti ed intents.
Chi si fosse perso la prima puntata può consultarla facendo riferimento all’articolo Programmare Android: creare applicazioni partendo da zero con Android SDK ed Eclipse.
Per sviluppare applicazioni Android due sono i requisiti software indispensabili:
– Il pacchetto Java Development Kit (JDK), prelevabile da questa pagina (sito web di Oracle).
– L’Android SDK, il prodotto che consente di realizzare applicazioni per il sistema operativo mobile targato Google contenente il debugger, le librerie, un emulatore, il codice d’esempio e la documentazione. Il pacchetto SDK è scaricabile gratuitamente da questa pagina.
Una volta che si sarà creata la prima applicazione Android od, almeno, il suo scheletro, seguendo le indicazioni riportate nell’articolo Programmare Android: creare applicazioni partendo da zero con Android SDK ed Eclipse, è giunto il momento di esaminarne l’anatomia.
La struttura di un’applicazione Android
Facendo riferimento alla finestra Package Explorer dell’ambiente di sviluppo Eclipse, si troveranno diversi elementi:
Ci si concentri sul nome delle varie cartelle in elenco:
– src
contiene il codice sorgente (linguaggio Java) del progetto in corso di sviluppo
– gen
ospita file generati dal compilatore che fanno riferimento alle varie risorse che compongono il progetto
– Android 4.2
contiene un’unica classe che include tutte le librerie necessarie per lo sviluppo dell’applicazione Android
– Android Dependencies
mostra l’elenco delle dipendenze ossia dalla presenza di quali file JAR il progetto in corso di sviluppo a sua volta dipende
– assets
visualizza l’elenco dei componenti che sono impiegati dall’applicazione Android (file di testo, HTML, database,…)
– bin
contiene i file generati dal plugin ADT (Android Development Tools) durante il processo di creazione del file binario in formato .APK (Android Package). Il pacchetto APK contiene tutto il necessario per garantire il corretto funzionamento dell’applicazione Android.
– libs
contiene le librerie utilizzate dall’applicazione
– res
ospita tutte le risorse usate da parte dell’applicazione. Sono presenti anche diverse sottocartelle: drawable-
(seguita dalla denominazione di varie risoluzioni), layout
e – values
. Utilizzando queste cartelle si potranno supportare dispositivi con diverse risoluzioni dello schermo: si vedrà più avanti come fare.
Molto importanti sono i file .xml
contenuto nella cartella res\layout
e strings.xml
(si trova in res\values
).
Il primo, come abbiamo già avuto modo di vedere nella scorsa puntata, definisce l’interfaccia utente dell’applicazione mentre il secondo, anch’esso già citato in precedenza, consente di impostare tutti i riferimenti alle strighe di caratteri richiamate dal codice.
È bene inserire tutte le stringhe utilizzate nell’applicazione all’interno del file strings.xml
: le si richiamerà poi dal codice utilizzando l’identificativo @string
.
Nel file strings.xml
è possibile aggiungere, nel nostro caso, le seguenti due righe:
<string name="presentazione">La mia prima applicazione Android!</string> <string name="pulsante_01">Pulsante cliccabile</string>
Nel file activity_ciao_mondo.xml
si dovranno sostituire le corrispondenti stringhe di carattere con @string/presentazione
e @string/pulsante_01
.
Il file AndroidManifest.xml
consente di specificare i permessi di cui ha bisogno l’applicazione per poter funzionare e di regolare alcune funzionalità accessorie.
Dopo aver aperto il file AndroidManifest.xml
dalla finestra Package Explorer quindi cliccando sull’omonima scheda AndroidManifest.xml
, si potrà esaminarne la struttura.
Accanto all’attributo package=
si trova il nome assegnato all’applicazione. L’attributo android:versionCode
consente di impostare il numero di versione dell’applicazione cosicché il sistema operativo possa in seguito stabilire quando è necessario applicare un aggiornamento.
L’attributo android:versionName
dà modo di specificare il numero di versione che dovrà esssere visualizzato agli utenti. In questo caso, dev’essere utilizzato il formato majorversion.minorversion.subminor
per definire l’aggiornamento.
Per mezzo dell’attributo android:minSdkVersion
è invece possibile stabilire la versione minima del sistema operativo Android che deve essere necessariamente installata sul dispositivo per poter usare l’applicazione.
L’attributo icon
consente di definire l’icona associata all’applicazione (@drawable
sta a significare che l’icona è situata nella cartella drawable
) mentre le varie label
consentono di indicare il nome dell’applicazione recuperato, come si vede, dal file strings.xml
(uso dell’identificativo @string
).
Il codice che dà il via al caricamento dell’interfaccia dell’applicazione è contenuto nel file .java
(cartella src
). Nello specifico, si tratta del metodo setContentView
:
Le attività, i frammenti e gli “intents” in Android
Si chiama attività (activities), in Android, ciascuna finestra che contiene l’interfaccia utente dell’applicazione. Ogni singola applicazione Android può avere zero attività oppure utilizzarne più di una.
A partire dalla versione 3.0 di Android, il sistema operativo di Google supporta anche l’impiego dei cosiddetti frammenti (fragments): si tratta di una sorta di “miniatura” delle attività che possono essere raggruppati per formare, a loro volta, un’attività.
Gli intents, invece, possono essere considerati come una sorta di collante che permette alle varie attività di operare in modo coordinato.
Attività, temi e finestre di dialogo
Quando si sviluppa un’applicazione Android, ogni attività deve essere esplicitamente dichiarata nel file AndroidManifest.xml
.
Tre sono gli eventi che “sovrintendono” il cosiddetto “ciclo di vita” di ogni singola attività:
– onCreate()
; invocato ogniqualvolta l’attività viene creata
– onStart()
; viene richiamato non appena la finestra diventa visibile per l’utente
– onResume()
; viene invocato appena l’attività comincia ad interagire con l’utente
– onPause()
; il codice al suo interno viene eseguito quando l’attività corrente viene “posta in pausa” e richiamata una precedente attività
– onStop()
; la sua esecuzione scatta non appena l’attività non è più visibile da parte dell’utente
– onDestroy()
; richiamato immediatamente prima che l’attività venga chiusa da parte del sistema (su richiesta dell’utente, in modo manuale, oppure per risparmiare memoria)
– onRestart()
; richiamato dopo che l’attività è stata chiusa per poi essere riaperta
In Google Android, un’attività viene subito chiusa non appena si preme il pulsante “Indietro” sullo smartphone o sul tablet (quello che riporta una freccia “arrotolata” su se stessa):
Per conservare “lo stato” di una specifica attività bisognerà scrivere del codice aggiuntivo. È bene notare che l’evento onPause()
viene invocato sia che da una certa attività si passi alla schermata home di Android premendo il pulsante “Indietro“, sia che l’attività venga posta “in background” e non più visualizzata direttamente.
Come regola generale, si dovrà utilizzare l’evento onCreate()
per istanziare tutti gli oggetti che saranno poi utilizzati da parte dell’applicazione.
Il metodo onResume()
può essere impiegato per eseguire codice od avviare servizi che necessitino di essere avviati mentre l’attività è in corso di visualizzazione da parte dell’utente.
Il metodo onPause()
servirà per fermare servizi e codice che non è necessario eseguire mentre l’applicazione non è in primo piano.
Infine, onDestroy()
è utilizzabile per liberare risorse prima che l’applicazione venga chiusa.
Utilizzare stili e temi
Per impostazione predefinita, ciascuna attività occupa tutto lo schermo. Ovviamente, com’è noto se si lavora spesso con un dispositivo Android, è cosa comune imbattersi in finestra a comparsa e finestre di dialogo che si sovrappongono alla finestra in primo piano.
Si provi ad esempio a sostituire la riga android:theme="@style/AppTheme"
contenuta nel file AndroidManifest.xml
con quanto segue:
Riavviando l’applicazione “CiaoMondo” (tasto F11), questa assumerà le sembianze di una finestra di dialogo:
Si ripristini quindi la riga android:theme="@style/AppTheme"
nel file AndroidManifest.xml
.
A questo punto, proviamo ad invocare la comparsa di una finestra di dialogo dal pulsante che, nella scorsa puntata, abbiamo inserito nella nostra applicazione di prova.
Nel file activity_ciao_mondo.xml
, in corrispondenza del pulsante (“button”) si aggiunga:
Adesso, ci si porti all’interno del file Java (cartella src
) e si sostituisca il codice già presente con quello che segue:
package com.ciaomondo; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.widget.Toast; public class CiaoMondoActivity extends Activity { CharSequence[] items = { "Mela", "Pera", "Banana" }; boolean[] itemsChecked = new boolean [items.length]; public void onClick(View v) { showDialog(0); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ciao_mondo); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_ciao_mondo, menu); return true; } @Override protected Dialog onCreateDialog(int id) { switch (id) { case 0: AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("Finestra di dialogo di prova..."); builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { Toast.makeText(getBaseContext(), "Cliccato OK!", Toast.LENGTH_SHORT).show(); } } ); builder.setNegativeButton("Annulla", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { Toast.makeText(getBaseContext(), "Cliccato annulla!", Toast.LENGTH_SHORT).show(); } } ); builder.setMultiChoiceItems(items, itemsChecked, new DialogInterface.OnMultiChoiceClickListener() { public void onClick(DialogInterface dialog, int which, boolean isChecked) { Toast.makeText(getBaseContext(), items[which] + (isChecked ? " selezionato":" deselezionato"), Toast.LENGTH_SHORT).show(); } } ); return builder.create(); } return null; } }
Avviando l’applicazione dall’emulatore (tasto F11), quindi facendo clic sul “Pulsante cliccabile“, apparirà la finestra di dialogo definita mediante il codice poco fa incollato:
Spuntando le varie caselle e cliccando sui pulsanti OK e Annulla, l’applicazione risponderà indicando l’operazione appena compiuta.
Nella prossima puntata analizzeremo da vicino il funzionamento del codice Java appena utilizzato.