1. ITIS Max Planck di Lancenigo diVillorba (TV)
A.S. 2013-2014
Prof. PAOLOTOSATO
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Programmazione mobile: ANDROID
Terza lezione: gestione eventi e memorizzazione dati
2. 30/04/2014 2
• Gestione degli eventi e dei widget
• Memorizzazione dei dati
• Accesso al file system
• Database
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Indice
3. 30/04/2014 3
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Gestione degli eventi
Metodi callbackVs event listener
I metodi di callback
• Formato: onTipoEvento() (ad esempio: onTouchEvent() ).
• Eseguiti automaticamente ogni volta che un widget viene selezionato (ad
esempio quando un bottone viene toccato).
• Per gestirli è necessario estendere il widget e ridefinire il metodo (un incubo
nel caso si abbiano diversi widget nell’interfaccia).
Event listener
• Formaro: setOnTipoEventoListener() (as esempio: setOnClickListener() )
• Si abbinano meglio con i layout definiti attraverso file XML.
• Nel caso di GUI non troppo complesse, la classe Activity può essere lei stessa
event listener.
4. 30/04/2014 4
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Gestione degli eventi
Metodi di callback: esempio
public class MyButton extends Button {
public MyButton(Context context) { //Costruttore
super(context);
}
public boolean onTouchEvent(MotionEvent event) { // Metodo callback
super.onTouchEvent(event);
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
Toast toast =Toast.makeText(getContext(), "Bottone cliccato!",Toast.LENGTH_SHORT);
toast.show();
return true;
}
return false;
}
}
5. 30/04/2014 5
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Gestione degli eventi
Event listener: esempio 1
public class DemoActivity extends Activity implements OnClickListener {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
Button bottone1 = (Button) findViewById(R.id.bottone1);
Button bottone2 = (Button) findViewById(R.id.bottone2);
bottone1.setOnClickListener(this); bottone2.setOnClickListener(this);
}
public void onClick(View v) {
String messaggio=“”;
if (v.getId() == R.id.bottone1) {
messaggio = "Hai cliccato il bottone 1!";
} else if (v.getId() == R.id.bottone2) {
messaggio = "Hai cliccato il bottone 2!";
}
Toast toast =Toast.makeText(this, messaggio,Toast.LENGTH_SHORT);
toast.show();
}
}
6. 30/04/2014 6
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Gestione degli eventi
Event listener: esempio 2
public void onCreate(Bundle savedInstanceState) {
bottone1.setOnClickListener(new OnClickListener() { // Classi innestate anonime di Java
public void onClick(View v) {
clickSuBottone1();
}
});
bottone2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
clickSuBottone2();
}
});
}
private void clickSuBottone1() {
Toast toast =Toast.makeText(this, "Hai cliccato il bottone 1!",Toast.LENGTH_SHORT);
toast.show();
}
7. 30/04/2014 7
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Gestione degli eventi
Gli eventi più importanti
Click
• Metodo sul widget: setOnClickListener()
• Interfaccia per il gestore: View.OnClickListener.
• Metodo da implementare: onClick(View view).
Click lungo (si mantiene la pressione per qualche istante)
• Metodo sul widget: setOnLongClickListener().
• Interfaccia per il gestore: View.OnLongClickListener.
• Metodo da implementare: onLongClick(View view).
Tocco (per rilevare un tocco qualsiasi su un componente)
• Metodo sul widget: setOnTouchListener().
• Interfaccia per il gestore: View.OnTouchListener.
• Metodo da implementare: onTouch(View view, MotionEvent event).
8. 30/04/2014 8
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Gestione degli eventi
Gli eventi più importanti
Digitazione
• Metodo sul widget: setOnKeyListener().
• Interfaccia per il gestore: View.OnKeyListener.
• Metodo da implementare: onKey(View view, int keyCode, KeyEvent event).
Focus
• Metodo sul widget: setOnFocusChangeListener().
• Interfaccia per il gestore: View.OnFocusChangeListener.
• Metodo da implementare: onFocusChange(View view, boolean hasFocus).
9. Gestione degli eventi
30/04/2014 9
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Un esempio con KeyListener
EditText editNome = (EditText) findViewById(R.id.editText1);
editNome.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View view, int keyCode, KeyEvent event) {
char c = event.getDisplayLabel();
String action = null;
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
action = "DOWN";
break;
case KeyEvent.ACTION_UP:
action = "UP";
break;
}
String messaggio = "Tasto: codice " + keyCode + " (" + c + "), azione " + action;
TextView logArea = (TextView) findViewById(R.id.textView4);
logArea.setText(messaggio);
return false; // Se “return true” non viene visualizzato
} // il carattere nell’EditText
});
10. 30/04/2014 10
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Memorizzazione dei dati: file system
Storage interno
• Porzione di file system esclusivamente assegnata
all’applicazione.
Storage esterno
• Solitamente una scheda che può all’occorrenza essere
rimossa e sostituita, ma non è detto.
11. 30/04/2014 11
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Memorizzazione dei dati: file system
Storage interno
• Per ottenere uno stream di output
public FileOutputStream openFileOutput(String name, int mode) throws FileNotFoundException
• Mode
Context.MODE_PRIVATE Rende il file privato all'applicazione(crea il file se non esiste)
Context.MODE_APPEND Agisce in append sul file specificato
• Per ottenere uno stream di input
public abstract FileInputStream openFileInput(String name) throws FileNotFoundException
• Per cancellare un file: public boolean deleteFile(Stringname)
• Per elencare i file nell’area riservata all’applicazione: public String[] fileList()
12. 30/04/2014 12
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Memorizzazione dei dati: file system
Storage esterno
• Controllare se disponibile: public static String getExternalStorageState()
• Environment.MEDIA_MOUNTED disponibile in lettura e scrittura
• Environment.MEDIA_MOUNTED_READ_ONLY disponibile solo in lettura
• Environment.XXX storage esterno non disponibile
• Per ottenere la radice dello storage esterno
public static File getExternalStorageDirectory()
• Si sconsiglia di creare file direttamente nella radice dello storage. Android
infatti organizza il suo storage esterno con una serie di directory standard
(Music per la musica, Download per i file scaricati, ecc.).
13. Memorizzazione dei dati: file system
30/04/2014 13
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Storage interno
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
Button butSalva = (Button) findViewById(R.id.button2);
Button butCarica = (Button) findViewById(R.id.button1);
butSalva.setOnClickListener(this);
butCarica.setOnClickListener(this);
/*
Dov'è lo storage interno dell'applicazione? (In Eclipse: DDMS File Explorer)
/data/data/<package applicazione>/files
*/
Log.i("FileDemo", "Directory: " + getFilesDir().getAbsolutePath());
}
14. Memorizzazione dei dati: file system
30/04/2014 14
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
public void onClick(View v) {
if (v.getId() == R.id.button1) {
carica("testo.txt");
} else if (v.getId() == R.id.button2) {
salva("testo.txt");
}
}
private void salva(String filename) {
EditText editNome = (EditText) findViewById(R.id.editText1);
EditText editCognome = (EditText) findViewById(R.id.editText2);
RadioGroup radioSesso = (RadioGroup)findViewById(R.id.radioGroup1);
int idSesso = radioSesso.getCheckedRadioButtonId();
Persona p = new Persona(editNome.getText().toString(),
editCognome.getText().toString(), idSesso);
ObjectOutputStream fOUT = null;
15. Memorizzazione dei dati: file system
30/04/2014 15
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
try {
fOUT = new ObjectOutputStream(openFileOutput(filename, MODE_PRIVATE));
fOUT.writeObject(p);
fOUT.flush();
Toast.makeText(this,"Campi salvati",Toast.LENGTH_LONG).show();
} catch (IOException e) {
Log.e("FileDemo", "Impossibile salvare il file", e);
Toast.makeText(this,"Errore", Toast.LENGTH_LONG).show();
} finally {
if (fOUT != null) {
try {
fOUT.close();
} catch (IOException e2) {}
}
}
}
16. Memorizzazione dei dati: file system
30/04/2014 16
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
private void carica(String filename) {
Persona p = null;
ObjectInputStream fIN = null;
try {
fIN = new ObjectInputStream(openFileInput(filename));
p = (Persona) fIN.readObject();
Toast.makeText(this,"Testo caricato",Toast.LENGTH_LONG).show();
} catch (FileNotFoundExceptione2) {;
Toast.makeText(this,"Utente non trovato",Toast.LENGTH_LONG).show();
} catch (Exception e2) {
Log.e("FileDemo", "Impossibile aprire il file", e2);
Toast.makeText(this,"Errore", Toast.LENGTH_LONG).show();
17. Memorizzazione dei dati: file system
30/04/2014 17
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
} finally {
if (fIN != null) {
try {
fIN.close();
} catch (IOException e3) {}
}
}
EditText editNome = (EditText) findViewById(R.id.editText1);
EditText editCognome = (EditText) findViewById(R.id.editText2);
RadioGroup radioSesso = (RadioGroup)findViewById(R.id.radioGroup1);
editNome.setText(p.getNome());
editCognome.setText(p.getCognome());
radioSesso.check(p.getSesso());
}
18. Memorizzazione dei dati: database
30/04/2014 18
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Android comprende un piccolo DBMS, che gli sviluppatori possono
richiamare per salvare ed organizzare i dati delle loro applicazioni.
Perché utilizzare un DBMS?
• Fatica risparmiata, sicurezza ed efficienza.
• Richiede però una conoscenza base di SQL.
Il DBMS integrato in Android è SQLite (Open Source)
• Scritto in C e funziona su Linux, Mac OS X e Windows.
• Il sito di riferimento per SQLite è disponibile all’indirizzo:
http://www.sqlite.org/
19. Memorizzazione dei dati: database
30/04/2014 19
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Ogni applicazione crea ed utilizza uno o più database in maniera esclusiva.
Database creati da un’applicazione non possono essere letti da altre
applicazioni.
Per utilizzare un database:
• Estendere la classe android.database.sqlite.SQLiteOpenHelper ed
implementare i metodi onCreate() e onUpdate().
• Sulla classe Helper si possono chiamare i metodi
• getReadableDatabase() per accedere al database in sola lettura
• getWritableDatabase() per accedere al database in scrittura,
per inserire, aggiornare o cancellare record dalle tabelle.
20. Memorizzazione dei dati: database
30/04/2014 20
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Operazioni di aggiornamento
public long insert(String table, String nullColumnHack, ContentValues values)
SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("nome", "Mario");
values.put("cognome", "Rossi");
// ID del record appena creato, oppure -1 se il record non è stato creato
long id = db.insert(“utenti", null, values);
21. 30/04/2014 21
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Memorizzazione dei dati: database
Operazioni di aggiornamento
public int update(String table, ContentValues values, String whereClause,
String[] whereArgs)
SQLiteDatabase db = mioDatabaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(“nome", “Paolo");
String whereClause = "nome = ? AND cognome = ?";
String[] whereArgs = { "Mario", "Rossi" };
// Sia whereClause che whereArgs possono essere null
int r = db.update(“utenti", values, whereClause, whereArgs);
22. Memorizzazione dei dati: database
30/04/2014 22
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Operazioni di aggiornamento
public int delete(String table, String whereClause, String[] whereArgs)
SQLiteDatabase db = mioDatabaseHelper.getWritableDatabase();
String whereClause = "_id = ?";
String[] whereArgs = { "1" };
int r = db.delete("agenda", whereClause, whereArgs);
23. Memorizzazione dei dati: database
30/04/2014 23
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Operazioni di aggiornamento: metodo generale
SQLiteDatabase db = mioDatabaseHelper.getWritableDatabase();
db.execSQL("DROPTABLE agenda");
Operazione di selezione
public Cursor query(String table, String[] columns, String selection, String[]
selectionArgs, String groupBy, String having, String orderBy)
Oppure (molto più semplicemente)
SQLiteDatabase db = mioDatabaseHelper.getReadableDatabase();
String query = “SELECT _id FROM utentiWHERE cognome = ? ORDER BY _id ASC”;
String[] selectionArgs = { "Rossi" };
Cursor cursor = db.rawQuery(query, selectionArgs);
24. Memorizzazione dei dati: database
30/04/2014 24
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
I cursori
Sono gli oggetti di Android che permettono di navigare all’interno di un result set.
Il cursore permette di ottenere il numero di righe restituite dalla query
int count = cursor.getCount();
e muoversi all’interno del result set
• public boolean moveToNext()
• public boolean moveToFirst()
• public boolean moveToLast()
• public boolean moveToPrevious()
• public boolean moveToPosition(int position)
25. 30/04/2014 25
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
Memorizzazione dei dati: database
String[] columns = { "_id", "nome", "cognome" };
String orderBy = "_id ASC";
Cursor cursor = db.query("agenda", columns, null, null, null, null, orderBy);
while (cursor.moveToNext()) {
long id = cursor.getLong(0);
String nome = cursor.getString(1);
String cognome = cursor.getString(2);
}
I cursori
26. Esempio: classe Helper
public class MyDatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "mydb";
private static final int DB_VERSION= 1;
public MyDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
// Richiamato quando il database è già presente sul sistema,
// ma stando al numero di versione richiesta, risulta obsoleto
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Aggiornamento delle tabelle
}
Memorizzazione dei dati: database
30/04/2014 26
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
27. Memorizzazione dei dati: database
30/04/2014 27
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
// Richiamato quando il database deve essere creato per la prima volta,
// cioè appena l’applicazioneè stata installata
public void onCreate(SQLiteDatabase db) {
String sql = "";
sql += "CREATETABLE utenti (";
sql += " _id INTEGER PRIMARY KEY,"; // campo di tipo contatore
sql += " nomeTEXT,";
sql += " cognomeTEXT,";
sql += " sesso INTEGER)";
db.execSQL(sql);
}
}
28. Memorizzazione dei dati: database
30/04/2014 28
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
public class MainActivity extends Activity implementsOnClickListener {
private MyDatabaseHelper myDatabaseHelper;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myDatabaseHelper = new MyDatabaseHelper(this);
setContentView(R.layout.mylayout);
// …
}
public void onClick(View v) {
if (v.getId() == R.id.button1) {
caricaDB();
} else if (v.getId() == R.id.button2) {
salvaDB();
}
}
Esempio:Attività
29. Memorizzazione dei dati: database
30/04/2014 29
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
private void salvaDB() {
EditText editNome = (EditText) findViewById(R.id.editText1);
EditText editCognome = (EditText) findViewById(R.id.editText2);
RadioGroup radioSesso = (RadioGroup)findViewById(R.id.radioGroup1);
int idSesso = radioSesso.getCheckedRadioButtonId();
SQLiteDatabase db = myDatabaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("nome", editNome.getText().toString());
values.put("cognome",editCognome.getText().toString());
values.put("sesso", idSesso);
long id = db.insert("utenti", null, values);
if (id == -1)
Toast.makeText(this,"Errore caricamento dati",Toast.LENGTH_LONG).show();
else
Toast.makeText(this,"Record creato. ID = " + id,Toast.LENGTH_LONG).show();
}
30. Memorizzazione dei dati: database
30/04/2014 30
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
private void caricaDB() {
SQLiteDatabase db = myDatabaseHelper.getReadableDatabase();
String query = "SELECT nome, cognome, sesso FROM utenti";
Cursor cursor = db.rawQuery(query, null);
if (cursor.getCount() == 0)
Toast.makeText(this,"Nessun utente presente", Toast.LENGTH_LONG).show();
else {
cursor.moveToNext();
EditText editNome = (EditText) findViewById(R.id.editText1);
EditText editCognome = (EditText) findViewById(R.id.editText2);
RadioGroup radioSesso = (RadioGroup)findViewById(R.id.radioGroup1);
editNome.setText(cursor.getString(0));
editCognome.setText(cursor.getString(1));
radioSesso.check(cursor.getInt(2));
}
}
31. 30/04/2014 31
Quest' opera è distribuita con
licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 3.0 Unported.
The end!