Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Appunti programmazione Android, Appunti di Programmazione Avanzata

Gli appunti, da me scritti, ripercorrono le lezioni del corso "COMPUTAZIONE PERVASIVA" presso l'università degli studi del sannio. L'argomento del corso è la programmazione Android.

Tipologia: Appunti

2016/2017

Caricato il 24/01/2022

di-martino-andrea
di-martino-andrea 🇮🇹

3

(1)

2 documenti

1 / 41

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
CICLO DI VITA DI UN’APPLICAZIONE
Un’attività viene lanciata, poi si invoca il metodo onCreate() non appena si attiva
l’applicazione. Poi viene lanciato onStart(), poi onResume() quindi l’attività è in esecuzione.
Quando succede qualcosa, l’attività và in foreground e quindi in pausa con onPause().
Quando l’attività non è più visibile allora va stoppata e poi può essere chiusa o dall’utente o
dal sistema. Da onPause() può essere riabilitata e può tornare ad onStart()
Per fare in modo che i nostri dati della app non vengano persi dobbiamo fare in modo che
in uno degli stati che vengono eseguiti, onPause(), onStop() oppure onDestroy(), salvino il
contenuto per poterlo riutilizzare in seguito. Facciamo ciò mediante sharedPreferences.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29

Anteprima parziale del testo

Scarica Appunti programmazione Android e più Appunti in PDF di Programmazione Avanzata solo su Docsity!

CICLO DI VITA DI UN’APPLICAZIONE

Un’attività viene lanciata, poi si invoca il metodo onCreate() non appena si attiva l’applicazione. Poi viene lanciato onStart(), poi onResume() quindi l’attività è in esecuzione. Quando succede qualcosa, l’attività và in foreground e quindi in pausa con onPause(). Quando l’attività non è più visibile allora va stoppata e poi può essere chiusa o dall’utente o dal sistema. Da onPause() può essere riabilitata e può tornare ad onStart() Per fare in modo che i nostri dati della app non vengano persi dobbiamo fare in modo che in uno degli stati che vengono eseguiti, onPause(), onStop() oppure onDestroy(), salvino il contenuto per poterlo riutilizzare in seguito. Facciamo ciò mediante sharedPreferences.

ANDROID MANIFEST

E’ un manifesto XML dell’applicazione che serve a specificare cosa può fare un’app e specifica i vari campi che la caratterizzano. Ecco i campi più importanti: Il tag è stato già incontrato parecchio nel corso di questa guida. Necessario ogni volta che la nostra applicazione deve avviare comunicazioni o accessi particolari, richiede almeno che la definizione dell’attributo android:name, che specifica esattamente il tipo di permission richiesta. Finora l’abbiamo incontrato in:  accesso alla Rete: android.permission.INTERNET;  localizzazione: android.permission.ACCESS_FINE_LOCATION e android.permission.ACCESS_COARSE _LOCATION;  storage esterno: android.permission.WRITE_EXTERNAL_STORAGE;  comunicazioni telefoniche: android.permission.CALL_PHONE e android.permission.READ_PHONE_STATE;  Content Providers : vari casi (contatti, calendario, chiamate, etc…). Infine, <uses-feature> è la risposta alla frammentazione hardware e software del sistema Android. Permette di specificare di quali caratteristiche hardware o software l’applicazione ha bisogno per funzionare. Gli attributi di cui dispone sono:  android:name: una stringa che definisce quale dotazione del dispositivo è necessaria affinchè l’applicazione funzioni correttamente. A livello hardware, si potrebbe avere bisogno di verificare se l’equipaggiamento elettronico del device comprende tecnologie come Bluetooth o NFC, nonchè dispositivi come la videocamera o lo schermo multitouch;  android:required: è un valore booleano. Se impostato a true indica che la caratteristica è assolutamente obbligatoria per il funzionamento dell’app; altrimenti indica che la feature è fortemente consigliata ma non obbligatoria;  android:glEsVersion: indica la versione delle librerie OpenGL ES richiesta dall’app.  android:icon: si utilizza per assegnare un’immagine all’icona dell’app, tale immaggine va inserito nelle risorse (drawable);  android:label: assegna il nome che verrà riportato come titolo;  android:supportRTL: dichiare se l’app supporta il layout da destra a sinistra;  android:theme=”@style/AppTheme”: modifica il tema dell’app;  activityandroid:nome=”MainActivity”: è il riferimento dove è scritto il codice di cosa vogliamo far fare alla nostra app e può essere utilizzato in combinazione con altre categoria per altri scopi specifici;  activity android:nome=”android.intent.category.LAUNCHER” fornisce ulteririori informazioni in merito all’azione da eseguire.

La gestione delle permission è cambiata radicalmente in Android 6 (ovvero dalla versione 23 delle API). A partire da questa versione, infattti, le permission dangerous dovranno essere accettate dall’utente al momento del primo utilizzo e tale permesso potrà essere revocato in qualsiasi momento, accedendo alle impostazioni dell’app. Per sviluppare app moderne, quindi, è necessario gestire le permission a runtime , verificando se esse siano revocate o meno, nonchè richiedendo all’utente di abilitarle. La classe ContextCompat , inclusa nella libreria di supporto, mette a disposizione un metodo per effettuare questo tipo di controllo: int statoPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION); dove this rappresenta la nostra Activity (che fungerà da Context). Il valore della variabile intera statoPermission sarà confrontato con le costanti PackageManager.PERMISSION_GRANTED oppure PackageManager.PERMISSION_DENIED che equivalgono, rispettivamente, alla concessione del permesso o al suo diniego. Dovremo verificare la disponibilità di una permission prima di utilizzare il metodo che ne ha bisogno, e qualora essa non fosse disponibile dovremo chiedere all’utente di acconsentire lanciando un apposito Intent. Per far comparire una finestra di dialogo che richieda l’accettazione della permission. Abbbiamo così passato un array di stringhe contenente le permission che dovranno essere accettate, ed una costante intera che noi abbiamo chiamato ID_RICHIESTA_PERMISSION, che permetterà di identificare la specifica richiesta che abbiamo inoltrato. Il risultato sarà inviato inviato ad un metodo che noi predisporremo: Si realizza la struttura di controllo da usare per far sì che l’utente acconsenta a svolgere attività soggette ad una permission dangerous. L’utente sarà sempre padrone di revocare le permission dangerous concesse, semplicemente agendo sul controllo che apparirà tra le impostazioni dell’app.

LAYOUT DI APP ANDROID

Un’Activity ha bisogno di un volto, di un suo aspetto grafico. La struttura grafica di un’Activity prende il nome di Layout.

L’interfaccia grafica

Le interfacce utente in Android possono essere create in modo procedurale o dichiarativo. Android permette la creazione di interfacce sia procedurali sia dichiarative: possiamo creare un’interfaccia utente completamente in codice Java (metodo procedurale) oppure possiamo creare l’interfaccia utente attraverso un descrittore XML (metodo dichiarativo). Android inoltre permette anche un approccio ibrido, in cui si crea un’interfaccia in modo dichiarativo e la si controlla e specifica in modo procedurale (si richiama il descrittore XML da codice e si continua a lavorare da lì). Nella prassi, su Android un layout viene progettato in XML , in una modalità che ricorda molto l’uso di HTML per le pagine web. Gli IDE offrono strumenti visuali per disegnare layout con approccio drag-and-drop e visualizzazioni di anteprima molto utili.

Tipi di Layout

Nel framework Android sono stati definiti vari tipi di layout ma ce ne sono tre di utilizzo molto comune che permettono di affrontare ogni situazione:

  1. LinearLayout : contiene un insieme di elementi che distribuisce in maniera sequenziale dall’alto verso il basso (se definito con orientamento verticale) o da sinistra a destra (se ha orientamento orizzontale, il valore di default).
  2. TableLayout : altro layout piuttosto semplice, inquadra gli elementi in una tabella e quindi è particolarmente adatto a mostrare strutture regolari suddivise in righe e colonne.
  3. RelativeLayout : sicuramente il più flessibile e moderno. Adatto a disporre in maniera meno strutturata gli elementi. Essendo “relative” gli elementi si posizionano in relazione l’uno all’altro o rispetto al loro contenitore, permettendo un layout fluido che si adatta bene a display diversi.

Elementi comuni nei layout

Gli attributi XML utilizzati per la maggior parte proverranno da un namespace avente URI http://schemas.android.com/apk/res/android. Per questo motivo quando definiremo layout in un progetto Android il nodo root che conterrà tutti gli elementi mostrerà al suo interno la dichiarazione il name space e darà senso al prefisso android: che verrà usato per tutti gli attributi nel file. Secondo aspetto comune non solo ai layout ma anche a tutti gli elementi in essi contenuti, la presenza obbligatoria di due attributi: layout_width e layout_height , che definiscono la capacità dell’elemento di estendersi, rispettivamente, in larghezza (width) o altezza (height). Il loro valore può essere una dimensione, espressa in dp, come già spiegato, o una costante da scegliere tra:  wrap_content : l’elemento sarà alto o largo a sufficienza per includere il suo contenuto;  match_parent : l’elemento si estenderà in altezza o in larghezza fino a toccare il suo contenitore.

VIEW

Con questo termine intendiamo un qualunque elemento che appare in un’interfaccia utente e che svolge due funzionalità :  mostra un aspetto grafico;  gestisce eventi relativi all’interazione con l’utente. Una classe derivata da View è ViewGroup. Esso è, al contempo, un tipo di View e un contenitore di altre View. Tanto per fare un esempio di ViewGroup pensiamo ai layout, sono tipici raggruppatori di View.

Classificazione di View

Tutto ciò che tratteremo come un controllo utente in Android sarà direttamente o indirettametne discendente di una View. Le tipologie di View da presentare si articoleranno per lo più in tre categorie:  i layout di cui si è discusso nei precedenti capitoli;  i controlli utente che renderanno le nostre applicazioni interattive. Il loro utilizzo, spiegato a breve, si snoderà tra posizionamento nei layout e configurazione dei loro gestori di evento;  gli AdapterView sono delle View, generalmente nello stesso package dei controlli utente, che collaborano nella realizzazione del pattern Adapter.

View e id

Prima di tutto gli id. Nei file di risorse, gli attributi id hanno un valore definito come @+id/ identificatore dove per identificatore si intende il nome dell’id scelto dall’utente. Il simbolo + apposto dopo la @ indica che se l’id con quel nome non è stato ancora definito nel sistema sarà definito per l’occasione.

Gestione degli eventi

La gestione degli eventi viene realizzata con il meccanismo dei listener. I tre punti cardine sono:

  1. il recupero di un riferimento alla View della quale verranno monitorati gli eventi;
  2. la definizione di un oggetto (anonimo in questo caso) che contiene un metodo onClick definito appositamente per gestire l’evento di click;
  3. la registrazione del listener tramite un metodo setter affinché il pulsante sappia chi è l’oggetto a cui delegare la gestione dei click.

CONTROLLI UTENTE

Discendono dalla classe View , ma quali sono tra essi i più comuni?  TextView : la classica label. Serve a rappresentare del testo fisso;  EditText : corrisponde all’inputbox di altre tecnologie. Viene usata per permettere l’inserimento del testo. Mediante attributi XML può essere adattata alle proprie necessità. Molto utile è android:inputType i cui valori definiscono i formati più comuni di input (date, password, testo, etc.);  Button : è il pulsante. La casistica più comune comporterà la gestione dell’evento click per attivare una qualche reazione nell’Activity;  CheckBox : come ci si aspetta definisce un classico flag che può essere attivato o disattivato. Nel codice Java leggeremo il suo stato (checked o unchecked) mediante un valore booleano;  Radio : esistono i radiobutton come in ogni altra tecnologia per interfacce utente. Vengono solitamente usati per definire valori alternativi tra loro come il sesso di una persona (maschio/femmina), possesso di facoltà (automunito Sì/No), etc. Questi non sono che alcuni esempi: come si può immaginare, un elenco esaustivo avrebbe dimensioni imponenti. Tuttavia, si può fare riferimento alla documentazione ufficiale per ulteriori approfondimenti.

CREARE MENU

Le tipologie di menu più comuni in Android sono due:  Options menu : è il menu principale dell’applicazione e contiene voci riguardanti operazioni di interesse generale nella vita dell’app.  Context Menu : è un menu invocabile su un singolo componente dell’interfaccia utente. Le voci richiamabili serviranno ad avviare operazioni sull’elemento su cui è stato richiesto il menu. Normalmente un menu contestuale viene attivato con un click lungo su un componente del layout.

Definire la struttura del menu

Il primo passo per aggiungere un menu di qualsiasi tipo alla nostra Activity è crearne la struttura. In proposito, va sempre tenuto a mente che i menu sono risorse. Quindi il loro layout va definito nella sottocartella res/menu. Questo è il punto di partenza della creazione di un menu. Per poter creare un menu minimale, sono sufficienti due tag:

che definisce il menu nel suo complesso e che dichiara la singola voce del menu. Gli attributi impiegati nella configurazione sono due:

  1. id che, come vedremo, saranno molto importanti nella gestione delle voci del menu ;
  2. title che contiene una stringa che dà il titolo alla voce di menu.

ACTION BAR

Non si tratta solo di un “bordo”. In realtà, l’ActionBar può essere definita una “cornice”programmabile destinata ad ospitare opzioni di navigazione e di interazione di utilità più o meno comune all’intera applicazione, tra cui:  actions ossia pulsanti cliccabili per attivare azioni. Altro non sono in realtà che voci dell’Options Menu collocate sull’ActionBar;  navigazione con “tab”;  navigazione con menu a tendina;  campi di ricerca;  molto altro ancora.

Avere l’ActionBar disponibile

 l’Activity dovrà estendere ActionBarActivity;  il tema dell’Activity dovrà essere Theme.AppCompat o un derivato.

Comandi nell’ActionBar

Le actions, come già accennato, non sono altro che i comandi. Infatti nella visione più moderna della programmazione Android, l’ActionBar tende ad assorbire parte del ruolo degli Options Menu dando la possibilità di ospitarne le voci. Per farlo si dovrà solo mettere mano al layout del menu (reperibile nella cartella di risorse res/menu) impostando opportunamente il valore dell’attributo showAsAction, tra i seguenti: ifRoom mostra le icone sull’ActionBar compatibilmente con lo spazio disponibile never non mostra le voci del menu sull’ActionBar ma solo nell’Options Menu always il layout viene forzato a mostrare le voci in ActionBar. E’ un valore sempre sconsigliabile, meglio optare per ifRoom withText Oltre all’icona viene mostrato in ActionBar anche il testo, solitamente collegato all’attributo android:title

Navigazione “all’indietro”

Altra funzionalità che può essere introdotta da subito nella configurazione dell’ActionBar è il supporto alla navigazione all’indietro. L’immagine mostra, cerchiata in rosso, una piccola freccia verso sinistra accanto all’icona dell’applicazione. Questo elementino di interazione dovrebbe prendere il posto del pulsante hardware comunemente chiamato “Back” o “Indietro”.  nell’ AndroidManifest.xml , esattamente nel nodo dell’Activity che dovrà mostrare la frecciolina, si specificherà la parent Activity ossia l’Activity a cui si dovrà tornare:  nell’onCreate dell’Activity che mostra la frecciolina, si inserirà la seguente riga di codice: getActionBar().setDisplayHomeAsUpEnabled(true);

NOTIFICHE ANDROID

Si manifestano con una piccola icona che appare nella cosiddetta “Notification Area” e se ne può consultare il contenuto aprendo il “Notification drawer”, una zona “a scomparsa” sul display. Ci sono diversi aspetti che caratterizzano una notifica:

  1. titolo della notifica ( content title );
  2. icona grande ( large icon );
  3. contenuto della notifica ( content text );
  4. informazioni accessorie ( content info );
  5. icona piccola ( small icon ) che di norma appare anche nella barra del display;
  6. ora della notifica ( when ) impostata dal programmatore o di default dal sistema.

La prima notifica

Nonostante la molteplicità di aspetti che contraddistinguono una notifica, ve ne sono tre assolutamente obbligatori :  l’icona piccola;  il titolo;  il contenuto. Questi saranno configurati, rispettivamente, con i metodi setSmallIcon, setTitle e setContentText.

Le Dialog

Dialog è la superclasse di tutte le finestre di dialogo e ne rappresenta il tipo più duttile ma che lascia più lavoro al programmatore. L’esempio seguente mostra codice che può essere eseguito all’interno di un metodo dell’Activity: Dialog d=new Dialog(this); d.setTitle("Login"); d.setCancelable(false); d.setContentView(R.layout.dialog); d.show(); Ciò che succede è descritto qui di seguito:  istanziamo un oggetto di classe Dialog passando un riferimento al Context;  impostiamo un titolo, già proprietà della finestra stessa;  definiamo la finestra come modale richiedendo la sua non-cancellabilità mediante setCancelable. Ciò impedirà che toccando il display al di fuori della finestra di dialogo essa si chiuda;  assegnamo un layout alla finestra di dialogo come faremmo per un’Activity. Il layout si trova nella cartella res/layout , rappresenta un form ed è lo stesso impiegato per i controlli utente;  ultimo ma non meno importante, invochiamo il metodo show() senza il quale la finestra di dialogo non apparirà. Il click sui pulsanti sarà gestito mediante click listener. Allo scopo è importante dotare, nel layout, i pulsanti di appositi id.

Dialog già “pronte”

Parallelamente, Android offre tipi di finestre di dialogo, molto comuni, praticamente pronte all’uso. I principali:  AlertDialog : la più adattabile. Sfrutta una classe interna detta Builder per configurare i vari aspetti: AlertDialog.Builder builder=new AlertDialog.Builder(this); builder.setTitle("Attenzione!"); builder.setMessage("Operazione non valida!"); builder.show();  ProgressDialog è un derivato della AlertDialog pensato per lo più per ospitare indicatori di progresso sia in stile orizzontale (barra) che spinner (circolare). Può essere utilizzato in maniera molto agevole grazie alla versione statica del metodo show: ProgressDialog progress = ProgressDialog.show(this, "Attendere", "Scaricamento in corso...", true);

WEB VIEW

Una WebView è un tipo di View che permette di visualizzare pagine web. La sua utilità principale è quella di permettere di integrare una web application o più in generale un sito web nella propria applicazione. Per ottenere questo risultato si sono compiute tre semplici operazioni:

  1. si è creato un layout come il seguente:
  2. si è richiesto alla WebView, già nell’onCreate dell’Activity, di caricare l’indirizzo remoto: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.loadUrl("http://www.html.it"); }
  3. si è provveduto ad impostare nell’AndroidManifest.xml, all’interno direttamente del nodo , la permission per il collegamento ad Internet: <manifest xmlns:android="http://schemas.android.com/apk/res/android" ... ... <uses-permission android:name="android.permission.INTERNET"/> <application ... ...

ADAPTER E ADAPTER VIEW

Finora abbiamo apprezzato due modalità diverse per realizzare le varie parti delle nostre app:  design in XML , per layout e risorse, dall’approccio piuttosto visuale ma orientato alla definizione di parti statiche;  sviluppo in Java , fondamentale per le funzionalità dinamiche ma meno pratico per il disegno di porzioni di layout. Ma se dovessimo realizzare una “via di mezzo”: una visualizzazione iterativa di contenuti archiviati in strutture dati, potenzialmente variabili, come dovremmo comportarci?

Sarà sufficiente:  nel layout, sostituire la ListView con la GridView , assegnando un numero di colonne alla griglia:  nel codice Java semplicemente sostituire l’uso della classe ListView con GridView : @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); String[] nomi=new String[]{"Torino","Roma","Milano","Napoli","Firenze"}; ArrayAdapter adapter=new ArrayAdapter(this, R.layout.row,nomi); // sostituiamo ListView con GridView GridView gridView = (GridView) findViewById(R.id.gridview); gridView.setAdapter(adapter); }

Gestione degli eventi

Gli AdapterView hanno un altro ruolo molto importante: la gestione degli eventi. Come per tutte le View viene effettuato mediante il meccanismo dei listener. Un caso molto comune è la gestione del click su un elemento della lista, ciò che viene normalmente interpretato come selezione. Tornando all’esempio della GridView, se volessimo far visualizzare un Toast che notifica quale elemento è stato selezionato dovremmo inserire il seguente codice: GridView gridView = (GridView) findViewById(R.id.gridview); gridView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> av, View v, int pos,long id) { Toast.makeText(getApplicationContext(), "Selezionato "+citta[pos], Toast.LENGTH_LONG).show(); } }); La classe OnItemClickListener viene utilizzata allo scopo di gestire il click ed il suo metodo onItemClick conterrà il vero codice da attivare ad ogni selezione di elemento. I suoi parametri in input conterranno tutte le informazioni utili tra cui:  l’elemento su cui si è cliccato (il secondo, di classe View);  la posizione che ricopre nella struttura (il terzo parametro, di tipo int). All’interno del metodo onItemClick si vede come l’informazione della posizione è stata sfruttata per recuperare dalla struttura dati l’oggetto (citta[pos]).

SPINNER (MENU A TENDINA)

Comunque lo Spinner trova la sua utilità anche in contesti meno complessi in cui si può usare come normale campo form per selezionare un valore in un dato insieme.  si crea un array di risorse stringa in un file della cartella res/values e lo si completa con tutti i valori necessari: <string-array name="staticivili"> Divorziato/a Separato/a Coniugato/a Celibe/Nubile </string-array>  La risorsa sarà accessibile in XML mediante @array/staticivili  nel file di layout in cui si trova lo Spinner si effettua una modifica. Si aggiunge l’attributo android:entries e gli si assegna la risorsa di stringhe a cui accedere: Seguendo questi due semplici passi, nel layout troveremo lo spinner già popolato dei valori. Non è stato necessario apportare alcuna modifica nel codice Java e tantomeno istanziare direttamente un adapter.

FRAGMENT

I Fragment costituiscono senz’altro uno dei più importanti elementi per la creazione di una interfaccia utente Android moderna. Un Fragment è una porzione di Activity. Ma si faccia attenzione a comprenderne bene il ruolo. Non si tratta solo di un gruppo di controlli o di una sezione del layout. Può essere definito più come una specie di sub-activity con un suo ruolo funzionale molto importante ed un suo ciclo di vita.

Fragments e Activity

Definiamo subito il rapporto tra Fragments e Activity. Prima di tutto un Fragment non può vivere senza un’Actvity. Tipicamente nei nostri programmi creeremo più Fragments che si alterneranno nel layout mentre di Activity ne sarà sufficiente una (ma possono essere anche di più). Come detto il Fragment ha il suo ciclo di vita fortemente collegato con quello dell’Activity di appartenenza. La figura qui riportata mostra la sequenza di stati che scandiscono la vita del Fragment.