Creare applicazioni Android: anatomia di una app, le attività, creazione di finestre di dialogo

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".
Creare applicazioni Android: anatomia di una app, le attività, creazione di finestre di dialogo

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.

Creare applicazioni Android: i requisiti e la prima app

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.

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:

android:theme="@android:style/Theme.Dialog"

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:

android:onClick="onClick"

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.

Ti consigliamo anche

Link copiato negli appunti