Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Programmazione mobile: ANDROID

121 views

Published on

Quarta lezione: file system, parsing file XML e networking

Published in: Education
  • Be the first to comment

  • Be the first to like this

Programmazione mobile: ANDROID

  1. 1. ITIS Max Planck di Lancenigo diVillorba (TV) A.S. 2013-2014 Prof. PAOLOTOSATO Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Programmazionemobile: ANDROID Quarta lezione: file system, parsing file XML e networking
  2. 2. 09/07/2016 2 • Accesso al file system • Storage interno • Storage esterno • Parse XML data • XML • ParserXML • Networking Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Indice
  3. 3. 09/07/2016 3 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Accesso al file system Storage interno • Porzione di file system esclusivamente assegnata all’applicazione: altri pacchetti installati nel dispositivo non possono farvi accesso. Storage esterno • Solitamente una scheda che può all’occorrenza essere rimossa e sostituita, ma non è detto.
  4. 4. Accesso al file system 09/07/2016 4 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Storage interno Per scoprire quale sia la directory radice dello spazio riservato ad un’applicazione: getFilesDir(), che restituisce un java.io.File. Metodo di android.content.Context, classe da cui derivano Activity e gli altri mattoni fondamentali di Android. protectedvoidonCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.mylayout); /* Dov'è lo storage interno dell'applicazione? (In Eclipse: DDMS  File Explorer) /data/data/<package applicazione>/files */ Log.i("FileDemo","Directory: " +getFilesDir().getAbsolutePath()); }
  5. 5. 09/07/2016 5 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Accesso al file system Storage esterno • Prima cosa da fare: controllare se disponibile! publicstaticStringgetExternalStorageState(),metododi android.os.Environment • Environment.MEDIA_MOUNTED disponibile in lettura e scrittura • Environment.MEDIA_MOUNTED_READ_ONLYdisponibile solo in lettura • Environment.XXX … • Per ottenere la radice dello storage esterno publicstatic FilegetExternalStorageDirectory(),metododi android.os.Environment • Sisconsiglia 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.).
  6. 6. 09/07/2016 6 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Parse XML data XML Oggigiorno difficilmente un’applicazione lavora in modo isolato e possiede tutti i dati che deve elaborare. Problema: raramente si deve interagire con applicazioni che possiedono la stessa tecnologia. Soluzione: scambiare informazioni attraverso un formato aperto come Extensible Markup language (XML)
  7. 7. 09/07/2016 7 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Parse XML data XML Metalinguaggioper la rappresentazione dei dati a struttura gerarchica in forma di testo. Consente di definire in modo semplice nuovi linguaggidi markup da usare in ambito web. <?xmlversion="1.0" encoding="UTF-8"?> <products> <product> <productname>Pantaloni</productname> <productcolor>nero</productcolor> <productquantity>5</productquantity> </product> <product> <productname>T-Shirt</productname> <productcolor>blu</productcolor> <productquantity>3</productquantity> </product> </products>
  8. 8. 09/07/2016 8 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Parse XML data XML Un documento XML è: • undocumento di testo • “humanreadable” • contiene tag (di apertura e chiusura) che possono avere attributi e dati al loro interno • case sensitive • deve essere ben formattato, cioè avere: • unprologo:<?xml version="1.0" encoding="UTF-8"?> • ununico elemento radice: <products> • tutti i tag devono essere bilanciati (corretto annidamento) Seil documento XML non contiene errori si dice Well Formed (ben formato). Seil documento è well formed e in più rispetta i requisiti strutturali definiti nel file DTD (DocumentType Definition ) o schema XMLassociato viene chiamato Valid (valido)
  9. 9. 09/07/2016 9 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Parse XML data ParserXML DOM (DocumentObject Model): è un'interfacciadi programmazione per la manipolazionedi fileXML. DOM, partendo dal file XML,costruisce un albero dove ogni nodo dell'albero corrisponde ad un elemento del file; per questo motivo è detto tree based o object based • Consumamolta memoria • Permette di fare il parse e creare un fileXML • Effettuareil parse di tutto il documento
  10. 10. 09/07/2016 10 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Parse XML data ParserXML SAX (SimpleAPI forXML): è un'interfacciadi programmazione che permette di leggere e modificarei documenti XML.SAX è event based, al contrario di DOM, e reagisce agli eventi di parsing facendo rapporto all'applicazione.È compito del programmatore implementarei metodi per reagire agli eventi di parsing (). • Consumamolta meno memoria del DOM (ottimo per grandi documenti) • Non può creare file XML,ma solo effettuare il parse • Effettuareil parse di tutto il documento PULL: simile a SAX, ma più semplice da implementare e più performante. • Sipuò effettuare il parse solo di un nodo specifico (“pull only a particular node”) • Consigliatoper piccoli documenti.
  11. 11. 09/07/2016 11 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Parse XML data XmlPullParser: esempio try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser xpp = factory.newPullParser(); xpp.setInput(new StringReader("<saluto>HelloWorld!</saluto>" )); /* * Restituisce lo stato corrente del parser * Inizialmente 0 (START_DOCUMENT) * Alla fine 1 (END_DOCUMENT) */ int eventType = xpp.getEventType();
  12. 12. Parse XML data 09/07/2016 12 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. XmlPullParser: esempio while (eventType !=XmlPullParser.END_DOCUMENT){ if(eventType ==XmlPullParser.START_DOCUMENT){ Log.i("MYAPP","Startdocument"); } else if(eventType == XmlPullParser.START_TAG){ // 2 Log.i("MYAPP","Starttag:" + xpp.getName()); } else if(eventType == XmlPullParser.END_TAG){// 3 Log.i("MYAPP","End tag:" + xpp.getName()); } else if(eventType == XmlPullParser.TEXT){ //4 Log.i("MYAPP","Testo: " + xpp.getText()); } eventType = xpp.next(); } Log.i("MYAPP","End document"); }catch(XmlPullParserException |IOExceptione) { Log.e("MYAPP","ParserException"); }
  13. 13. Parse XML data 09/07/2016 13 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. XmlPullParser: esempio XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser xpp = factory.newPullParser(); Factory Design pattern • Disaccoppiarele modalità di creazione degli oggetti dal loro utilizzo. • Factory incapsula la logica di costruzione (connessioni EJB, DB, ecc): cambiamenti nellacostruzione della classe comportano modifiche alla sola classe Factory. • Lacreazione di un oggetto richiede l'accesso ad informazioni o risorse che non dovrebbero essere contenute nella classe di composizione. • Lagestione del ciclo di vita degli oggetti deve essere centralizzata in modo da assicurareun comportamento consistente all'interno dell'applicazione.
  14. 14. Parse XML data 09/07/2016 14 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. XmlPullParser • Ese volessimo accedere a una risorsa presente nel file system? /* * getAssets() restituisce un AssetManager, che permette di accedere * alle risorse della directory assets (non hanno un riferimento in R) */ InputStream file = getApplicationContext().getAssets().open("data.xml"); xpp.setInput(file, null);
  15. 15. Parse XML data 09/07/2016 15 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. XmlPullParser • Ese volessimo memorizzare le informazione in un oggetto ad hoc? ArrayList<Prodotto> prodotti = null; Prodotto currentProduct = null; int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { String name = null; switch (eventType) { case XmlPullParser.START_DOCUMENT: prodotti = new ArrayList<Prodotto>(); break;
  16. 16. Parse XML data 09/07/2016 16 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. case XmlPullParser.START_TAG: name = xpp.getName(); if (name.equals("product")) { currentProduct = new Prodotto(); } else if (currentProduct != null) { if (name.equals("productname")) { currentProduct.setNome(xpp.nextText()); } else if (name.equals("productcolor")) { currentProduct.setColore(xpp.nextText()); } else if (name.equals("productquantity")) { currentProduct.setQuantita(Integer.parseInt(xpp.nextText())); } } break;
  17. 17. Parse XML data 09/07/2016 17 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. case XmlPullParser.END_TAG: name = xpp.getName(); if (name.equals("product") && currentProduct != null){ prodotti.add(currentProduct); } } // chiude lo switch eventType = xpp.next(); } // chiude il ciclo while
  18. 18. Parse XML data 09/07/2016 18 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. /* * Stampa l’array list su LogCat */ StringBuffercontent = new StringBuffer(); Iterator<Prodotto> iterator = prodotti.iterator(); while(iterator.hasNext()) { Prodotto prodotto = iterator.next(); content.append("Nome: " + prodotto.getNome() + " "); content.append("Colore: " + prodotto.getColore() + " "); content.append("Quantita': " + prodotto.getQuantita()); Log.i("MYAPP", content.toString()); content.delete(0, content.length()); }
  19. 19. Net 09/07/2016 19 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. AsyncTask • Questa classe consente di eseguire operazioni in background e di pubblicarne in modo semplice i risultati nel Thread dell'interfaccia grafica (UIThread). • Dovrebbe essere utilizzato per operazioni di breve durata (pochi secondi al massimo). • E' definito da 3 tipi generici: Params, Progress e Result e da 4 fasi: OnPreExecute, doInBackground, onProgressUpdate e OnPostExecute. • Per essere implementato è necessario estendere la classe AsyncTask e sovrascrivere il metodo doInBackground(Params...)
  20. 20. 09/07/2016 20 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Net AsyncTask: tipi generici • Params, il tipo dei parametri inviati al task al momento dell'esecuzione. • Progress, il tipo delle progress unit pubblicate durante le operazioni in background. • Result, il tipo di risultato dell'elaborazione in background. Non tutti i tipi devono essere utilizzati da un task asincrono. Per indicare che un tipo non è utilizzato si utilizza Void: private class MyTask extends AsyncTask<Void, Void, Void> { ... }
  21. 21. Net 09/07/2016 21 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. AsyncTask: 4 fasi • onPreExecute(),invocato sul thread dell'interfaccia grafica prima che il task venga eseguito. Questafase viene normalmente utilizzata per il setup del task, per esempio per mostrare una progress bar nell'interfaccia utente. • doInBackground(Params...),invocatoquando termina onPreExcecute() e serve per avviare il task asincrono. Il risultato dell'elaborazione deve essere restituito a questo metodo. Questa fase puòutilizzare publishProgress(Progress...) perpubblicaredelle unità di progressione. Questi valorisono pubblicati nell'interfaccia utente tramite onProgressUpdate(Progress...). • onProgressUpdate(Progress...),invocatoda publishProgress(Progress...).Questometodo è utilizzato per visualizzare qualsiasi forma di progresso nell'interfaccia utente mentre il task è in esecuzione in background. Per esempio, può essere utilizzato per animare una progress bar. • onPostExecute(Result),invocato dopo che l'elaborazione in backgroud è terminata. Il risultato diquesta elaborazione è passato al metodo come parametro.
  22. 22. Net 09/07/2016 22 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Permessi Settare l’app in modo che possa connettersi ad Internet AndroidManifest  Permission  ADD  Uses Permission  android.permission.INTERNET <uses-permissionandroid:name="android.permission.INTERNET"/> <application <activity android:name="esempi.android.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
  23. 23. Net 09/07/2016 23 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. private static finalStringTAG = "MYAPP"; // Parametri della richiesta HTTP private static finalStringVERB = "ListRecords"; private static finalString METADATA_PREFIX = "oai_lom"; // QUERYURL private static finalString SERVER_URL= "http://cird.unive.it/"; private static finalStringQUERY_FILE = "oai/request"; private static finalStringQUERY_OPTIONS= "?verb=" +VERB + "&metadataPrefix=" + METADATA_PREFIX; private static finalStringQUERY_URL = SERVER_URL+ QUERY_FILE+ QUERY_OPTIONS;
  24. 24. 09/07/2016 24 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. Net protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btDownload = (Button) findViewById(R.id.btConnect); btDownload.setOnClickListener(this); } publicvoid onClick(View v) { TextView txtNumRec = (TextView) findViewById(R.id.txtNumRec); txtNumRec.setText("0"); AsyncDownload downloader = new AsyncDownload(); // Chiamo il Thread downloader.execute(); } publicvoid printResult(intnumRecord) { TextView txtNumRec = (TextView) findViewById(R.id.txtNumRec); txtNumRec.setText(String.valueOf(numRecord)); }
  25. 25. Net 09/07/2016 25 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. privateclass AsyncDownload extends AsyncTask<Object, String,Integer> { // Inner classper fare il download in background protected IntegerdoInBackground(Object... params) { XmlPullParser datiRicevuti =downloadXmlData(); int numRecords=parsingXmlData(datiRicevuti); return numRecords; } privateXmlPullParser downloadXmlData() { Log.i(TAG,"Download avviato ..."); try { URL xmlUrl = newURL(QUERY_URL); XmlPullParser datiRicevuti =XmlPullParserFactory.newInstance().newPullParser(); datiRicevuti.setInput(xmlUrl.openStream(),null); return datiRicevuti; } catch (MalformedURLException e){ Log.e(TAG, "URL errato",e); } catch (XmlPullParserException e){ Log.e(TAG, "Factory error",e); } catch (IOException e){ Log.e(TAG, "Errore di connessione",e); } return null; }
  26. 26. Net 09/07/2016 26 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. privateint parsingXmlData(XmlPullParser datiRicevuti){ int numRecord =0; if (datiRicevuti !=null){ try { int eventType =datiRicevuti.getEventType(); while (eventType !=XmlPullParser.END_DOCUMENT) { String nome =null; switch(eventType){ case XmlPullParser.START_TAG: nome = datiRicevuti.getName(); if (nome.equals("record")){ numRecord++; publishProgress(String.valueOf(numRecord)); //Chiama onProgressUpdate } break; } eventType = datiRicevuti.next(); } } catch (XmlPullParserException e){ Log.e(TAG, "PullParser error",e); } catch (IOException e){ Log.e(TAG, "PullParser error",e); } } return numRecord; }
  27. 27. Net 09/07/2016 27 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. protected void onProgressUpdate(String... values){ super.onProgressUpdate(values); if (values.length == 1) { printResult(Integer.parseInt(values[0])); } } } }
  28. 28. 09/07/2016 28 Quest' opera è distribuitacon licenzaCreative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0 Unported. The end!

×