Zugriff auf Online-mySQL-Datenbank von Android-App

  • Antworten:28
  • OffenNicht stickyBentwortet
Gelöschter Account
  • Forum-Beiträge: 5.136

02.02.2013 20:18:23 via Website

Dann wird der Fehler auch noch der gleiche sein ..

Keine Ahnung was du mit den <br /> machst .. ich weiß ja nicht was da später mit dem xml passieren soll..
Jedenfalls solltest Du statt des einfachen <xml> tags eher : <?xml version="1.0" encoding="UTF-8"?> schreiben. Das macht dem Parser das ganze wesentlich leichter und deklariert das XML korrekt. So werden auch Fehlermeldungen vermieden die aus der nicht korrekten Erkennung des Dokuments her rühren.

— geändert am 03.02.2013 10:52:20

lg Voss

Antworten
  • Forum-Beiträge: 72

03.02.2013 15:31:50 via Website

Jetzt sieht das Ganze so aus:

1<?xml version="1.0" encoding="UTF-8"?>
2 <entry>
3 <titel>Küchenumbau am 19.01.2013</titel>
4 <text>Am 19.Januar haben wir die Küche umgebaut:\n\n - Der Herd sowie einige Schränke wurden entfernt.\n - Ein Durchgang von der Bar zur Küche wurde gesägt.\n - Eine neue Wand zwischen Aufenthaltsraum und Küche wurde gebaut.\n</text>
5 </entry>
6 <entry>
7 <titel>Neue Facebookseite</titel>
8 <text>Zwei Anläufe sind gescheitert, daher nun der dritte: Das Freakhall hat ab heute eine neue Facebookseite. Diese soll aktueller gehalten werden und in naher Zukunft auch mit dieser Website verknüpft werden.</text>
9 </entry>

aber der Fehler besteht weiterhin. Immer noch "not well-formed (invalid token)" Da ich die Einrückung etwas verbessert habe, heisst es nun Line 3 Column 16, was das 'm' in 'Am 19. Januar...' ist. Ich habe jetzt auch in parser.require das Encoding auf UTF-8 eingestellt, aber immer noch keine Verbesserung.

ich weiß ja nicht was da später mit dem xml passieren soll..
Der Text soll in einem LinearLayout angezeigt werden:
1LinearLayout layout = new LinearLayout(this);
2layout.setOrientation(LinearLayout.VERTICAL);
3for (int i = 0; i < entries.size(); i++) {
4 TextView t1 = new TextView(this);
5 t1.setText(entries.get(i).title);
6 t1.setTextSize(30);
7 layout.addView(t1);
8 TextView t2 = new TextView(this);
9 t2.setText(entries.get(i).text);
10 t2.setTextSize(20);
11 layout.addView(t2);
12}
13setContentView(layout);


EDIT: Jetzt habe ich Umlaute (ÄäÖöÜü) durch die entsprechenden Escapesequenzen (\uXXXX) ersetzt. Der Fehler mit dem invalid token besteht nun nicht mehr. Jetzt gibt es aber einen neuen Fehler:
At line 11, column 4: junk after document element

Line 11 (eigentlich 12) ist der 2. <titel>-Tag.

Was soll das schon wieder heissen?

— geändert am 03.02.2013 17:23:07

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

03.02.2013 17:59:43 via Website

OK versuchen wir es mal anders. Ruf mal folgende Seite auf und lass Dein XML dort parsen.

http://xml.online-toolz.com/tools/xml-validator.php

Du wirst im unteren Feld eine Ausgabe erhalten, die lautet:
Invalid:
Reason:DOMDocument::loadXML() [<a href='domdocument.loadxml'>domdocument.loadxml</a>]: Validation failed: no DTD found !Extra content at the end of the document in Entity, line: 6

Bau mal folgendes mit ein:
<!DOCTYPE entrys [
<!ELEMENT entrys (entry)+>
<!ELEMENT entry (titel,text)>
<!ELEMENT titel (#PCDATA)>
<!ELEMENT text (#PCDATA)>
]>

Damit definierst Du, dass das Element <entry> mehrmals vorkommen darf. Was Du da siehst ist die sogenannte DTD (Document Type Definition) welche die Struktur Deines XML definiert.

Insgesamt schaut Dein XML dann so aus:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE entrys [
<!ELEMENT entrys (entry)+>
<!ELEMENT entry (titel,text)>
<!ELEMENT titel (#PCDATA)>
<!ELEMENT text (#PCDATA)>
]>
<entrys>

<entry>
<titel>Küchenumbau am 19.01.2013</titel>
<text>Am 19.Januar haben wir die Küche umgebaut:\n\n - Der Herd sowie einige Schränke wurden entfernt.\n - Ein Durchgang von der Bar zur Küche wurde gesägt.\n - Eine neue Wand zwischen Aufenthaltsraum und Küche wurde gebaut.\n</text>
</entry>

<entry>
<titel>Neue Facebookseite</titel>
<text>Zwei Anläufe sind gescheitert, daher nun der dritte: Das Freakhall hat ab heute eine neue Facebookseite. Diese soll aktueller gehalten werden und in naher Zukunft auch mit dieser Website verknüpft werden.</text>
</entry>

</entrys>
Dieses Dokument wird dann auch valide geparsed. Somit ist Dein XML einerseits "wellformed" und auch noch "valid" obendrein.

Die DTD kannst Du theoretisch auch weglassen. Ich hab sie hier mal zu Hilfe genommen, um Dir zu zeigen wie Du valide XML Dokumente erzeugen kannst, weil es dabei hilft, die Strukturen zu verstehen und bessere Fehlermeldungen produziert. Sie zwingt Dich sozusagen die selbstauferlegten Strukturen einzuhalten und andererseits auch es aus der Überlegung heraus auch richtig zu machen.

— geändert am 03.02.2013 18:05:08

lg Voss

Sebastian P.

Antworten
  • Forum-Beiträge: 72

03.02.2013 19:21:53 via Website

So jetzt ist der XML-Fehler verschwunden, die Funktion entries.size() gibt aber 0 zurück.

1//Ausschnitt aus NewsScreen.java:
2
3public List<Entry> entries = new ArrayList<Entry>();
4
5 //0=success 1=connection error 2=Parsing error
6 public int updateNews() {
7
8 //Create stream -> returns XML
9 URL url;
10 InputStream is;
11 try {
12 url = new URL("http://www.freakhall.ch/androidapp.php?cat=news");
13 is = url.openStream();
14 } catch (Throwable t) {
15 return 1;
16 }
17
18 //Parsing the XML
19 try {
20
21 XmlPullParser parser = Xml.newPullParser();
22 parser.setInput(is, null);
23 while (parser.next() != XmlPullParser.END_TAG) {
24 if (parser.getEventType() != XmlPullParser.END_TAG)
25 continue;
26 String name = parser.getName();
27 if (name.equalsIgnoreCase("entry")) {
28 entries.add(Entry.readEntry(parser));
29 } else {
30 Entry.skip(parser);
31 }
32 }
33
34 } catch (Throwable t) {
35 Log.e("NewsScreen /parser", "Error: "+ t.toString());
36 return 2;
37 }
38 return 0;
39 }

Was ist jetzt der Fehler? Der Code ist schliesslich von developer.android.com abgeleitet, viel falsch machen kann ich da ja nicht, oder?

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

03.02.2013 20:13:58 via Website

Versuch es doch mal selber .. bau dir Log Ausgaben ein und analysiere mal wo der Fehler liegt. Wenn andere Dir die Arbeit abnehmen wirst Du es nicht lernen.

lg Voss

Sebastian P.

Antworten
  • Forum-Beiträge: 72

04.02.2013 15:55:01 via Website

Danke... aber es geht jetzt. Der Fehler: ich hab bei einem Mal irgendwo im Code "title" statt "titel" geschrieben. Und den neuen Tag entries musste ich auch noch mit continue; behandeln.

Hier das Ergebnis:


Jetzt führe ich das mal weiter: das XML soll zuerst abgespeichert werden (Cache) und bei fehlender Internetverbindung geladen werden. Wie mache ich das und welche zusätzliche permission ausser android.permission.INTERNET muss ich noch definieren?


EDIT: Hab das ganze jetzt noch so umgebaut, dass die Netzwerkaktivitäten in einem seperaten Thread laufen:

1public InputStream is;
2 public int parseRes =0;
3
4 //0=success 1=connection error 2=Parsing error
5 public int updateNews() {
6
7 Thread thread = new Thread () {
8 @Override
9 public void run () {
10 try {
11 URL url = new URL("http://www.freakhall.ch/androidapp.php?cat=news");
12 is = url.openStream();
13 } catch (Throwable t) {
14 Log.e("NewsScreen /ucon", t.toString());
15 parseRes = 1;
16 return;
17 }
18 return;
19 }
20 };
21
22 thread.run();
23 if (parseRes == 1)
24 return 1;
25
26 //Parsing the XML..
27//Rest eher unwichtig für Problem

Wenn ich die App mit einem 4.2 AVD ausführe, schreibt mir LogCat:
NewsScreen /ucon android.os.NetworkOnMainThreadException

Wo finden da Netzwerkaktivitäten im MainThread statt? V.a. weil der Fehler ja im Netzwerkthread ausgegeben wird. Auf meinem 2.3.6-Gerät läuft alles problemlos.

— geändert am 04.02.2013 17:58:02

Antworten
  • Forum-Beiträge: 72

05.02.2013 19:01:38 via Website

So, jetzt funktioniert das öffnen der URL in den InputStream auch auf dem Emulator, nachdem ich die google developers Seite ein wenig durchsucht habe:

1package me.the_Seppi.freakhall;
2
3import java.io.InputStream;
4import java.net.URL;
5
6import android.os.AsyncTask;
7
8@SuppressWarnings("rawtypes")
9public class DownloadTask extends AsyncTask {
10
11 public InputStream is;
12
13 @Override
14 protected Object doInBackground(Object... args) {
15
16 try {
17 URL url = new URL((String) args[0]);
18 is = url.openStream();
19 } catch (Throwable t) {
20 return null;
21 }
22 return is;
23 }
24}


NewsScreen.java
1DownloadTask dl = new DownloadTask();
2 dl.execute("http://www.freakhall.ch/androidapp.php?cat=news");
3 try {
4 is = (InputStream) dl.get(10, TimeUnit.SECONDS);
5 } catch (Throwable t) {
6 Log.e("NewsScreen /ucon", t.toString());
7 return 1;
8 }
9
10 //Parsing the XML
11//.....

Aber ich bekomme tortzdem noch eine Fehlermeldung:
102-05 17:54:27.698: E/NewsScreen /parser(794): Error: org.xmlpull.v1.XmlPullParserException: Invalid stream or encoding: android.os.NetworkOnMainThreadException (position:START_DOCUMENT null@1:1 in java.io.InputStreamReader@40de9368) caused by: android.os.NetworkOnMainThreadException
202-05 17:54:27.698: E/NewsScreen(794): Failed parsing XML: 2

Heisst das, dass das parsen auch noch eine Netzwerkaktivität ist? Dann müsste ich den kompletten Parsingprozess in DownloadTask ausführen und als Rückgabewert die Liste der geparsten Einträge verwenden, oder?

Btw. ist das Timeout von 10s angemessen?

— geändert am 05.02.2013 20:36:22

Antworten
  • Forum-Beiträge: 72

05.02.2013 19:21:28 via Website

Sebastian P.
Heisst das, dass das parsen auch noch eine Netzwerkaktivität ist? Dann müsste ich den kompletten Parsingprozess in DownloadTask ausführen und als Rückgabewert die Liste der geparsten Einträge verwenden, oder?

das hiess es... ich habs getestet und es funktioniert. Jetzt muss ich das ganze noch auf die EventScreen.java anwenden und das Problem ist beseitigt.

— geändert am 07.02.2013 20:19:30

Antworten
  • Forum-Beiträge: 72

08.02.2013 18:52:57 via Website

Zum Abschluss:

Den Plan mit dem Abspeichern habe ich selbst hinbekommen (endlich etwas, was ich nur aufgrund der Informationen von android.com machen konne :D )
Ich habe das Problem so gelöst:

Wenn Interneterbindung vorhanden:
- Daten parsen
- Geparste Resultate
-->speichern (SharedPreferences)
-->anzeigen
Wenn keine Verbindung:
-Gespeicherte Daten einlesen und anzeigen.

Das jetzt noch als Abschluss, damit ist das Thema geklärt und beantwortet.

Antworten