Android
Porfirio Tramontana - Android
1
Letture consigliate • Android Developer, sito web di riferimento dei realizzatori di Android – http://developer.android.com/index.html
• Massimo Carli, Android 4, guida per lo sviluppatore, Apogeo – Disponibili, dagli stessi autore ed editore, anche altri libri relativi alle versioni precedenti di Android
Porfirio Tramontana - Android
2
Ulteriore elenco di libri su Android • • • • • • • • • • • • • • • • • • • • • •
Mark Murphy, The Busy Coder's Guide to Advanced Android Development, http://commonsware.com/Android/Android-1_0-CC.pdf MCGraw-Hill Osborne Android, A Programmer's Guide (2008) Apress Beginning Android (2009) Apress Pro Android (2009) Apress Pro Android Games (2009) Apress Pro Android Media, Developing Graphics Music Video and Rich Media Apps for Smartphones and Tablets (2009) Manning Unlocking Android, A Developer's Guide (2009) Pragmatic Bookshelf Publishing Hello, Android 2nd (2009) Wrox Press Professional Android Application Development (2009) Apress Android for Work, Productivity for Professionals (2010) Apress Beginning Android 2 (2010) Apress Multimobile Development, Building Applications for the iPhone and Android Platforms (2010) Apress Pro Android 2 (2010) OReilly Best Android Apps, The Guide for Discriminating Downloaders (2010) OReilly Building Android Apps with HTML CSS and JavaScript (2010) QUE Web Geek's Guide to the Android-Enabled Phone (2010) SAMS Teach Yourself Android Application Development in 24 Hours (2010) Wrox Press Professional Android 2 Application Development (2010) Addison-Wesley Android Wireless Application Development 2nd (2011) Addison-Wesley The Android Developer's Cookbook, Building Applications with the Android SDK (2011) Manning Android in Action 2nd (2011) Wrox Press Professional Flash Mobile Development, Creating Android and iPhone Applications (2011)
Porfirio Tramontana - Android
3
Cos’è Android? • Android è un insieme di componenti software, comprendente un sistema operativo, un middleware e un insieme di applicazioni basilari
– Android è usualmente utilizzato in smartphones e tablets ma potrebbe essere esteso a supportare qualsiasi dispositivo, ipoteticamente anche un PC
Porfirio Tramontana - Android
5
Breve storia di Android • 2003: Andy Rubin fonda la Android Inc. • 2005: Android viene acquisito da Google • 2007: Viene fondata la Open Handset Alliance, consorzio comprendente 84 membri tra cui produttori di hardware, di software e compagnie di telecomunicazione (oltre a Google stessa), con lo scopo di realizzare congiuntamente tutto il necessario per la diffusione del sistema. • 2007: viene rilasciato con licenza Apache l’Android Open Source Project http://source.android.com/
Porfirio Tramontana - Android
6
Breve storia di Android • 2007: Android Beta • 2008: Android 1.0 (eseguibile su un unico dispositivo, HTC G1) • 2009: Android 1.5 Cupcake (prima vera versione supportata da dispositivi ad ampia diffusione commerciale • 2009: Android 1.6 Donut • 2009: Android 2.0 Éclair • 2010: Android 2.2 Froyo • 2010: Android 2.3 Gingerbread • 2011: Android 3 Honeycomb • 2011: Android 4 Ice Cream Sandwich http://blog.o2.co.uk/home/2011/05/android-versions-whats-the-difference.html Porfirio Tramontana - Android
7
Breve storia di Android 2012: Android 4.1/4.2/4.3 Jelly Bean 2013/14: Android 4.4 Kit Kat 2014: Android 5 Lollipop
http://www.cnet.com/news/history-of-android/ Porfirio Tramontana - Android
8
Porfirio Tramontana - Android
9
Android Architecture
Porfirio Tramontana - Android
10
Sistema operativo e librerie •
Il sistema operativo sottostante è una distribuzione, opportunamente ridotta di Linux (kernel 2.6)
•
Un certo numero di librerie di base sono state inserite, per supportare alcune features fondamentali: Handset layouts Storage Connectivity Messaging Multiple language support Web browser Java support Media support Streaming media support
Porfirio Tramontana - Android
Additional hardware support Multi-touch Bluetooth Video calling Multitasking Voice based features Tethering Screen capture
11
Dalvik Virtual Machine •
All’interno di ogni dispositivo Android è presenta una virtual machine, denominata Dalvik – Dalvik è una macchina virtuale open source in grado di eseguire bytecode, in maniera simile alla Java Virtual Machine della Sun
Dalvik
• Il bytecode è denominato dex (Dalvik executable)
•
•
– Dalvik è ottimizzata per macchine dalla ridotta memoria – Gestisce i thread, con alcune limitazioni – Non gestisce le eccezioni Ogni applicazione su Android è vista come un diverso user, con un proprio processo, una propria zona dati e una propria istanza di Dalvik virtual machine.
Il nome Dalvik deriva dal villaggio di pescatori Dalvíkurbyggð di cui la famiglia di Bornstein, dipendente Google e autore della VM è originaria.
In futuro, Dalvik sarà integrata/sostituita da ART
Porfirio Tramontana - Android
12
Java Framework • E’ possibile scrivere applicazioni in Java e poi compilarle nel formato dex eseguibile dalla Dalvik Virtual Machine • La versione di riferimento è J2SE, non J2ME
• Java non è l’unico possibile linguaggio di programmazione utilizzabile sotto Android, ma è largamente il più comune, nonché quello con maggior supporto software e consigliato dagli stessi sviluppatori di Android – E’ possibile realizzare, ad esempio, applicazioni e componenti in C/C++ con il supporto dell’Android Native Development Kit (NDK) • http://developer.android.com/sdk/ndk/overview.html Porfirio Tramontana - Android
13
Android SDK • Android Standard Development Kit è il contenitore di tutti gli strumenti fondamentali per lo sviluppo di applicazioni Android in Java • Scaricabile da: – http://developer.android.com/sdk/installing.html • Disponibile per tutti i sistemi operativi più diffusi • Non ha necessità di installazione • Comprende: – Strumenti a supporto dello sviluppo – Emulatore – Documentazione – Esempi – Strumenti di utilità
Porfirio Tramontana - Android
14
Installazione dei componenti aggiuntivi • Tramite SDK Manager è possibile scaricare tutti i componenti aggiuntivi necessari all’esecuzione delle applicazioni in tutte le versioni di Android • Le applicazioni Android possono essere eseguite su device reali o emulati Porfirio Tramontana - Android
15
Android Virtual Device • E’ possibile generare macchine virtuali Android riproducenti le caratteristiche di una macchina reale tramite AVD Manager
Porfirio Tramontana - Android
16
Creazione e avvio di una AVD
Porfirio Tramontana - Android
17
Emulatore
Porfirio Tramontana - Android
18
Alcune utility dell’SDK •
Tutte richiamabili anche direttamente da linea di comando
•
emulator –
•
Avvia un emulatore
adb - Android Debug Bridge –
Consente la comunicazione con un dispositivo Android, reale o emulato • • • • •
•
android –
Un file batch dal quale è possibile avviare molte utilityper la gestione dei progetti android da linea di comando •
•
adb push / adb pull – trasferisce file verso/dal dispositivo adb install – installa un’applicazione adb logcat – mostra il log di debug adb shell – avvia una shell linux sul dispositivo …
android create project \ --target
\ --name \ --path path/to/your/project \ --activity \ --package
… e molte altre
Porfirio Tramontana - Android
19
Android ed Eclipse: ADT • ADT (Android Development Toolkit) è un’estensione di eclipse totalmente dedicata ad Android – Scaricabile via Eclipse all’indirizzo https://dlssl.google.com/android/eclipse/ – Scaricabile insieme a tutto l’ambiente Eclipse da: • Win x86: http://dl.google.com/android/adt/adt-bundle-windows-x86-20140702.zip Win x64 : http://dl.google.com/android/adt/adt-bundle-windows-x86_64-20140702.zip
•
Integra nell’ambiente di sviluppo Eclipse tutti gli strumenti necessari allo sviluppo e all’esecuzione di un’applicazione Android – In particolare, rende possibile l’utilizzo di quasi tutte le utility disponibili a linea di comando
Porfirio Tramontana - Android
20
Features di ADT • Wizards e viste
Porfirio Tramontana - Android
21
Android ADT Bundle • Dal sito android developer è possibile scaricare Android ADT Bundle, che comprende ADT e una distribuzione di Eclipse preconfigurata con Android – http://developer.android.com/sdk/installing/bundle.html
Porfirio Tramontana - Android
22
Android Studio •
Più recentemente, Google ha adattato un altro ambiente di sviluppo (IntelliJ Idea) ad Android, costruendo un nuovo ambiente denominato Android Studio – http://developer.android.com/sdk/installing/studio.html
Porfirio Tramontana - Android
23
Processo di build
Porfirio Tramontana - Android
24
Build •
•
Aapt: Android Asset Packaging Tool – Legge gli xml e genera R.java Aidl: Android Interface Definition Language – Aidl converte interfacce di servizi .aidl in interfacce Java
• • • • •
Tutto il codice java è compilato generando bytecode .class Dex converte i .class in file dex eseguibili da Dalvik (e include eventuali librerie) Apkbuilder comprime e impacchetta i .dex e le risorse (grafiche, etc.) in un unico file .apk Jarsigner permette di inserire una firma nel .apk Zipalign consente di ottimizzare le risorse di memoria utilizzata dall’applicazione in un dispositivo Porfirio Tramontana - Android
25
Signing •
Ogni applicazione Android ha bisogno di una firma privata, che identifichi l’autore, per poter essere pubblicata – La firma serve per garantire fiducia nell’applicazione – La firma è messa direttamente dall’autore stesso – La firma può essere generata da tools integrati nell’ambiente, come Keytool e Jarsigner
•
Finchè l’applicazione è in fase di sviluppo e testing, è possibile utilizzare una modalità di firma debug mode – In debug mode la firma è costante (ma l’applicazione non può essere pubblicata) • • • • •
Keystore name: "debug.keystore" Keystore password: "android" Key alias: "androiddebugkey" Key password: "android" CN: "CN=Android Debug,O=Android,C=US"
– Per passare in release mode è necessaria una firma dell’utente • Il plug-in ADT Export Wizard è in grado di supportare il processo di signing
•
Se si vogliono rilasciare degli aggiornamenti dell’applicazione, è necessario riutilizzare la stessa firma
Porfirio Tramontana - Android
26
Android Manifest • Tutte le caratteristiche esterne di una applicazione Android sono strutturate in un file manifest.xml • Manifest.xml è un file pubblico, che può essere letto in chiaro da ogni possibile utente della app – Si tratta di una pratica molto diffusa, nei framework di nuova generazione: dichiarare tutte le costanti di configurazione in file xml statici, che vengono elaborati da qualche metodo del framework, in maniera trasparente al programmatore Porfirio Tramontana - Android
27
Esempio di manifest
Icona
E’ l’activity di partenza dell’applicazione Comparirà tra le
A quale “richiesta” (intent) risponde l’applicazione
Porfirio Tramontana - Android
applicazioni lanciabili
28
Interfaccia ADT Android Manifest
Porfirio Tramontana - Android
29
Interfaccia ADT Android Manifest
Porfirio Tramontana - Android
30
Android Market • Strumento standard fornito da Android per la pubblicazione e la pubblicizzazione delle applicazioni • La registrazione è molto semplice e richiede – Un Account Google – Una quota di iscrizione di 25$ (~18€) una tantum
• Nel caso in cui si voglia vendere applicazioni bisogna fornire poi anche le proprie coordinate bancarie e il proprio codice fiscale
Porfirio Tramontana - Android
31
Ricerca di un’applicazione sul market • Android Market è disponibile – come applicazione Web • https://market.android.com/
– come applicazione client su tutti i dispositivi Android • Non disponibile sugli emulatori
• In alternativa, è possibile distribuire applicazioni proprie anche in maniera diretta – Esistono ulteriori market, non approvati da Google
Porfirio Tramontana - Android
32
Pubblicazione di una applicazione • Tramite l’applicazione Web https://market.android.com/publish
Porfirio Tramontana - Android
33
Pubblicazione di una applicazione • Per pubblicare un’applicazione è necessario – L’apk firmato – Almeno 2 screenshots – Un’icona ad alta risoluzione – Titolo e descrizione (per ogni lingua che si vuole supportare) – Descrizione delle ultime modifiche – Tipo e categoria – Maturità del pubblico cui l’applicazione è diretta – Prezzo (se non gratis) • Sono automaticamente ricavati dal manifest – Versioni di Android compatibili – Dispositivi compatibili – Permessi da richiedere all’utente installatore
Porfirio Tramontana - Android
34
Modelli di business (cenni) •
•
Applicazione gratuita – E’ possibile, però, entro certi limiti, lucrare dal servizio svolto dall’applicazione, ad esempio con e-commerce Applicazione con banner pubblicitari – Ogni scaricamento del banner e, in misura maggiore, ogni click su esso fornisce ricavi • I ricavi vengono accreditati periodicamente • Esistono molti circuiti pubblicitari, tra cui Google Ads
•
•
Applicazione a pagamento – Google trattiene il 30% del costo, ma accredita velocemente il ricavato Applicazioni con acquisti in-app – E’ possibile fare acquisti internamente alla app • Ad esempio, in un gioco è possibile acquistare nuove armi, in whatsapp è possibile acquistare un prolungamento della licenza
Porfirio Tramontana - Android
35
Application Framework • Il livello di application framework fornisce un insieme di classi, interfacce e package tramite i quali è possibile sviluppare applicazioni. Ad esempio: – Activity Manager gestisce il ciclo di vita delle activity – Content providers consente la condivisione delle informazioni tra diverse applicazioni e servizi – Telephony Manager gestisce le azioni legate al telefono – Location Manager gestisce le informazioni legate al GPS – Notification Manager consente la gestione delle informazioni visualizzate come alert sulla barra di stato del dispositivo – …
Porfirio Tramontana - Android
36
Application components (cenni) Activity • •
Il componente fondamentale di una applicazione Android interattiva, poiché rappresenta il contenitore per i widget di una schermata. Eredita dalla classe Activity
Service •
I Services sono componenti responsabili di esecuzioni in background, senza possibilità di ricevere input dall’interfaccia utente, eccetto che tramite il Notification Manager • Un service è implementato come una classe che eredita dalla classe Services della quale poi istanziare un oggetto Broadcast Receiver • Un Broadcast Receiver è un ascoltatore di eventi di sistema (Intent), che può partire appena uno di essi arriva, come una ISR • Ad un Broadcast Receiver è associato un piccolo spezzone di codice che comprende di solito chiamate ad Activity o Services (da eseguire in un tempo limite, oltre il quale il sistema deduce che ci sia stato uno stallo) Content Provider • Un Content Provider è un componente che fa da interfaccia verso una sorgente di dati persistente. Un Content Provider consente il disaccoppiamento tra gestione dei dati e resto dell’applicazione –
In Android sono disponibili librerie per l’interfacciamento con SQLite, un dbms estremamente leggero
Porfirio Tramontana - Android
37
Resources • In Android è ampiamente adottata la tecnica di catalogare tutte le risorse (costanti, descrizioni di interfacce, file grafici, etc.) sotto forma di Resources • Le risorse sono elaborate automaticamente dal framework di esecuzione tramite l’utility aapt, creando un file R.java che le cataloga e le rende accessibili da codice Porfirio Tramontana - Android
38
File R • Il framework di esecuzione tiene conto delle caratteristiche dell’ambiente di esecuzione – Vengono automaticamente selezionati, ad esempio, il layout e le immagini più consone alle dimensioni e alla risoluzione dello schermo del dispositivo target Porfirio Tramontana - Android
39
Internazionalizzazione • Un classico utilizzo delle risorse è quello che consente la realizzazione parallela di diverse versioni di un’applicazione per diverse lingue • Tutte le stringhe di testo dell’interfaccia utente devono essere catalogate in una risorsa strings.xml • Se vogliamo realizzare una app in inglese, francese, italiano • Dovrebbe essere creato – uno strings.xml con le stringhe in italiano nella cartella res/values-it – uno strings.xml con le stringhe in francese nella cartella res/values-fr – uno strings.xml con le stringhe in inglese nella cartella res/values-en (o nella cartella di default res/values)
Porfirio Tramontana - Android
40
Compatibilità con gli schermi • Si può utilizzare una soluzione analoga a quella usata per l’internazionalizzazione – Diverse cartelle contenenti versioni diverse dei file di layout – Cartelle etichettate convenzionalmente in base a: • • • •
Dimensione (small-normal-large-xlarge) Densità Orientamento (land-port) Proporzioni
– I nomi delle cartelle si ottengono componendo le etichette. Ad esempio: • res/layout-xlarge-land/
Porfirio Tramontana - Android
41
Accesso alle risorse • Da codice java, tramite il file R. Sono disponibili funzioni come findViewByid(id), getString(id) … – ImageView imageView = (ImageView) findViewById(R.id.myimageview);
• Da file xml (ad esempio da un file di layout è possibile accedere ad un valore di una string): –
Porfirio Tramontana - Android
44
Layout grafico • Ad ogni Activity può essere associato un layout grafico (un file .xml) – Anche altri componenti (ad esempio i Customized Dialogs) possono avere il proprio file di layout – Anche singoli widget o sezioni di activity possono avere propri layout • I layout xml sono gestiti via codice fondamentalmente con metodi come setContentView setContentView(R.layout.main); • Main è il nome del layout (main.xml) • Il comando è nel metodo onCreate dell’Activity
Porfirio Tramontana - Android
45
Application components: Activity Activity • Una activity in Android rappresenta una singola schermata di una applicazione interattiva – Da non confondere con il concetto di UML Activity
• Una applicazione può avere diverse activity • Una sola activity per volta può essere sullo schermo – A differenza dei sistemi operativi per PC, non è prevista la possibilità di avere più finestre aperte contemporaneamente
• Al passaggio da una Activity ad un’altra, l’activity esistente viene messa in pausa • Una activity è implementata come una classe che eredita dalla classe Activity della quale poi istanziare un oggetto
Porfirio Tramontana - Android
46
Ciclo di vita di una Activity Le activity non ‘running’ vanno ad accodarsi in uno stack, pronte per essere rimesse in foreground sul video del dispositivo
Porfirio Tramontana - Android
47
Activity •
Per istanziare una activity è necessario dichiarare una classe che la estenda – public class myActivity extends Activity
•
La classe così creata potrà ridefinire (per override) alcuni metodi di Activity, tra cui quelli relativi alla gestione del suo ciclo di vita:
• • •
onCreate(Bundle savedInstanceState) - Eseguito al primo avvio dell’activity onDestroy() - Eseguito alla chiusura e deallocazione dell’activity onPause() - Eseguito quando l’activity smette di essere in primo piano (foreground),
• •
onResume() - Eseguito quando l’Activity ritorna in primo piano (foreground) onStop() - Eseguito quando l’Activity viene sostituita da un’altra (ma è ancora
• •
messa in secondo piano da un’altra Activity
istanziata in memoria) onRestart() – Eseguito quando l’Activity viene riavviata
Il ripristino di una Activity dopo una pausa è reso possibile dalla chiamata, automatica, a onSaveInstanceState() che utilizza l’oggetto Bundle passato da onCreate per mantenere le informazioni necessarie al ripristino
Porfirio Tramontana - Android
48
Intent 1/2 • Una activity Android non può indiscriminatamente chiamare altre activity – Questo meccanismo esiste sia per ragioni di sicurezza, sia per favorire il riuso di componenti, che viene mediato dal sistema
• Col termine Intent si definisce un oggetto corrispondente ad un messaggio col quale si richiede l’attivazione di una Activity (o anche un servizio o un receiver) – Ad esempio come parametro di startActivity o startActivityForResult
Porfirio Tramontana - Android
49
Intent 2/2 • Il modo più semplice per avviare da programma un’altra Activity è con explicit intent: Intent intent = new Intent(this, MiaActivity.class); startActivity(intent);
• Se, invece, vogliamo far partire un’activity che svolga un particolare compito senza conoscere staticamente la classe che la implementa (implicit intent): Intent intent = new Intent(Intent.ACTION_SEND); startActivity(intent); • In questo caso si chiede di avviare una activity che abbia settato il filtro ACTION_SEND
•
Per passare dati da una Activity ad un’altra si può utilizzare il metodo putExtra di Intent (passaggio per valore)
Porfirio Tramontana - Android
50
Cenno ai Fragment • Android non è un ambiente a finestre – Si tratta di una scelta progettuale motivata dalla necessità di poter essere installato con processori poco performanti, scarsa memoria e schermi video molto piccoli
• A partire dalle versione 3.0, la diffusione dei tablet ha portato i progettisti a proporre una soluzione parziale al problema: i Fragment • I Fragment somigliano molto ai Frame che potevano comporre una pagina Web (frameset)
Porfirio Tramontana - Android
51
Cenno ai Fragment • A differenza di due Activity, due o più fragment condividono lo stesso spazio di memoria comune, quindi è possibile per un fragment leggere e modificare gli elementi degli altri fragment della stessa activity • Ogni fragment ha il suo layout e il suo ciclo di vita
Porfirio Tramontana - Android
52
Ciclo di vita di un fragment • Il ciclo di vita di un Fragment si posiziona all’interno del ciclo di vita di una Activity, avendo ulteriori metodi suoi propri
Porfirio Tramontana - Android
53
Menu • Anche i menu possono essere scritti in XML o con l’ausilio dello strumento visuale • In alternativa, potrebbero essere
Porfirio Tramontana - Android
54
Event Delegation • •
•
La gestione dei menu in Android è realizzata con il pattern Event Delegation Dal momento che una sola Activity per volta può essere visualizzata e una Activity può avere un solo menu, il codice relativo all’handling dei menu è contenuto nell’Activity Se fosse esistita una classe menu, sarebbe stato possibile assegnarle dei metodi evento da ridefinire. Viceversa, esiste: – un unico metodo onCreateOptionsMenu(Menu menu) dell’activity che ne crea il menu – Un unico metodo onOptionsItemSelected(MenuItem item) che associa a qualsiasi opzione del menu il suo codice di handling • Questi due metodi hanno funzione di Delegati per la creazione/scelta di un qualsiasi elemento del menu
Porfirio Tramontana - Android
55
Event Delegation: esempi //Genera un menu leggendone la composizione nel file R, automaticamente // generato a partire dalle informazioni in menu.xml @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu, menu); return true; } // Parte dalla selezione di un item dal menu dell’activity. Tramite il parametro item viene passato // l’identificatore della voce di menu scelta public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { case R.id.restart: … return true; … default: return super.onOptionsItemSelected(item); } }
Porfirio Tramontana - Android
56
Dialog •
La gestione delle finestre di dialogo rappresentano un altro esempio di event delegation – Un Dialog è una interfaccia modale che va in primo piano rispetto all’activity cui appartiene, e vi rimane fino a che l’utente non ha specificato una risposta • Ad esempio, il messaggio di conferma che si fornisce ad un utente che sta cercando di uscire dal programma
•
In Android non esiste la possibilità di dichiarare i dialog via xml, per cui devono essere generati dinamicamente
– Il layout di un dialog, personalizzato, però, può essere realizzato allo stesso modo dell’interfaccia di un activity •
I dialog non sono activity, ma suoi attributi, cui possono essere agganciati dei gestori degli eventi, la cui delega per l’esecuzione spetta ancora all’Activity
Porfirio Tramontana - Android
57
Dialog: esempio 1/2 Tutto il codice seguente si pone nella classe che eredita da Activity // dichiarazione della costante identificativa e dell’oggetto AlertDialog static final int QUIT_DIALOG_ID = 1; AlertDialog quitDialog; // costruzione dell’alertDialog tramite la Factory AlertdIalog.Builder AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Sei sicuro di voler abbandonare?") .setCancelable(false) .setPositiveButton("Si'", new DialogInterface.OnClickListener() { // codice associato al pulsante Si public void onClick(DialogInterface dialog, int id) { CacciaAlTesoro.this.finish(); } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { // codice associato al pulsante Si public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); quitDialog = builder.create(); //istanziazione dell’oggetto quiDialog
Porfirio Tramontana - Android
58
Dialog: esempio 2/2 // Override del metodo onCreateDialog di Activity, responsabile della // visualizzazione in foreground del Dialog protected Dialog onCreateDialog(int id) { switch (id) { case QUIT_DIALOG_ID: return quitDialog; … // Chiamata del metodo showDialog, che scatena la visualizzazione del // Dialog. In questo caso il dialog è legato alla pressione di una voce dal menu public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { case R.id.quit: showDialog(QUIT_DIALOG_ID); return true;
Porfirio Tramontana - Android
59
Tutorial: IndovinaOraDelitto • Si tratta di un progetto molto più piccolo – Piccolo gioco nel quale bisogna indovinare “l’orario del delitto” (un orario scelto a caso nelle 24 ore) • Ad ogni tentativo, il sistema risponde dicendo se l’orario esatto è precedente o successivo – Un’unica interfaccia un’unica Activity – Gestione delle SharedPreferences (per memorizzare il punteggio migliore) – Riuso di un componente (widget) per la richiesta dell’orario – Visualizzazione di un’immagine di sfondo e di un’icona
Porfirio Tramontana - Android
63
Crea una nuova Android Application • Oltre a nome e package bisogna impostare:
– Versione minima della SDK • Più è bassa più la app sarà compatibile per dispositivi vecchi
– Versione target della SDK • Quella sulla quale testeremo la app
– Compilatore • Scegliamo di solito il più recente Porfirio Tramontana - Android
64
Impostazione icone •
Dobbiamo creare una icona per la app – Dobbiamo creare con diverse risoluzioni, per adattarsi alle diverse possibili dimensioni dello schermo di un cellulare o tablet
•
Possiamo caricare l’icona da un qualsiasi file e darle una forma
Porfirio Tramontana - Android
65
Impostazione prima Activity •
Dobbiamo creare la prima Activity – Il sistema ci suggerisce alcuni layout possibili – Successivamente diamo un nome all’Activity e al suo layout
Porfirio Tramontana - Android
66
Codice generato automaticamente • • • •
MainActivity.java File automatici BuildConfig e R (da non modificare) Librerie di sistema da importare File png rappresentativi delle icone a diverse risoluzioni, in diverse cartelle –
• • •
Xml con la descrizione del layout Xml con la descrizione del menu Xml che riportano le stringhe di testo costanti utilizzate nel programma –
• •
I nomi delle cartelle seguono sempre precise convenzioni e non devono essere modificati
Anche le stringhe possono variare con la dimensione dello schermo. Ad es. su schermo piccolo si possono utilizzare abbreviazioni
AndroidManifest.xml Altre proprietà del progetto (utili per la compilazione)
Porfirio Tramontana - Android
67
AndroidManifest.xml
Porfirio Tramontana - Android
68
Editor del layout
Porfirio Tramontana - Android
69
Immagine di sfondo e icona •
Modifichiamo la casella di testo «Hello, World» – Scriviamo «Indovina l’ora del delitto», scriviamola in rosso su sfondo nero e con font più grande • Cerchiamo di definire delle resources, anziché mettere costanti nel codice xml • In particolare i colori vanno in un file di colori della cartella res/values • Il background può essere editato tramite Other properties/all By Name/Background nel menu contestuale
•
Mettiamo un’immagine di background – Dobbiamo prima copiarla in una o più delle cartelle res/drawable
•
Creiamo un pulsante «Ipotizza un orario» Porfirio Tramontana - Android
70
Immagine di sfondo e icona •
Creiamo un menu (menu.xml nella cartella menu) con un’unica voce: esci – La stringa «Esci» la salviamo come risorsa
Porfirio Tramontana - Android
71
MainActivity.java •
Codice generato automaticamente
package com.example.indovinaprova; import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
Porfirio Tramontana - Android
Collegamento dinamico col layout creato visualmente (e trasformato dal framework in codice java e compilato) Collegamento dinamico al menu creato visualmente (e trasformato dal framework in codice java e compilato) 72
Codice per il menu e il dialog corrispondente 1/3 •
Vogliamo che sulla voce di menu «esci» si apra un dialog di conferma e eventualmente venga chiusa la app – In onCreate
AlertDialog.Builder è in
AlertDialog.Builder builder = new AlertDialog.Builder(this); grado di «costruire» un builder.setMessage("Sei sicuro di voler uscire?") alert dialog .setCancelable(false) .setPositiveButton("Si'", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { MainActivity.this.finish(); Metodo collegato al } pulsante «SI» }) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } Metodo collegato al pulsante }); «No» quitDialog = builder.create(); Qui viene davvero creato il
dialog
Porfirio Tramontana - Android
73
Codice per il menu e il dialog corrispondente 2/3 •
Vogliamo che sulla voce di menu «esci» si apra un dialog di conferma e eventualmente venga chiusa la app
@Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { case R.id.esci: showDialog(QUIT_DIALOG_ID); return true; default: return super.onOptionsItemSelected(item); } }
Porfirio Tramontana - Android
Metodo per collegare i click sulle voci di menu alle azioni corrispondenti
Avvio del dialog QUIT_DIALOG_ID
74
Codice per il menu e il dialog corrispondente 3/3 •
Vogliamo che sulla voce di menu «esci» si apra un dialog di conferma e eventualmente venga chiusa la app
Metodo che viene chiamato tramite showDialog e che @Override abbina ai codici dei dialog protected Dialog onCreateDialog(int id) { le azioni corrispondenti
switch (id) { case QUIT_DIALOG_ID: return quitDialog; } return null; };
Avvio del dialog QUIT_DIALOG_ID
Porfirio Tramontana - Android
Codice per il pulsante e il dialog corrispondente 1/3 •
Vogliamo che sul pulsante «Ipotizza» si avvii un componente che fa scegliere un orario e venga confrontato con quello da indovinare – In onCreate
Abbiniamo al pulsante chimato ipotizza nel layout l’oggetto Button mPickTime
//pulsante Ipotizza orario mPickTime = (Button) findViewById(R.id.ipotizza); mPickTime.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Ascoltatore del pulsante showDialog(TIME_DIALOG_ID); } Avvio del dialog });
TIME_DIALOG_ID
Porfirio Tramontana - Android
76
Codice per il pulsante e il dialog corrispondente 2/3 •
Vogliamo che sul pulsante «Ipotizza» si avvii un componente che fa scegliere un orario e venga confrontato con quello da indovinare Aggiungiamo
@Override TIME_DIALOG_ID protected Dialog onCreateDialog(int id) { switch (id) { case TIME_DIALOG_ID: return new TimePickerDialog(this,mTimeSetListener, mHour, mMinute, true); case QUIT_DIALOG_ID: return quitDialog; return null; Avvio di un TimePickerDialog, oggetto }; proveniente da una delle librerie standard }
di Android
mTimeSetListener conterrà il codice collegato al pulsante Imposta mHour e mMinute sono variabili 77 di output e conterranno l’ora e minuto scelti
Porfirio Tramontana - Android
Codice per il pulsante e il dialog corrispondente 3/3 •
Vogliamo che sul pulsante «Ipotizza» si avvii un componente che fa scegliere un orario e venga confrontato con quello da indovinare
private TimePickerDialog.OnTimeSetListener mTimeSetListener = new TimePickerDialog.OnTimeSetListener() { public void onTimeSet(TimePicker view, int hourOfDay, int minute) { mHour = hourOfDay; L’ora inserita in mMinute = minute; input if (mHouroraOK || (mHour==oraOK && mMinute>minutoOK)) { txtStato.setText("Prima! (finora "+tentativi+" tentativi)"); tentativi++; } else if (mHour==oraOK && mMinute==minutoOK) txtStato.setText("Hai indovinato in "+tentativi+" tentativi ed e' il miglior risultato di oggi!"); } } Porfirio Tramontana - Android
78
Resto del codice •
Costanti e variabili
private static final Random RNG = new Random(); private int oraOK; private int minutoOK; private int tentativi=1; static final int TIME_DIALOG_ID = 0; static final int QUIT_DIALOG_ID = 1; • In onCreate txtStato = (TextView)findViewById(R.id.textView1); oraOK=RNG.nextInt(24); minutoOK=RNG.nextInt(60);
Porfirio Tramontana - Android
79
Esecuzione
Porfirio Tramontana - Android
80
Progetto d’esempio: Caccia Al Tesoro • Sfruttando le capacità di ricezione GPS contenute in un dispositivo mobile Android, si vuole realizzare una sorta di Caccia al Tesoro • Una Caccia al Tesoro si compone di una sequenza di tappe da completare – L’obiettivo di ogni tappa è il raggiungimento di un determinato luogo, che dovrà essere notificato dalle coordinate GPS lette dal dispositivo stesso • In pratica il giocatore dovrà recarsi fisicamente nel luogo richiesto
Porfirio Tramontana - Android
81
Modello delle informazioni • Il modello delle informazioni è molto semplice: – Una Caccia è composta di Tappe (3 in questa versione) e può essere giocata da un unico giocatore • Bisogna memorizzare il tempo trascorso dall’inizio della tappa
– Ogni Tappa ha un nome e una coppia di coordinate dell’obiettivo – C’è una ovvia relazione di aggregazione tra Caccia e Tappa
Porfirio Tramontana - Android
82
Modello dell’interfaccia • L’interfaccia utente consiste di un’unica classe che estende Activity, CacciaAlTesoro, con 4 campi di testo, definiti staticamente in xml
Porfirio Tramontana - Android
83
Extra features • Ogni tappa ha un tempo massimo e un punteggio dipendente dal tempo impiegato • E’ possibile chiedere degli aiuti, che fanno diminuire il punteggio. In particolare: – L’aiuto distanza visualizza la distanza in linea d’aria dal punto obiettivo – L’aiuto direzione indica la direzione (rispetto al nord) nella quale andare per raggiungere, in linea d’aria, l’obiettivo • Il gioco non si interrompe se un’altra applicazione (ad esempio il telefono) si attiva – Il gioco termina solo su esplicita richiesta dell’utente
Porfirio Tramontana - Android
84
Menu • Un menu definito staticamente per l’unica Activity con 4 opzioni semplici e un sottomenu per gli aiuti con 4 opzioni • 9 handler da implementare (nella classe CacciaAlTesoro che estende Activity e fa da Delegate)
Porfirio Tramontana - Android
85
Suddivisione delle responsabilità •
La classe CacciaAlTesoro estende Activity, gestisce l’interfaccia utente – ha la delega per la gestione degli eventi da menu – Implementa e gestisce i Dialog – Gestisce gli eventi legati al GPS – Gestisce il ciclo di vita dell’activity
public class CacciaAlTesoro extends Activity implements LocationListener
• •
La classe Caccia implementa l’algoritmo del gioco – Calcolo del punteggio, gestione del tempo, etc. La classe Tappa modella le strutture dati di una singola tappa – Per semplicità, in questa versione le tappe sono istanziate nel codice di Caccia
Porfirio Tramontana - Android
86
Gestione del GPS •
La classe Activity implementa – –
myManager = (LocationManager) getSystemService(LOCATION_SERVICE); myManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) •
– –
Forza una valutazione sincrona della posizione
private void startListening() myManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); private void stopListening() { myManager.removeUpdates(this);
–
public void onLocationChanged(Location location) { … } •
Parte in maniera asincrona col programma e sincrona con il rilevamento GPS
•
La classe android.location.Location fornisce tra l’altro i metodi getLongitude() e getLatitude()
•
Nel Manifest.xml bisogna settare
Porfirio Tramontana - Android
87
Gestione di chiusura e riapertura • Nella classe CacciaAlTesoro – onCreate istanzia tutti i dialog, inizializza gli attributi e avvia la Caccia – onPause salva lo stato della Caccia – onResume ripristina lo stato della Caccia – onDestroy distrugge i dati della Caccia e chiude l’applicazione • La Caccia prosegue anche se l’applicazione non è visibile sull’interfaccia sfruttando il fatto che il tempo (di sistema) continua a scorrere – L’eventuale tempo scaduto su di una caccia viene in realtà notificato solo quando l’applicazione è riaperta Porfirio Tramontana - Android
88
SharedPreferences • •
Come memorizzare il punteggio migliore? Android ha diversi metodi per gestire la persistenza. Il più semplice si basa sulle SharedPreferences, simili alle variabili di sessione delle applicazioni Web
•
Esempio di lettura private SharedPreferences settings; settings = getSharedPreferences("RecordFile", 0); min = settings.getInt("record", 1000);
•
Esempio di scrittura (salva record) SharedPreferences.Editor editor = settings.edit(); editor.putInt("record", min); editor.commit(); Porfirio Tramontana - Android
89
Ulteriori approfondimenti
Porfirio Tramontana - Android
90
Services • I Services sono componenti responsabili di esecuzioni in background, senza possibilità di interagire con l’interfaccia utente – eccetto che tramite il Notification Manager, che consente di scrivere sulla barra delle notifiche, emettere suoni o vibrazioni
• Più service possono essere eseguiti in concorrenza tra loro e con una Activity • Un service è implementato come una classe che eredita dalla classe Services della quale poi istanziare un oggetto – Di solito si effettua l’override di due metodi fondamentali: startService e stopService – Un service può avviare un Intent (e tramite esso un’Activity)
Porfirio Tramontana - Android
91
Broadcast Receiver • Un Broadcast Receiver è un ascoltatore di eventi di sistema (Intent), che può partire appena uno di essi arriva – In analogia con una ISR • Ad un Broadcast Receiver è associato un piccolo spezzone di codice che comprende di solito chiamate ad Activity o Services – da eseguire in un tempo limite, oltre il quale il sistema deduce che ci sia stato uno stallo • Sono dichiarati anch’essi nel Manifest – Un Broadcast Receiver può anche essere aativato da codice col metodo Context.sendBroadcast()
Porfirio Tramontana - Android
92
Content Provider • Un Content Provider è un componente che fa da interfaccia verso una sorgente di dati persistente. • Un Content Provider consente il disaccoppiamento tra gestione dei dati e resto dell’applicazione – In Android sono disponibili librerie per l’interfacciamento con SQLite, un dbms estremamente leggero basato su SQL – Un db SQLite serve unicamente per salvare dati persistente sulla memoria del dispositivo – In alternativa, possiamo utilizzare file di testo per implementare database XML – L’utilizzo di un Content Provider NON è necessario ma facilita astrazione, riuso e testing Porfirio Tramontana - Android
93
Accesso a risorse Web • Una applicazione Android può accedere in numerosi modi a risorse remote • Solo a titolo di esempio: – Con il widget WebView è possibile aprire all’interno di una Activity l’equivalente di un browser – Con il widget MapView è possibile accedere dall’interno di una Activity alla mappe di Google – E’ possibile eseguire richieste http, ad esempio verso servizi Web
Porfirio Tramontana - Android
94
Esempio: riuso di un servizio meteo • Caso 1) Il servizio meteo è disponibile tramite richieste http – In risposta viene restituito un XML – Bisogna scrivere un analizzatore in grado di leggere dati da un XML • SAX, DOM, ...
Ingegneria del Software 2 – Service Engineering
95
Codice SAX (1/2) try { url = new URL("http://www.google.com/ig/api?weather=Procida"); /* Get a SAXParser from the SAXPArserFactory. */ SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); /* Get the XMLReader of the SAXParser we created. */ XMLReader xr = sp.getXMLReader(); /* Create a new ContentHandler and apply it to the XML-Reader*/ MeteoXMLHandler meteoXMLHandler = new MeteoXMLHandler(this); xr.setContentHandler(meteoXMLHandler); /* Parse the xml-data from our URL. */ xr.parse(new InputSource(url.openStream())); /* Parsing has finished. */ } catch (MalformedURLException e) {e.printStackTrace(); } catch (ParserConfigurationException e) {e.printStackTrace(); } catch (SAXException e) {e.printStackTrace(); } catch (IOException e) {e.printStackTrace(); }
Ingegneria del Software 2 – Service Engineering
96
Codice SAX (2/2) package com.porfirio.orariprocida2011; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; ... public class MeteoXMLHandler extends DefaultHandler{ StringBuffer buff = null; boolean buffering = false; @Override public void startDocument() throws SAXException { } @Override public void endDocument() throws SAXException { } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (localName.equals("wind_condition")) { /** Get attribute value */ String attr = attributes.getValue("data"); setMeteo(attr); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { } ...
Ingegneria del Software 2 – Service Engineering
97
• Caso 2) Il servizio meteo è disponibile sotto forma di json raggiungibile via http – Bisogna scrivere un analizzatore di file json
Ingegneria del Software 2 – Service Engineering
98
Esempio di risposta json { "response":{ "version":"0.1", "features":{ "conditions":1 } }, "current_observation":{ "image":{ "url":"http://icons-ak.wxug.com/graphics/wu2/logo_130x80.png", "title":"Weather Underground", }, "display_location":{ "full":"San Francisco, CA", "city":"San Francisco", "state":"CA", }, …
Ingegneria del Software 2 – Service Engineering
99
Codice per json import org.json.JSONException; import org.json.JSONObject; import org.json.simple.*; private void leggiMeteo() { URL url; JSONObject jsonObject=null; try { jsonObject = readJsonFromUrl("http://api.wunderground.com/api/7a2bedc35ab44ecb/geolookup/conditions/q/IA/Procida.jso n"); if (!(jsonObject==null)){ meteo.setWindKmh((Double) jsonObject.getJSONObject("current_observation").get("wind_kph")); Integer windDir=(Integer) jsonObject.getJSONObject("current_observation").get("wind_degrees"); meteo.setWindDirectionString((String) jsonObject.getJSONObject("current_observation").get("wind_dir")); meteo.setWindBeaufort((Double) jsonObject.getJSONObject("current_observation").get("wind_kph")); } catch (JSONException e) {Log.d("ORARI", "dati meteo non caricati da web");}
Ingegneria del Software 2 – Service Engineering
100
Servizi di Sistema • Il sistema Android fornisce classi e servizi per accedere in lettura e/o comandare un po’ tutti i sensori a disposizione: – – – – – – – –
Power Service Vibrator Service Alarm Service Sensor Service Audio Service Telephony Service Wi-Fi Service …
Sensor Service •
Tramite la classe SensorManager è possibile accedere alla maggior parte dei sensori: –
•
SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE)
Per conoscere l’insieme dei sensori disponibili: – getSensorList (type) • Type può essere: – – – – – – – – –
TYPE_ACCELEROMETER TYPE_GYROSCOPE TYPE_LIGHT TYPE_MAGNETIC_FIELD TYPE_ORIENTATION TYPE_PRESSURE TYPE_PROXIMITY TYPE_TEMPERATURE …
Esempio: Sensore di luminosità • Aggiungiamo un altro TextView sul layout • In onCreate aggiungiamo: txtSensore= (TextView)findViewById(R.id.textView2); sensorService = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorService.getDefaultSensor(Sensor.TYPE_LIGHT); if (sensor != null) { sensorService.registerListener(mySensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL); } }
• In questo modo abbiamo creato un campo di testo e un servizio di ascolto del sensore luminosità, legato alla classe mySensorEventListener
Classe mySensorEventListener private SensorEventListener mySensorEventListener = new SensorEventListener() { @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { float luce = event.values[0]; txtSensore.setText(Double.toString(luce)); } }; •
Quando cambia il valore del sensore lo leggiamo (è in event.values[0]) e lo visualizziamo in txtSensore
Android Testing
Porfirio Tramontana - Android
105
Android Testing: generalità • Un’applicazione Android in senso lato è composta di un lato client e di una o più tipologie di risorse lato server – Web Applications, Web Services, Risorse REST …
• Ci si limiterà allo studio delle problematiche del testing della parte client, la cosiddetta app
• Una app Android è sostanzialmente un’applicazione interattiva sottoposta a: – Eventi utente (eventi touch, segnali da sensori) – Eventi di sistema (interruzioni, segnali broadcast) Porfirio Tramontana - Android
106
Android Testing: generalità • E’ necessario definire, adattandoli all’ambiente Android: – test models, per rappresentare le tipologie di elementi e interazioni da considerare e procare; – testing levels, che specifichino i diversi punti di vista e obiettivi rispetto ai quali viene progettato il testing; – test strategies, che definiscono obiettivi, euristiche e algoritmi da seguire nella progettazione dei casi di test; – testing processes, che definiscono le modalità di esecuzione dei processi per il testing delle applicazioni Android; – testing tools, strumenti a supporto delle attività di testing, in particolare a supporto della loro automazione
Porfirio Tramontana - Android
107
Unit Testing • Che cosa è possibile considerare come unità, nel testing di un’applicazione Android? – – – – –
Activity Service Broadcast Receiver Content Provider Classi Java semplici, che non estendono classi del framework Android
Porfirio Tramontana - Android
108
Testing con JUnit • E’ possibile utilizzare un framework come Junit per le applicazioni Android (in particolare per le Activity)? – Problema: una sola activity può accedere attivamente all’interfaccia utente. – Soluzione: un framework di testing che esegua la activity sotto testing come sua parte, utilizzando funzionalità di instrumentazione per poterla monitorare • In questo modo, è possibile pensare di testare una Activity scrivendo dei classici Android JUnit Test Cases, nell’ambito, però, di un project separato
– Da notare che il progetto di test e il progetto da testare devono avere la stessa signature (di solito si usa quella pubblica di debug) http://developer.android.com/guide/topics/testing/activity_testing.html Porfirio Tramontana - Android
109
Android Test Architecture
Porfirio Tramontana - Android
110
Creazione di un progetto di test • Da linea di comando si può scrivere android create test-project -m -n -p
• In Eclipse è sufficiente utilizzare il widget di creazione progetto
Porfirio Tramontana - Android
111
Manifest di un progetto di test Controlla l’esecuzione delle
classi del package
Porfirio Tramontana - Android
112
Creazione di una classe di test • Utilizzo di JUnit3
Porfirio Tramontana - Android
113
Metodi generati package com.porfirio.orariprocida2011.test; import com.porfirio.orariprocida2011.OrariProcida2011Activity; import android.test.ActivityInstrumentationTestCase2; public class OrariProcida2011ActivityTests extends ActivityInstrumentationTestCase2 { public OrariProcida2011ActivityTests() { super("com.porfirio.orariprocida2011", OrariProcida2011Activity.class); } @Override protected void setUp() throws Exception { super.setUp(); } protected void tearDown() throws Exception { super.tearDown(); }
} Porfirio Tramontana - Android
114
Primi test case Precondizioni: esistenza degli oggetti utilizzati nel test … public class OrariProcida2011ActivityTests extends ActivityInstrumentationTestCase2 {
public void testPreconditions() { assertNotNull(mTextView1); assertNotNull(mListView); }
private OrariProcida2011Activity mActivity; private TextView mTextView1; private ListView mListView;
public void testTextView1(){ String resourceString = new String(mActivity.getString(com.porfir io.orariprocida2011.R.string.mezzo));
@Override protected void setUp() throws Exception { super.setUp(); mActivity = this.getActivity(); mTextView1=(TextView) mActivity.findViewById(R.id.textVi ew1); mListView =(ListView) mActivity.findViewById(R.id.listMe zzi); }
assertEquals(resourceString,(String)mTextView1. getText()); }
Oggetti utilizzati nel test Porfirio Tramontana - Android
protected void tearDown() throws Exception { super.tearDown(); } } Test sul corretto valore di una casella di testo 115
Esecuzione dei test • Da Eclipse Run as Junit Test • Sequenza di esecuzione (Console) [2011-11-16 19:33:36 - OrariProcida2011Testing] -----------------------------[2011-11-16 19:33:36 - OrariProcida2011Testing] Android Launch! [2011-11-16 19:33:36 - OrariProcida2011Testing] adb is running normally. [2011-11-16 19:33:36 - OrariProcida2011Testing] Performing android.test.InstrumentationTestRunner JUnit launch [2011-11-16 19:33:36 - OrariProcida2011Testing] Automatic Target Mode: using existing emulator 'emulator-5554' running compatible AVD 'AVD_1_6' [2011-11-16 19:33:36 - OrariProcida2011Testing] Uploading OrariProcida2011Testing.apk onto device 'emulator-5554' [2011-11-16 19:33:36 - OrariProcida2011Testing] Installing OrariProcida2011Testing.apk... [2011-11-16 19:33:40 - OrariProcida2011Testing] Success! [2011-11-16 19:33:40 - OrariProcida2011Testing] Project dependency found, installing: OrariProcida2011 [2011-11-16 19:33:44 - OrariProcida2011] Application already deployed. No need to reinstall. [2011-11-16 19:33:44 - OrariProcida2011Testing] Launching instrumentation android.test.InstrumentationTestRunner on device emulator-5554 [2011-11-16 19:33:44 - OrariProcida2011Testing] Collecting test information [2011-11-16 19:33:48 - OrariProcida2011Testing] Sending test information to Eclipse [2011-11-16 19:33:48 - OrariProcida2011Testing] Running tests... [2011-11-16 19:34:23 - OrariProcida2011Testing] Test run finished
Porfirio Tramontana - Android
116
Un test più complesso •
Esempio di test che interagisce con l’interfaccia utente, settando un valore di uno Spinner public void testListaVuota(){ mActivity.runOnUiThread( new Runnable() { public void run() { mSpnPortoPartenza.setSelection(1); mSpnPortoArrivo.setSelection(1); assertEquals(0,(int)mListView.getCount()); } }); mInstrumentation.waitForIdleSync(); }
• •
Per settare un campo di una oggetto sulla UI, è necessario, in Android, farlo interagendo nello stesso thread della UI stessa Per impedire la concorrenza tra eventi dell’utente reale ed eventi simulati da test setActivityInitialTouchMode(false);
Porfirio Tramontana - Android
117
Activity Testing • Finora sono stati esemplificati casi di test riguardanti l’interazione con la UI in un’Activity • Altri possibili test da eseguire su di una Activity: – Testing in risposta a eventi riguardanti il ciclo di vita dell’Activity – Testing in risposta ad eventi di sistema – Testing in risposta ad eventi provenienti da sensori
Porfirio Tramontana - Android
118
Testing del ciclo di vita di un Activity • Per simulare una pausa e resume, ad esempio: Instrumentation mInstr = this.getInstrumentation(); mInstr.callActivityOnPause(mActivity); mInstr.callActivityOnResume(mActivity);
Porfirio Tramontana - Android
119
Testing in isolamento • Per realizzare Unit Testing è necessario limitare al minimo e controllare le dipendenze dell’unità testata dal resto del software e dell’ambiente di esecuzione • La classe IsolatedContext è in grado di riprodurre un contesto di esecuzione fittizio, da utilizzare tutte le volte che sia necessario, senza dipendere dal reale stato del sistema • Per emulare gli eventi di sistema si possono utilizzare le classi del package android.hardware – Per emulare I sensori si possono usare le classi Sensor, SensorEvent, SensorEventListener e SensorManager, ridefinendole in modo che generino eventi fittizi
Porfirio Tramontana - Android
120
Esempio Mock • SMSReceiver è un Broadcast Receiver che ascolta per la ricezione di SMS • SMS è una Activity che viene avviata da SMSReceiver in seguito alla ricezione di un SMS e ne visualizza il testo • MockProvider è una classe che estende Thread e, tramite Intent si dichiara (tramite Intent) in grado di inviare SMS e controllarne il delivery • SMSMock è una classe che estende SMS, imitandolo. In pratica definisce e avvia un MockProvider • SMSTesting è una classe di test che, così come SMSMock, definisce e avvia un MockProvider e gli chiede di inviare un messaggio, come prova
Porfirio Tramontana - Android
121
Class Diagram • •
•
• •
SMSTesting istanzia SMSMock e MockProvider SMSMock sostituisce il metodo onCreate di SMSActivity e, istanziandosi, avvia MockProvider e lo dichiara come gestore degli SMS (al posto di un reale fornitore) MockProvider dichiara due Intent corrispondenti a eventi di Invio e Consegna del messaggio SMSTesting chiede a MockProvider di “inviare” un messaggio SMSReceiver riceve i messaggi fittiziamente inviati da MockProvider e li gestisce come se fossero reali
Porfirio Tramontana - Android
<> SMSActivity
<> SMSReceiver
+onCreate()
+onReceive()
<> MockProvider
SMSMock +onCreate() 1
1
+sendMessage()
SMSTesting +test()
122
Codice ... public class SmsTesting extends ActivityInstrumentationTestCase2 { private SMSMock myActivity; private MockProvider mymockprov; ... @Override protected void setUp() throws Exception{ super.setUp(); setActivityInitialTouchMode(false); mymockprov = new MockProvider(SmsManager.getDefault(),getInstrumentation().getContext()); } public void testcase1(){mymockprov.invia_messaggio(phoneNumber,messaggio);} ... public class MockProvider extends Thread{ private Context ctx; private SmsManager sms; private PendingIntent sentPI; private PendingIntent deliveredPI; ... @Override public void run() { sentPI = PendingIntent.getBroadcast(ctx, 0, new Intent(SENT), 0); deliveredPI = PendingIntent.getBroadcast(ctx, 0, new Intent(DELIVERED), 0); } public void invia_messaggio(String PHNUM, String MEX){sms.sendTextMessage(PHNUM, null,MEX, sentPI, deliveredPI);} }
Porfirio Tramontana - Android
123
Unit Testing di altri componenti •
Per testare il ciclo di vita di un Service si possono utilizzare i metodi Context.startService e Context.bindService – Il testing di un servizio è più semplice del testing di una Activity, perchè non dipende da eventi utente e di sistema
•
Un Broadcast Receiver è molto semplice da testare. Per avviarlo da test si può utilizzare il metodo Context.sendBroadcast per simulare l’invio di un Intent
•
Un ContentProvider fornisce un’astrazione di accesso ai dati. Deve essere testato rispetto all’interfaccia di accesso che fornisce
•
Alcune apposite classi da cui ereditare – ServiceTestCase, ProviderTestCase2
Porfirio Tramontana - Android
124
Livelli di Testing • Dopo lo Unit Testing: – Integration Testing • Le varie unità sono testate in insiemi più grandi
– System Testing in tre stage • Simulation stage – Il software viene testate in isolamento in un ambiente completamente simulato
• Prototyping stage – L’ambiente reale inizia a rimpiazzare quello simulato, ma il software è eseguito sempre su di un emulatore
• Pre-production stage – Il software è eseguito su di un device reale in un ambiente reale
Porfirio Tramontana - Android
125
DDMS • Il DDMS (Dalvik Debug Monitor Server) è uno strumento dell’Android SDK particolarmente utile in fase di prototyping – Monitora il comportamento della macchina virtuale • • • •
Accesso al file system Thread in esecuzione Allocazione della memoria Log dei messaggi
– Consente l’emulazione (spoofing) di • Variazioni nelle coordinate GPS • Ricezioni di messaggi SMS • Ricezione di telefonate
Porfirio Tramontana - Android
126
DDMS
Porfirio Tramontana - Android
127
Robotium • Robotium è un framework a supporto del testing di unità delle Activity che estende e potenzia Junit. In particolare: – è più semplice scrivere test che riguardano più Activity, Dialog, Toast, Menu e Context Menu. – E’ migliorata la leggibilità dei test case – I test case sono meno dipendenti dalla variabilità dei tempi di esecuzione
• Robotium è un progetto open source la cui prima versione è stata rilasciata a gennaio 2010 – http://code.google.com/p/robotium/
Porfirio Tramontana - Android
128
Caratteristiche di Robotium • Il funzionamento di Robotium è tutto basato sull’utilizzo di un oggetto denominato SOLO Solo solo = new Solo(getInstrumentation(),getActivity());
• Tramite l’oggetto solo è possibile interrogare e modificare i widget della UI, eventualmente anche senza conoscerne l’identificativo – Particolarmente utile nei test di accettazione – Ad esempio, è possibile selezionare l’insieme dei widget visibili oppure è possibile selezionare un widget in base al testo che mostra
Porfirio Tramontana - Android
129
Esempi public void testTextView(){ String resourceString = new String(solo.getString(com.porfirio.orariprocida2011.R.strin g.mezzo)); TextView mTextView1=solo.getText(1); assertEquals(resourceString,(String)mTextView1.getText()); }
public void testButtonRobotium(){ TextView mTxtOrario=solo.getText(3); String initial=new String(mTxtOrario.getText().toString()); solo.clickOnButton("<<"); solo.clickOnButton(">>"); assertEquals(mTxtOrario.getText().toString(),initial); }
Porfirio Tramontana - Android
130
Monkey • Monkey è un’utility interna fornita con l’android SDK, che è in grado di generare eventi utente pseudocasuali su una qualsiasi interfaccia, registrando gli eventuali crash – Monkey gira all’interno del dispositivo; per avviarla bisogna passare per adb. Ad esempio, da linea di comando: adb shell monkey –v -p com.porfirio.orariprocida2011 30
Porfirio Tramontana - Android
131
Output di Monkey :Monkey: seed=0 count=30 :AllowPackage: com.porfirio.orariprocida2011 :IncludeCategory: android.intent.category.LAUNCHER :IncludeCategory: android.intent.category.MONKEY // Event percentages: // 0: 15.0% // 1: 10.0% // 2: 15.0% // 3: 25.0% // 4: 15.0% // 5: 2.0% // 6: 2.0% // 7: 1.0% // 8: 15.0% :Switch: #Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10000000;com ponent=com.porfirio.orariprocida2011/.OrariProcida2011Activity;end // Allowing start of Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.porfirio.orariprocida2011/.OrariProcida2011Activity } in package com.porfirio.orariprocida2011 :Sending Pointer ACTION_MOVE x=-4.0 y=2.0 :Sending Pointer ACTION_UP x=0.0 y=0.0 :Sending Pointer ACTION_DOWN x=47.0 y=122.0 Events injected: 30 :Dropped: keys=0 pointers=0 trackballs=0 flips=0 ## Network stats: elapsed time=7766ms (7766ms mobile, 0ms wifi, 0ms not connecte d) // Monkey finished
Porfirio Tramontana - Android
132
Monkeyrunner •
Monkeyrunner, a differenza di monkey, è un API che consenta la scrittura di programmi in grado di controllare un dispositivo Android dall’esterno – Ad esempio è possibile scrivere un programma Python che installa un’applicazione, esegue casi di test, invia eventi, salva screenshot
•
Esempio di programma: from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice device = MonkeyRunner.waitForConnection() device.installPackage('myproject/bin/MyApplication.apk') package = 'com.example.android.myapplication' activity = 'com.example.android.myapplication.MainActivity' runComponent = package + '/' + activity device.startActivity(component=runComponent) device.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP) result = device.takeSnapshot() result.writeToFile('myproject/shot1.png','png')
Porfirio Tramontana - Android
133
Android Ripper • Una alternativa, con più “intelligenza” di Monkey è l’Android Ripper sviluppato all’Università di Napoli – Navigazione “in ampiezza” o “in profondità” dell’interfaccia utente di un’applicazione Android • Esecuzione di eventi su tutti i Widget trovati
– – – –
Generazione di sequenze di esecuzione Generazione di casi di test JUnit Rilevazione automatica di crash Valutazione della copertura ottenuta (con Emma)
Porfirio Tramontana - Android
134
Problemi • L’albero è teoricamente illimitato Si può limitarlo: – fissando un limite alla profondità – interrompendo l’esplorazione quando si giunge ad una Activity “simile” ad una già esplorata Porfirio Tramontana - Android
135
Emma • Emma è uno strumento di istrumentazione del codice sorgente che consente di valutare l’effettiva copertura del codice ottenuta a seguito dell’esecuzione di un insieme di casi di test • Può essere eseguito solo da linea di comando, tramite adb. Ad esempio: – adb shell am instrument -w -e coverage true [Package di test]/android.test.InstrumentationTestRunner
• Genera report e metriche, anche in formato HTML • Molto utile per il testing White Box Porfirio Tramontana - Android
136
Output di EMMA
Porfirio Tramontana - Android
137
Copertura del codice con EMMA
Porfirio Tramontana - Android
138
TestDroid • TestDroid comprende un insieme di strumenti che consentono l’automazione di test di applicazioni Android in ambiente reale e simulato – – – –
TestDroid Enterprise TestDroid Cloud TestDroid Privateloud TestDroid Recorder
• http://testdroid.com/
Porfirio Tramontana - Android
139
TestDroid Recorder • TestDroid Recorder è uno strumento, parzialmente di libero utilizzo, che fornisce funzionalità di capture & replay su Android – Capture: è in grado di osservare esecuzione utente su dispositivo reale o anche su emulatore – Replay: è in grado di rieseguire le interazioni catturate e anche di generare codice Junit+Robotium rieseguibile http://testdroid.com/product/testdroid-recorder#0 • TestDroid Recorder è disponibile sotto forma di estensione di Eclipse/ADT http://www.testdroid.com/updates/ • E’ necessario registrarsi e scrivere e-mail e password all’atto dell’utilizzo di TestDroid Recorder in Eclipse Porfirio Tramontana - Android
140
TestDroid Recorder •
Tutorial per l’utilizzo di TestDroid Recorder sono disponibili a: – http://help.testdroid.com/customer/portal/topics/315855-testdroid-recordertutorials/articles
1. Avviare New dal menu file o dal menu contestuale dell’app da testare Scegliere First Recording 2. Se necessario, inserire login e password di registrazione a TestDroid Selezionare l’app da testare
Porfirio Tramontana - Android
141
TestDroid Recorder - Tutorial 1. Dal pannello è possibile avviare la registrazione premendo Record L’applicazione verrà installata e avviata sul dispositivo o sull’emulatore scelto 2. Utilizzare l’app eseguendo gli scenari da registrare 3. Premere Stop I test verranno generati all’interno di un apposito progetto di Test
Porfirio Tramontana - Android
142
TestDroid Recorder - Tutorial • Progetto di test generato … public void testRecorded() throws Exception { try { solo.waitForActivity("OrariProcida2011Activity"); solo.sleep(21500); assertTrue("Wait for button (text: OK) failed.", solo.waitForButton("OK", 20000)); solo.clickOnButton("OK"); solo.sleep(9000); assertTrue("Wait for spinner (index: 0) failed.", solo.waitForSpinner(0, 20000)); solo.pressSpinnerItem(0, 1); solo.sleep(6700); assertTrue( "Wait for button (id: com.porfirio.orariprocida2011.R.id.button4) failed.", solo.waitForButtonById( "com.porfirio.orariprocida2011.R.id.button4", 20000)); solo.clickOnButton((Button) solo .findViewById("com.porfirio.orariprocida2011.R.id.button4")); } catch (AssertionFailedError e) { solo.fail( "com.porfirio.orariprocida2011.test.OrariProcida2011ActivityTest2.testRe corded_scr_fail", e); throw e; } catch (Exception e) { solo.fail( "com.porfirio.orariprocida2011.test.OrariProcida2011ActivityTest2.testRe corded_scr_fail", e); throw e; } } …
Porfirio Tramontana - Android
143
TestDroid Recorder - Approfondimenti •
•
I test generati da TestDroid Recorder possono essere eseguiti automaticamente come qualsiasi altro test, senza ulteriore supporto di TestDroid Sessioni di Record/Stop ripetute consentono di generare più casi di test –
•
Ad ogni nuovo test l’applicazione viene reinstallata
Le istruzioni Sleep nel caso di test rispecchiano i reali intervalli di tempo tra gli eventi. Possono essere editati sia qui che direttamente nel caso di test –
Tempi troppo brevi potrebbero non consentire al sistema di evolvere in tempo prima dell’evento successivo
Porfirio Tramontana - Android
144
TestDroid Recorder - Approfondimenti
•
• • •
•
Tramite Append Command è possibile (dopo il recording e prima della generazione dei casi di test) editare i test aggiungendo comandi specifici oppure asserzioni sui valori dei campi visualizzati Tramite Add Method è possibile dare un nome ai test prima di registrarli Tramite Take Screenshot è possibile aggiungere un comando per salvare una schermata grafica all’interno del test stesso Smart Assert crea automaticamente asserzioni riguardanti la maggior parte delle etichette che riesce a trovare nella schermata a video Con Adjust Sleeps è possibile variare il tempo di sleep nei test
Porfirio Tramontana - Android
145
TestRecorder – un esempio completo • • •
Consideriamo un’applicazione molto semplice come esempio Simply Do è una semplice applicazione Android che consente di gestire azioni da svolgere, organizzate in liste. Dall’interfaccia principale è possibile: – –
•
vedere l’elenco di tutte le liste; aggiungere una nuova lista (semplicemente digitandone il nome e chiedendo di aggiungerla).
Selezionando una lista, è possibile: – – –
visualizzare tutte le azioni all’interno della lista aggiungere un’azione all’interno della lista (scrivendone il nome) segnare un’azione come già svolta (selezionandola): in questo caso l’azione sarà visualizzata in grigio e barrata. E’ possibile segnare nuovamente un’azione come non ancora svolta selezionandola ulteriormente
•
Dal menu è inoltre possibile eliminare tutte le azioni già svolte e ordinare le azioni secondo l’ordine prestabilito.
•
E’ possibile personalizzare l’applicazione tramite alcune voci disponibili dal menu (Settings). In particolare è possibile: – – – – –
Scegliere l’ordine di visualizzazione delle azioni (prima quelle non ancora effettuate – Active, oppure prima quelle evidenziate – Starred) Scegliere l’ordine di visualizzazione delle liste (alfabetico oppure lasciarle in ordine di immissione) Decidere se chiedere conferma ogni volta che si tenta di cancellare le azioni già effettuate Effettuare il backup sulla memoria locale Ripristinare le note salvate in uno dei backup precedenti.
Porfirio Tramontana - Android
146
TestRecorder – un esercizio • Testare l’applicazione Simply Do eseguendo un insieme di esecuzioni – Nell’ambito di TestDroid Recorder – Generando automaticamente al termine i corrispondenti test Junit rieseguibili – Cercando di provare l’applicazione in tutti i modi possibili, sulla base dei requisiti e delle strategie di progettazione dei casi di test note – Al termine verranno misurate (con Emma) e valutate le coperture raggiunte, per avere un’idea dell’efficacia dei test generati – Si cerchi di tenere conto del tempo impiegato per eseguire i vari passi del processo Porfirio Tramontana - Android
147
Valutazione dell’efficacia del test • Come confronto rispetto a Simply Do, consideriamo la copertura che ho ottenuto io con una sessione di test durata 8 minuti
Porfirio Tramontana - Android
148
Robotium Recorder • Un altro ambiente che supporta il capture & replay è Robotium Recorder • http://robotium.com/products/robotium-recorder
– Robotium Recorder si basa sulle stesse librerie e sulla stessa architettura di TestDroid – Ha meno funzionalità ma è più stabile grazie all’utilizzo della classe ExtSolo di Robotium – Un tutorial esauriente è all’indirizzo: • http://robotium.com/pages/user-guide
Porfirio Tramontana - Android
149
Robotium Recorder • Robotium Recorder è disponibile, in versione gratuita, all’indirizzo: – http://robotium.com/pages/free-trial
• Anche Robotium Recorder è disponibile sotto forma di estensione di Eclipse, scaricabile da: – http://recorder.robotium.com/updates
• E’ possibile, però, catturare (e salvare come test Junit) solo 5 casi di test
Porfirio Tramontana - Android
150
Istruzioni per l’esercizio di testing con TestDroid 1/2 1. Installare Simply Do scompattando il .zip ed importandolo come progetto Eclipse 2. Creare una macchina virtuale con le caratteristiche in figura e avviarla 3. Registrare una serie di esecuzioni con TestDroid Recorder sull’emulatore Porfirio Tramontana - Android
151
Istruzioni per l’esercizio di testing con TestDroid 2/2 • Far generare automaticamente i test case a TestDroid Recorder • Rieseguire i casi di test per controllare se la loro esecuzione va a buon fine –
–
•
Problemi nella riesecuzione potrebbero essere dovuti a click troppo veloci (TestDroid Recorder potrebbe avere reazioni lente, talvolta: meglio testare con calma) Eventualmente, è possibile valutare piccoli difetti nel test generato e ripararli eseguendo il debug del caso di test
Misurare la copertura (vedi istruzioni)
Porfirio Tramontana - Android
152
Misurare la copertura (dell’esercizio con TestDroid) 1) Avviare l'emulatore 2) Disinstallare SimplyDo 3) Spostarsi nella cartella del sorgente della applicazione da testare (\SimplyDo) Sotto windows, è preferibile che le cartelle non abbiano spazi
4) [percorso di ant\bin]\ant clean ant può essere scaricato da http://it.apache.contactlab.it//ant/binaries/apache-ant-1.9.4-bin.zip
5) [Percorso di android\tools]\android update project --path . --target android-10 [Percorso di android\tools] potrebbe essere D:\adt-bundle-windows-x86-20140702\sdk\tools Per generare il file build.xml necessario ad ant
6) Spostarsi nella cartella del caso di test (\SimplyDoTest) 7) [percorso di ant\bin]\ant clean Porfirio Tramontana - Android
153
Misurare la copertura 8) [Percorso di android\tools]\android update test-project -p .\ --main ..\SimplyDo Se SimplyDo si trova in una posizione diversa sul disco al posto di ..\SimplyDo mettere il percorso esatto di SimplyDo (utilizzato al punto 3) Per creare un file build.xml per il progetto di test collegandolo a quello dell’applicazione
9) Nella cartella del caso di test eseguire : [percorso di ant\bin]\ant emma debug install test 10) Al termine del caso di test, nella cartella \SimplyDo\bin saranno disponibili i risultati di copertura in vari formati (html, xml, txt) 11) Inviarmi il progetto di test con tutti i file di copertura (è sufficiente zippare le due cartelle SimplyDo e SimplyDoTest)
Porfirio Tramontana - Android
154
Istruzioni per l’esercizio di testing con Robotium Recorder 1/2 • La prima parte dell’esercizio si svolge sulla macchina di test approntata presso il Laboratorio di Ingegneria del Software 1. Accedere alla macchina (fisicamente o virtualmente) 2. Avviare la macchina virtuale Robotium Recorder (se non è già avviata) 3. Avviare Eclipse 4. Avviare un emulatore chiamato test (Api Level 15)
Porfirio Tramontana - Android
155
Istruzioni per l’esercizio di testing con Robotium Recorder 2/2 5. Per ogni applicazione da testare 1. Dal menu contestuale scegliere Robotium Recorder/New Robotium Test 2. Scegliere l’applicazione e dare un nome al test 3. Avviare New Robotium Test 4. Operare sull’emulatore interagendo con l’applicazione sotto test 5. Al termine delle operazioni, premere Stop Robotium Test 6. Premere Save
Porfirio Tramontana - Android
156
Progetto di test e riesecuzione •
In questo modo verrà così creato un progetto di test che potrà essere subito rieseguito e, successivamente, modificato – Per rieseguire il test è necessario azzerare i dati dell’applicazione con Clear Data dall’applicazione Settings/Apps sul’emulatore – Duplicare il progetto di test prima di modificarlo per poter tenere nota di tutta la sua evoluzione – E’ possibile calcolare la copertura in maniera completamente analoga al caso precedente • L’unica differenza consiste nello specificare android-15 anziché android-10 come target
– Per poter continuare il proprio lavoro a casa, è opportuno portare una memoria usb con almeno 5 GB liberi che conterrà la macchina virtuale (in formato Oracle VM Virtual Box) sulla quale si è condotta la prima parte dell’esperimento Porfirio Tramontana - Android
157
Altri processi di testing • • • • • •
Performance testing Stress testing Security Testing Compatibility Testing Usability Testing Accessibility Testing
Porfirio Tramontana - Android
161
Tracce proposte • Il progetto Android da realizzare è a scelta degli studenti • Si raccomanda la realizzazione di una app che possa sfruttare alcune delle peculiarità delle applicazioni mobili – Sensori, connessioni, servizi, touchscreen, database locale, interazione con i servizi telefonici …
• Nel caso in cui si realizzi una applicazione distribuita (ad esempio client/server) ai fini del giudizio verrà tenuta in conto primariamente la complessità e la qualità del lato client (android) Porfirio Tramontana - Android
163
Applicazioni possibili (quest’elenco viene pubblicato a puro titolo di esempio e di possibile ispirazione, ma ogni gruppo può scegliere liberamente una applicazione da realizzare)
•
•
•
•
Ombrello, app che prende in input orario e luogo di partenza e di arrivo, e mezzo di locomozione in un viaggio/spostamento e cerca di quantificare la probabilità che sia necessario l’ombrello, interrogando appositi servizi meteo Luna Rossa, app che, noti dati astronomici sulla posizione relativa di sole, luna e osservatore, cerchi di indovinare se si verificherà una luna rossa (ad esempio luna sull’orizzonte ad ovest poco dopo il tramonto del sole) Controllo Volume, app che controlla il volume della suoneria del telefono in base ad alcuni fattori ambientali (rumore di fondo, prossimità, illuminazione) Tombola da Bar, app che consente di organizzare una partita ad un gioco come la tombola (ma va bene anche un qualsiasi altro gioco con molti giocatori, ad esempio un quiz o un sorteggio) nel quale ogni giocatore ha un proprio client Android e, eventualmente, c’è un server (o servizio) per il mantenimento dello stato della partita
Porfirio Tramontana - Android
164
Applicazioni possibili • •
•
•
Caccia Al Tesoro, estensione dell’esempio visto al corso, con la gestione della coordinazione tra diversi giocatori che giocano in contemporanea Campo Minato nel mondo reale, nel quale il client Android piazza delle «mine» in punti geografici e il giocatore deve correre da un punto all’altro mantenendo attivo il gps e evitando di avvicinarsi troppo ad alcuna delle «mine» Pac Man nel mondo reale: scopo del gioco è quello di passare per tutti i punti di interesse (come le palline di un Pac Man) il più velocemente possibile (percorrendo il minor spazio possibile). Questo «gioco» può avere anche connotazione culturale, aiutando il turista a percorrere un centro storico osservando tutti i punti d’interesse Silenzio, app che abbassa il volume della suoneria (ed eventualmente attiva la vibrazione) in corrispondenza del rilevamento di luoghi specifici (ad esempio una un’aula universitaria) oppure una altra condizione (ad esempio un determinato orario)
Porfirio Tramontana - Android
165
Applicazioni possibili •
•
•
Giochi con i sensori, app che chiede all’utente di risolvere particolari task che hanno a che fare con i sensori (ad esempio tenere il telefono con una certa inclinazione data, muoverlo con una certa velocità, portarlo ad una certa distanza da un ostacolo, allinearlo ad una certa direzione cardinale, etc.) Giochi di sincronizzazione: come i precedenti, ma nei quali lo scopo dei due giocatori è quello di effettuare operazioni uguali nello stesso istante. La sincronizzazione può essere ottenuta implementando un protocollo peer to peer tra i client (ad esempio via bluetooth) o anche tramite un server (ad esempio un http server nel quale salvare semplici dati riguardanti lo stato) Giochi peer to peer a due giocatori, ad esempio giochi con le carte (sette e mezzo, briscola), dama, scacchi, tris, etc. La comunicazione può essere ottenuta implementando un protocollo peer to peer tra i client (ad esempio via bluetooth) o anche tramite un server (ad esempio un http server nel quale salvare semplici dati riguardanti lo stato)
• Porfirio Tramontana - Android
166
Applicazioni possibili •
Sveglia multifunzione, con alcune funzionalità particolari possibili, ad esempio: –
– –
Spegnimento della sveglia condizionato alla risposta ad una domanda (ad esempio una espressione aritmetica oppure un quiz che chieda quale è il motivo della sveglia stessa); Suono della sveglia in corrispondenza del raggiungimento di un certo livello di batteria (per evitare che la batteria sia scarica quando la sveglia dovrebbe suonare); Previsione da parte della sveglia della possibilità che la batteria si scarichi per l’ora della sveglia stessa (con tecniche di stima storica)
Porfirio Tramontana - Android
167