Kontynuacja projektu BazaDanychSQLite 1. Tworzymy klasę PlikXml (plik PlikXml.java) 2. Metoda do zapisu tabeli osób: package pl.umk.fizyka.bazadanychsqlite; import ... public class PlikXml { static public void zapiszOsobyDoPlikuXml(Activity activity, Osoba[] osoby, String nazwaPlikuXml) throws IOException { FileOutputStream fos = activity.openFileOutput(nazwaPlikuXml, Context.MODE_PRIVATE); //dopisywanie - Context.MODE_APPEND //Reflection try { Field pathField = FileOutputStream.class.getDeclaredField("path"); pathField.setAccessible(true); String ścieżka = (String) pathField.get(fos); Toast.makeText(activity.getApplicationContext(), "Ścieżka pliku XML: " + ścieżka, Toast.LENGTH_LONG).show(); } catch (Exception exc) //NoSuchFieldException, IllegalAccessException { Toast.makeText(activity.getApplicationContext(), "Błąd: " + exc.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } XmlSerializer xml = Xml.newSerializer(); xml.setOutput(fos, "UTF-8"); xml.startDocument("UTF-8", true); xml.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); String ns = null; //namespace xml.startTag(ns, "Osoby"); xml.attribute(ns, "length", Integer.toString(osoby.length)); for (Osoba osoba : osoby) { xml.startTag(ns, "Osoba"); xml.attribute(ns, "ID", Integer.toString(osoba.ID)); xml.startTag(ns, "Imie"); //Imie zamiast Imię - problem przy parsowaniu za pomocą DOM xml.text(osoba.Imię); xml.endTag(ns, "Imie"); xml.startTag(ns, "Nazwisko"); xml.text(osoba.Nazwisko); xml.endTag(ns, "Nazwisko"); xml.startTag(ns, "Wiek"); xml.text(Integer.toString(osoba.Wiek)); xml.endTag(ns, "Wiek"); xml.startTag(ns, "NumerTelefonu"); xml.text(Integer.toString(osoba.NumerTelefonu)); xml.endTag(ns, "NumerTelefonu"); xml.endTag(ns, "Osoba"); } xml.endTag(ns, "Osoby"); xml.endDocument(); xml.flush(); fos.close(); } } 3. Użycie w funkcji MainActivity.onCreate: String nazwaPlikuXml = "osoby.xml"; try { PlikXml.zapiszOsobyDoPlikuXml(this, osoby, nazwaPlikuXml); Toast.makeText(getApplicationContext(), "Plik XML został zapisany", Toast.LENGTH_LONG).show(); } catch(IOException exc) { Toast.makeText(getApplicationContext(), "Błąd zapisu do pliku: " + exc.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } catch(Exception exc) { Toast.makeText(getApplicationContext(), "Ogólny błąd: " + exc.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } 4. Sprawdzamy obecność pliku XML Nie zadziała: Menu Tools, Android, Android Device Monitor, zakładka File Explorer, bo bez zrootowanego urządzenia nie mamy dostępu do katalogu /data/data/pl.umk.fizyka.bazadanychsqlite/files/ Zamiast tego uruchamiamy cmd w katalogu c:\Program Files (x86)\Android\android-sdk\platform-tools\ Uwaga! Musi być włączony jeden emulator lub podłączone urządzenie - w przeciwnym przypadku dodatkowe parametry identyfikujące adb shell su ls -l /data/data/pl.umk.fizyka.bazadanychsqlite/ more /data/data/pl.umk.fizyka.bazadanychsqlite/files/osoby.xml exit exit ***************** c:\Program Files (x86)\Android\android-sdk\platform-tools>adb shell generic_x86:/ $ su generic_x86:/ # ls -l /data/data/pl.umk.fizyka.bazadanychsqlite/ total 32 drwxrwx--x 2 u0_a84 u0_a84 4096 2017-07-28 11:51 cache drwxrwx--x 2 u0_a84 u0_a84 4096 2017-07-28 11:51 code_cache drwxrwx--x 2 u0_a84 u0_a84 4096 2017-07-28 20:52 databases drwxrwx--x 2 u0_a84 u0_a84 4096 2017-07-28 12:02 files generic_x86:/ # more /data/data/pl.umk.fizyka.bazadanychsqlite/files/osoby.xml Hans Muller 32 564738219 Jean Dupont 50 1230198318 John Smith 20 987654321 generic_x86:/ # ********************* 5. Wczytywanie i parsowanie lokalnego pliku XML: static public Osoba[] czytajOsobyZPlikuXml(Activity activity, String nazwaPlikuXml) throws ParserConfigurationException, IOException, SAXException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); //dbf.setIgnoringComments(true); //dbf.setIgnoringElementContentWhitespace(true); //dbf.setValidating(false); DocumentBuilder db = dbf.newDocumentBuilder(); FileInputStream fis = activity.openFileInput(nazwaPlikuXml); //Document d = db.parse(fis); //to UTF-8 nie działa - błąd przy Imię Reader r = new InputStreamReader(fis,"UTF-8"); InputSource is = new InputSource(r); is.setEncoding("UTF-8"); //to tak naprawdę nie działa - błąd gdy Imię Document d = db.parse(is); NodeList węzły = d.getElementsByTagName("Osoba"); int n = węzły.getLength(); Osoba[] osoby = new Osoba[n]; for(int i = 0; i < n; ++i) { Node węzeł = węzły.item(i); String _id = węzeł.getAttributes().getNamedItem("ID").getNodeValue(); int id = Integer.parseInt(_id); NodeList podwęzły = węzeł.getChildNodes(); String imię = ""; String nazwisko = ""; int wiek = -1; int numerTelefonu = -1; for(int j = 0; j < podwęzły.getLength(); ++j) { Node podwęzeł = podwęzły.item(j); String nazwaPodwęzła = podwęzeł.getNodeName(); String wartość = ""; if(podwęzeł.hasChildNodes()) wartość = podwęzeł.getFirstChild().getNodeValue(); switch(nazwaPodwęzła) { case "Imie": imię = wartość; break; case "Nazwisko": nazwisko = wartość; break; case "Wiek": wiek = Integer.parseInt(wartość); break; case "NumerTelefonu": numerTelefonu = Integer.parseInt(wartość); break; } } osoby[i] = new Osoba(id, imię, nazwisko, wiek, numerTelefonu); } return osoby; } 6. Testowanie w funkcji MainActivity.onCreate: try { osoby = PlikXml.czytajOsobyZPlikuXml(this, nazwaPlikuXml); pokażOsoby(osoby); Toast.makeText(getApplicationContext(), "Plik XML został odczytany", Toast.LENGTH_LONG).show(); } catch(DOMException exc) { Toast.makeText(getApplicationContext(), "Błąd parsowania: " + exc.getMessage() + ", kod: " + Integer.toString(exc.code), Toast.LENGTH_LONG).show(); } catch(Exception exc) { Toast.makeText(getApplicationContext(), "Błąd (" + exc.getClass().getName() + "): " + exc.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } 7. Pobieranie pliku z serwera WWW: http://www.fizyka.umk.pl/~jacek/dydaktyka/mobilne/android_studio/osoby.xml Modyfikacje w metodzie PlikXml.czytajOsobyZPlikuXMl: static public Osoba[] czytajOsobyZPlikuXml(URL url) throws ParserConfigurationException, IOException, SAXException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); //dbf.setIgnoringComments(true); //dbf.setIgnoringElementContentWhitespace(true); //dbf.setValidating(false); DocumentBuilder db = dbf.newDocumentBuilder(); InputStream is = url.openStream(); Document d = db.parse(is); //to UTF-8 nie działa - błąd przy Imię NodeList węzły = d.getElementsByTagName("Osoba"); int n = węzły.getLength(); Osoba[] osoby = new Osoba[n]; for(int i = 0; i < n; ++i) { Node węzeł = węzły.item(i); String _id = węzeł.getAttributes().getNamedItem("ID").getNodeValue(); int id = Integer.parseInt(_id); NodeList podwęzły = węzeł.getChildNodes(); String imię = ""; String nazwisko = ""; int wiek = -1; int numerTelefonu = -1; for(int j = 0; j < podwęzły.getLength(); ++j) { Node podwęzeł = podwęzły.item(j); String nazwaPodwęzła = podwęzeł.getNodeName(); String wartość = ""; if(podwęzeł.hasChildNodes()) wartość = podwęzeł.getFirstChild().getNodeValue(); switch(nazwaPodwęzła) { case "Imie": imię = wartość; break; case "Nazwisko": nazwisko = wartość; break; case "Wiek": wiek = Integer.parseInt(wartość); break; case "NumerTelefonu": numerTelefonu = Integer.parseInt(wartość); break; } } osoby[i] = new Osoba(id, imię, nazwisko, wiek, numerTelefonu); } return osoby; } Uwaga! Operacje sieciowe muszą być od Android 3.0 wykonywane w osobnym wątku. Test w MainActivity.onCreate: //plik XML z serwera WWW try { //Osoba[] _osoby; Thread thread = new Thread(new Runnable() { @Override public void run() { try { URL url = new URL("http://www.fizyka.umk.pl/~jacek/dydaktyka/mobilne/android_studio/osoby.xml"); _osoby = PlikXml.czytajOsobyZPlikuXml(url); } catch (Exception exc) { Toast.makeText(getApplicationContext(), "Błąd (" + exc.getClass().getName() + "): " + exc.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } } }); thread.start(); thread.join(); pokażOsoby(_osoby); Toast.makeText(getApplicationContext(), "Plik XML został odczytany (URI)", Toast.LENGTH_LONG).show(); } /* catch(InterruptedException exc) { Toast.makeText(getApplicationContext(), "Błąd (" + exc.getClass().getName() + "): " + exc.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } */ catch(Exception exc) { Toast.makeText(getApplicationContext(), "Błąd (" + exc.getClass().getName() + "): " + exc.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } Uwaga! Wymagane uprawnienie: