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: