Kontynuacja projektu BazaDanychSQLite

1. Tworzymy klas� PlikXml (plik PlikXml.cs)

2. Metoda do zapisu tabeli os�b w pliku XML:

using Android.App;
using Android.Content;
using Android.Util;
using Org.XmlPull.V1;
using System;
using System.IO;

namespace BazaDanychSQLite
{
    public static class PlikXml
    {
        public static void ZapiszOsobyDoPlikuXml(Activity activity, Osoba[] osoby, string nazwaPlikuXml, IFormatProvider formatProvider = null)
        {
            if (formatProvider == null) formatProvider = System.Globalization.CultureInfo.InvariantCulture;

            Stream fos = activity.OpenFileOutput(nazwaPlikuXml, FileCreationMode.Private); //dopisywanie - FileCreationMode.Append

            IXmlSerializer xml = Xml.NewSerializer();
            xml.SetOutput(fos, "UTF-8");
            xml.StartDocument("UTF-8", Java.Lang.Boolean.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", osoby.Length.ToString(formatProvider));

            foreach(Osoba osoba in osoby)
            {
                xml.StartTag(ns, "Osoba");
                xml.Attribute(ns, "ID", osoba.Id.ToString(formatProvider));

                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(osoba.Wiek.ToString(formatProvider));
                xml.EndTag(ns, "Wiek");

                xml.StartTag(ns, "NumerTelefonu");
                xml.Text(osoba.NumerTelefonu.ToString(formatProvider));
                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\
(je�eli VS by�o instalowane przed Android-Studio: c:\Users\pk\Xamarin\MonoForAndroid\AndroidSDK\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/BazaDanychSQLite.BazaDanychSQLite/
more /data/data/BazaDanychSQLite.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/BazaDanychSQLite.BazaDanychSQLite/
total 32
drwxrwx--x 2 u0_a88 u0_a88 4096 2018-12-30 02:09 cache
drwxrwx--x 2 u0_a88 u0_a88 4096 2018-12-30 02:09 code_cache
drwxrwx--x 2 u0_a88 u0_a88 4096 2018-12-30 17:55 databases
drwxrwx--x 5 u0_a88 u0_a88 4096 2018-12-30 17:55 files
lrwxrwxrwx 1 root   root     53 2018-12-30 17:54 lib -> /data/app/BazaDanychSQLite.BazaDanychSQLite-1/lib/x86
generic_x86:/ # more /data/data/BazaDanychSQLite.BazaDanychSQLite/files/osoby.xml
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<Osoby length="3">
  <Osoba ID="3">
    <Imie>Hans</Imie>
    <Nazwisko>Muller</Nazwisko>
    <Wiek>32</Wiek>
    <NumerTelefonu>564738219</NumerTelefonu>
  </Osoba>
  <Osoba ID="4">
    <Imie>Jean</Imie>
    <Nazwisko>Dupont</Nazwisko>
    <Wiek>50</Wiek>
    <NumerTelefonu>1230198318</NumerTelefonu>
  </Osoba>
  <Osoba ID="2">
    <Imie>John</Imie>
    <Nazwisko>Smith</Nazwisko>
    <Wiek>20</Wiek>
    <NumerTelefonu>987654321</NumerTelefonu>
  </Osoba>
</Osoby>generic_x86:/ #

*********************

5. Wczytywanie i parsowanie lokalnego pliku XML:

        public static Osoba[] CzytajOsobyZPlikuXml(Activity activity, string nazwaPlikuXml)
        {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.NewInstance();
            //dbf.setIgnoringComments(true);
            //dbf.setIgnoringElementContentWhitespace(true);
            //dbf.setValidating(false);

            DocumentBuilder db = dbf.NewDocumentBuilder();
            Stream fis = activity.OpenFileInput(nazwaPlikuXml);
            //Document d = db.parse(fis); //to UTF-8 nie dzia�a - b��d przy Imi�

            Java.IO.Reader r = new Java.IO.InputStreamReader(fis, "UTF-8");
            InputSource _is = new InputSource(r);
            _is.Encoding = "UTF-8"; //to tak naprawd� nie dzia�a - b��d gdy Imi�
            IDocument d = db.Parse(_is);

            INodeList w�z�y = d.GetElementsByTagName("Osoba");

            int n = w�z�y.Length;
            Osoba[] osoby = new Osoba[n];
            for (int i = 0; i < n; ++i)
            {
                INode w�ze� = w�z�y.Item(i);
                string _id = w�ze�.Attributes.GetNamedItem("ID").NodeValue;
                int id = int.Parse(_id);
                INodeList podw�z�y = w�ze�.ChildNodes;

                string imi� = "";
                string nazwisko = "";
                int wiek = -1;
                int numerTelefonu = -1;

                for (int j = 0; j < podw�z�y.Length; ++j)
                {
                    INode podw�ze� = podw�z�y.Item(j);
                    string nazwaPodw�z�a = podw�ze�.NodeName;
                    string warto�� = "";
                    if (podw�ze�.HasChildNodes) warto�� = podw�ze�.FirstChild.NodeValue;
                    switch (nazwaPodw�z�a)
                    {
                        case "Imie":
                            imi� = warto��;
                            break;
                        case "Nazwisko":
                            nazwisko = warto��;
                            break;
                        case "Wiek":
                            wiek = int.Parse(warto��);
                            break;
                        case "NumerTelefonu":
                            numerTelefonu = int.Parse(warto��);
                            break;
                    }
                }
                osoby[i] = new Osoba(id, imi�, nazwisko, wiek, numerTelefonu);
            }
            return osoby;
        }


6. Testowanie w funkcji MainActivity.OnCreate:

            try
            {
                Osoba[] _osoby = PlikXml.CzytajOsobyZPlikuXml(this, nazwaPlikuXml);
                poka�Osoby(_osoby);
                Toast.MakeText(ApplicationContext, "Plik XML zosta� odczytany", ToastLength.Long).Show();
            }
            catch (Org.W3c.Dom.DOMException exc)
            {
                Toast.MakeText(ApplicationContext, "B��d parsowania: " + exc.Message + ", kod: " + exc.Code.ToString(), ToastLength.Long).Show();
            }
            catch (System.Exception exc)
            {
                Toast.MakeText(ApplicationContext, "B��d (" + exc.GetType().Name + "): " + exc.Message, ToastLength.Long).Show();
            }


7. Pobieranie pliku z serwera WWW:

http://www.fizyka.umk.pl/~jacek/dydaktyka/pum/xamarin/xamarin_android/osoby.xml

Modyfikacje w metodzie PlikXml.CzytajOsobyZPlikuXMl:

        public static Osoba[] CzytajOsobyZPlikuXml(Java.Net.URL url)
        {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.NewInstance();
            //dbf.setIgnoringComments(true);
            //dbf.setIgnoringElementContentWhitespace(true);
            //dbf.setValidating(false);

            DocumentBuilder db = dbf.NewDocumentBuilder();
            Stream _is = url.OpenStream();     <--------------------------------------- tylko tu
            IDocument d = db.Parse(_is); //to UTF-8 nie dzia�a - b��d przy Imi�

            INodeList w�z�y = d.GetElementsByTagName("Osoba");

            int n = w�z�y.Length;
            Osoba[] osoby = new Osoba[n];
            for (int i = 0; i < n; ++i)
            {
                INode w�ze� = w�z�y.Item(i);
                string _id = w�ze�.Attributes.GetNamedItem("ID").NodeValue;
                int id = int.Parse(_id);
                INodeList podw�z�y = w�ze�.ChildNodes;

                string imi� = "";
                string nazwisko = "";
                int wiek = -1;
                int numerTelefonu = -1;

                for (int j = 0; j < podw�z�y.Length; ++j)
                {
                    INode podw�ze� = podw�z�y.Item(j);
                    string nazwaPodw�z�a = podw�ze�.NodeName;
                    string warto�� = "";
                    if (podw�ze�.HasChildNodes) warto�� = podw�ze�.FirstChild.NodeValue;
                    switch (nazwaPodw�z�a)
                    {
                        case "Imie":
                            imi� = warto��;
                            break;
                        case "Nazwisko":
                            nazwisko = warto��;
                            break;
                        case "Wiek":
                            wiek = int.Parse(warto��);
                            break;
                        case "NumerTelefonu":
                            numerTelefonu = int.Parse(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.
Uwaga! Wymagane uprawnienie: INTERNET

Test w MainActivity.onCreate:

            //plik XML z serwera WWW
            try
            {
                Osoba[] _osoby = null;
                Java.Lang.Thread thread = new Java.Lang.Thread(
                    () =>
                    {
                        try
                        {
                            Java.Net.URL url = new Java.Net.URL(@"http://www.fizyka.umk.pl/~jacek/dydaktyka/pum/xamarin/xamarin_android/osoby.xml");
                            _osoby = PlikXml.CzytajOsobyZPlikuXml(url);
                        }
                        catch (System.Exception exc)
                        {
                            //osobna obs�uga wyj�tk�w w ka�dym w�tku
                            throw new System.Exception("B��d (" + exc.GetType().Name + "): " + exc.Message, exc);
                            //Toast.MakeText(ApplicationContext, "B��d (" + exc.GetType().Name + "): " + exc.Message, ToastLength.Long).Show();
                        }
                    });
                thread.Start();
                thread.Join();
                poka�Osoby(_osoby); //musi by� w w�tku UI
                Toast.MakeText(ApplicationContext, "Plik XML zosta� odczytany (URI)", ToastLength.Long).Show();
            }
            catch (System.Exception exc)
            {
                Toast.MakeText(ApplicationContext, "B��d (" + exc.GetType().Name + "): " + exc.Message, ToastLength.Long).Show();
            }