Programmazione mobile: ANDROID

31
ITIS Max Planck di Lancenigo di Villorba (TV) A.S. 2013-2014 Prof. PAOLO TOSATO 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

description

Terza lezione: gestione eventi e memorizzazione dati

Transcript of Programmazione mobile: ANDROID

Page 3: Programmazione mobile: ANDROID

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 callback Vs 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.

Page 4: Programmazione mobile: ANDROID

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; } }

Page 5: Programmazione mobile: ANDROID

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(); } }

Page 6: Programmazione mobile: ANDROID

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(); }

Page 7: Programmazione mobile: ANDROID

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).

Page 8: Programmazione mobile: ANDROID

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).

Page 9: Programmazione mobile: ANDROID

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’Edit Text });

Page 11: Programmazione mobile: ANDROID

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(String name) • Per elencare i file nell’area riservata all’applicazione: public String[] fileList()

Page 12: Programmazione mobile: ANDROID

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.).

Page 13: Programmazione mobile: ANDROID

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()); }

Page 14: Programmazione mobile: ANDROID

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;

Page 15: Programmazione mobile: ANDROID

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) {} } } }

Page 16: Programmazione mobile: ANDROID

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 (FileNotFoundException e2) {; 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();

Page 17: Programmazione mobile: ANDROID

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()); }

Page 18: Programmazione mobile: ANDROID

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/

Page 19: Programmazione mobile: ANDROID

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.

Page 20: Programmazione mobile: ANDROID

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);

Page 21: Programmazione mobile: ANDROID

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);

Page 22: Programmazione mobile: ANDROID

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);

Page 23: Programmazione mobile: ANDROID

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("DROP TABLE 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 utenti WHERE cognome = ? ORDER BY _id ASC”; String[] selectionArgs = { "Rossi" }; Cursor cursor = db.rawQuery(query, selectionArgs);

Page 24: Programmazione mobile: ANDROID

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)

Page 25: Programmazione mobile: ANDROID

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

Page 26: Programmazione mobile: ANDROID

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.

Page 27: Programmazione mobile: ANDROID

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 += "CREATE TABLE utenti ("; sql += " _id INTEGER PRIMARY KEY,"; // campo di tipo contatore sql += " nome TEXT,"; sql += " cognome TEXT,"; sql += " sesso INTEGER)"; db.execSQL(sql); } }

Page 28: Programmazione mobile: ANDROID

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 implements OnClickListener { 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à

Page 29: Programmazione mobile: ANDROID

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(); }

Page 30: Programmazione mobile: ANDROID

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)); } }