Parsen in Android mit SimpleXML

U

u20i

Neues Mitglied
0
Hallo zusammen,

ich bin recht neu in der Andorid- und Java-Welt (komme von PHP) und würde gerne eine recht einfache App erstellen, die ein XML eines Rechners im lokalen Netzwerk regelmäßig auslesen und darauf basierend GUI-Elemente anpassen (Farbe ändern usw.) soll.

Nach einiger Recherche habe ich dieses Tutorial ( http://www.worldling.de/einfaches-xml-parsen-in-android-mit-simplexml-xml-parsing/) eingesetzt und mich in Eclipse, dem Emulator, Bibliotheken-Import usw. vorher soweit durchgearbeitet, dass die App auch ohne Fehler im LogCat läuft.

Leider habe ich dabei trotzdem eine Exception die in der Funktion parseXml() geworfen wird und komme nicht weiter, woran es liegt. Kann jemand helfen??

Versuch das Problem einzurgenzen: Breakpoints in der Data.java und in der o.g. Funktion unterhalb der Zeile

String xmlData = retrieve(url);


in er Main.java wurden nie erreicht. Ich wäre auch für Tipps dankbar, wie man solche Probleme noch besser eingrenzen kann. :cursing:

Main.java
Code:
[SNIP diverse import-zeilen]

public class Main extends Activity {

    private static final String url = "http://www.worldling.de/data.xml";
    TextView name;
    private DefaultHttpClient client = new DefaultHttpClient();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        name = (TextView) findViewById(R.id.tvForParsing);

        parseXml();
    }

    private void parseXml() {
        try {
            String xmlData = retrieve(url);
            Toast.makeText(this, xmlData, Toast.LENGTH_LONG).show();
            Serializer serializer = new Persister();

            Reader reader = new StringReader(xmlData);
            Data user = serializer.read(Data.class, reader);

            String tempName = user.getName();
            name.setText(tempName);
        } catch (Exception e) {
            Toast.makeText(this, "Error Occured", Toast.LENGTH_LONG).show();
        }

    }

    public String retrieve(String url) {

        HttpGet getRequest = new HttpGet(url);
        try {
            HttpResponse getResponse = client.execute(getRequest);
            final int statusCode = getResponse.getStatusLine().getStatusCode();

            if (statusCode != HttpStatus.SC_OK) {
                return null;
            }

            HttpEntity getResponseEntity = getResponse.getEntity();
            if (getResponseEntity != null) {
                return EntityUtils.toString(getResponseEntity);
            }
        } catch (IOException e) {
            getRequest.abort();
            Log.w(getClass().getSimpleName(), "Error for URL " + url, e);
        }
        return null;

    }
}
Data.java
Code:
[SNIP diverse import-zeilen]  

  
  
@Root  
public class Data {  
  
    public Data(){  
        super();  
    }  
  
    public Data(String name){  
        this.name = name;  
    }  
  
    @Element  
    private String name;  
  
    public String getName() {  
        return name;  
    }  
}
***
Danke im Voraus!
 
Lass mich raten: Die Exception besagt, dass Netzwerkverkehr im GUI Thread verboten ist.
Lösung: AsyncTask benutzen.

Verzeih' mir, dass ich so kurz angebunden bin, aber das ist das Problem bei jedem zweiten Thread hier.
 
Mein gepinnter thread scheint nicht zu helfen...

Gesendet von meinem GT-S5660 mit der Android-Hilfe.de App
 
Danke für die super schnellen Antworten!

Den gepinnten Thread hatte ich natürlich nicht gelesen... Asche auf mein Haupt. Mir ist auch klar, dass es für die fertige App nicht sinnvoll ist, Netzwerkverkehr im UI abzuhandeln. Ich dachte nur, zum Testen und auf "altem" Android könnte ich mir das ersparen.

Leider war die Exception "leer" so das ich nicht drauf gekommen bin. Und ich muss wohl noch mal Tutorials studieren, bis ich das richtig gekapselt hinbekomme. Im Moment fehlt mir noch die Verbindung vom Konzept zum eigenen Code... vielleicht sollte ich mich doch lieber aufs Konzeptionieren statt Coden beschränken. :cool2:

Wie auch immer: ich setze mich da noch mal dran und halte Euch auf dem Laufenden.

@DieGoldeneMitte: Verzeihung? Im Gegenteil, ich bin Dir dankbar für den Hinweis!
 
So, ich habe es noch mal versucht und AsyncTask eingebaut. Damit läuft es weiter und ich sehe im Debug, dass parseXML() mit Daten aufgerufen wird. Trotzdem geht dann etwas schief, das ich noch nicht verstehe :mad2: und Breakpoints in der Data.java werden nie erreicht.

Wäre für Hilfe und Hinweise zum eigenen Eingrenzen mittels Eclipse dankbar.

Main.java
Code:
import java.io.*;
import java.net.URI;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class Main extends Activity {

    public static final String url = "http://www.worldling.de/data.xml";
    TextView name;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        readWebpage(url);
        // name = (TextView) findViewById(R.id.tvForParsing);
        
}
    
    public void readWebpage(String string) {
        DownloadWebPageTask task = new DownloadWebPageTask();
        task.execute(new String[] { url });
        // parseXml();
    }
    
    private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... urls) {
          String response = "";
          for (String url : urls) {
            DefaultHttpClient client = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);
            try {
              HttpResponse execute = client.execute(httpGet);
              InputStream content = execute.getEntity().getContent();

              BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
              String s = "";
              while ((s = buffer.readLine()) != null) {
                response += s;
              }

            } catch (Exception e) {
              e.printStackTrace();
            }
          }
          return response;
        }

        @Override
        protected void onPostExecute(String response) {
            parseXml(response.toString());
        }
      }

    public void parseXml(String xmlData) {
        try {
            // String xmlData = retrieve(url);
            Toast.makeText(this, xmlData, Toast.LENGTH_LONG).show();
            Serializer serializer = new Persister();

            Reader reader = new StringReader(xmlData);
            Data user = serializer.read(Data.class, reader);

            String tempName = user.getName();
            name.setText(tempName);
        } catch (Exception e) {
            
            Toast.makeText(this, "Fehler", Toast.LENGTH_LONG).show();
        }

    }

    
    }
Logcat:
Code:
03-02 11:16:07.948: W/ActivityThread(817): Application de.rbtest.rbmobiwall is waiting for the debugger on port 8100...
03-02 11:16:07.987: I/System.out(817): Sending WAIT chunk
03-02 11:16:08.008: I/dalvikvm(817): Debugger is active
03-02 11:16:08.187: I/System.out(817): Debugger has connected
03-02 11:16:08.187: I/System.out(817): waiting for debugger to settle...
03-02 11:16:08.397: I/System.out(817): waiting for debugger to settle...
03-02 11:16:08.597: I/System.out(817): waiting for debugger to settle...
03-02 11:16:08.807: I/System.out(817): waiting for debugger to settle...
03-02 11:16:09.007: I/System.out(817): waiting for debugger to settle...
03-02 11:16:09.207: I/System.out(817): waiting for debugger to settle...
03-02 11:16:09.417: I/System.out(817): waiting for debugger to settle...
03-02 11:16:09.617: I/System.out(817): waiting for debugger to settle...
03-02 11:16:09.817: I/System.out(817): waiting for debugger to settle...
03-02 11:16:10.028: I/System.out(817): waiting for debugger to settle...
03-02 11:16:10.227: I/System.out(817): debugger has settled (1465)
03-02 11:16:10.967: E/dalvikvm(817): Could not find class 'org.simpleframework.xml.core.Persister', referenced from method de.rbtest.rbmobiwall.Main.parseXml
03-02 11:16:10.977: W/dalvikvm(817): VFY: unable to resolve new-instance 567 (Lorg/simpleframework/xml/core/Persister;) in Lde/rbtest/rbmobiwall/Main;
03-02 11:16:10.977: D/dalvikvm(817): VFY: replacing opcode 0x22 at 0x0009
03-02 11:16:11.077: D/dalvikvm(817): DexOpt: unable to opt direct call 0x0e00 at 0x0b in Lde/rbtest/rbmobiwall/Main;.parseXml
03-02 11:16:14.328: D/gralloc_goldfish(817): Emulator without GPU emulation detected.
03-02 11:18:59.687: D/dalvikvm(817): GC_CONCURRENT freed 127K, 9% free 2704K/2956K, paused 75ms+91ms, total 270ms
03-02 11:20:47.082: D/AndroidRuntime(817): Shutting down VM
03-02 11:20:47.082: W/dalvikvm(817): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
03-02 11:20:56.696: E/AndroidRuntime(817): FATAL EXCEPTION: main
03-02 11:20:56.696: E/AndroidRuntime(817): java.lang.NoClassDefFoundError: org.simpleframework.xml.core.Persister
03-02 11:20:56.696: E/AndroidRuntime(817):     at de.rbtest.rbmobiwall.Main.parseXml(Main.java:79)
03-02 11:20:56.696: E/AndroidRuntime(817):     at de.rbtest.rbmobiwall.Main$DownloadWebPageTask.onPostExecute(Main.java:71)
03-02 11:20:56.696: E/AndroidRuntime(817):     at de.rbtest.rbmobiwall.Main$DownloadWebPageTask.onPostExecute(Main.java:1)
03-02 11:20:56.696: E/AndroidRuntime(817):     at android.os.AsyncTask.finish(AsyncTask.java:631)
03-02 11:20:56.696: E/AndroidRuntime(817):     at android.os.AsyncTask.access$600(AsyncTask.java:177)
03-02 11:20:56.696: E/AndroidRuntime(817):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
03-02 11:20:56.696: E/AndroidRuntime(817):     at android.os.Handler.dispatchMessage(Handler.java:99)
03-02 11:20:56.696: E/AndroidRuntime(817):     at android.os.Looper.loop(Looper.java:137)
03-02 11:20:56.696: E/AndroidRuntime(817):     at android.app.ActivityThread.main(ActivityThread.java:5041)
03-02 11:20:56.696: E/AndroidRuntime(817):     at java.lang.reflect.Method.invokeNative(Native Method)
03-02 11:20:56.696: E/AndroidRuntime(817):     at java.lang.reflect.Method.invoke(Method.java:511)
03-02 11:20:56.696: E/AndroidRuntime(817):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
03-02 11:20:56.696: E/AndroidRuntime(817):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
03-02 11:20:56.696: E/AndroidRuntime(817):     at dalvik.system.NativeStart.main(Native Method)
 
Hi,

der Stacktrace sagt dir:
java.lang.NoClassDefFoundError: org.simpleframework.xml.core.Persister

Heißt soviel wie "Klasse aus dem Simple-Framework" nicht gefunden.
Du hast die Lib nicht richtig eingebunden.
Die "SimpleXXX.jar" muss unterhalb von deinem Projekt in "Android Dependencies" auftauchen.
 
Danke für den Hinweis. Vermutlich mein "Anfängerfehler Nr. 2 " - sie steht bei mir nur unter "Referencde Libraries" aber nicht unter "Android Dependencies". Nur über "Build Path" / "Configure..." kann ich sie leider unter "Android Dependencies" auch nicht eränzen?! Nach dem ich sie aber unter "Order and Export" auch angehakt habe, lief es weiter. Ich nehme mal an, dass war dieser Fehler, vielen Dank!

Ich hoffe, wir kommen dann langsam zu den "wirklichen" Probemen beim Parsen?! Und falls jemand 'n Hinweis für mich hat, wie man Bibliotheken richtig einbindet, damit sowas nicht passiert, würde ich mich freuen.

Ich melde mich hier noch mal, wenn ich nicht weiter komme oder erfolgreich am Ende war - so lange es zum Thema passt.
 
Also ich mache n ordner libs kopiere die library da rein dann rechtsklick add to build path. Dann klappts bei mir.

Gesendet von meinem GT-S5660 mit der Android-Hilfe.de App
 
Hmm... naja ich werde das mal beobachten, wenn ich die Nerven behalte noch weitere Java / Android-Sachen zu entwicklen.

Erst mal vielen Dank für den 'Support' hier.

Und sollte jemand auf die Idee kommen, später meinen Code hier 1 zu 1 zu kopieren... bitte die auskommentierten Zeilen noch mal prüfen. Wenn man es so lässt, wie es hier steht, gibt's dann noch eine java.lang.nullpointerexception die sich aber leicht beheben lässt.

Thread ist aus meiner Sicht damit erledigt!
 
Jetzt habe ich wohl doch noch ein Problem, das eigentliche Parsen zu verstehen (http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php).

Das XML beginnt so:
Version=1.0.0.0(Infowall)
<Interpret>Madonna</Interpret><Titel> Like a Virgin</Titel><Intro>0</Intro>

[snip]

Meine Data.java sieht inzwischen so aus:

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;


@Root
Code:
public class Data {
    
    @Element
    private String Interpret;
  
    public Data(){  
        super();  
    }  
  
    public Data(String Interpret){  
        this.Interpret = Interpret;  
    }  
  
     public String getInterpret() {  
        return Interpret;  
    }  
}
Die Versionsinfo am Anfang schneide ich schon weg, damit es lesbar wird für den Parser. Trotzdem bekomme ich diese Exception:

org.simpleframework.xml.core.ValueRequiredException: Unable to satisfy @org.simpleframework.xml.Element(data=false, name=, required=true, type=void) on field 'Interpret'
[snip]


Ich habe zwar in der Doku zum SimpleXML gelesen, wie mit Feldern umgegangen werden kann, die optional sind. Aber hier ist "Interpret" doch vorhanden?! Was sagt mir also diese Exception?! Danke für Eure Geduld.
 
Schönen Sonntag zusammen:

nach meinem Wochenendschlaf habe ich das Problem frisch ausgeruht selbst gelöst. :) Problem war, dass das XML ja nicht "wohlgeformt" ist und auch kein "Root"-Tag hat. Bei meinem bisherigen Code müsste das "<Data>" heißen. Das Tag habe ich jetzt ergänzt ... dann funktioniert auch der SimpleXML-Parser so, wie gewollt.


Code:
            xmlData.substring(25);
            xmlData = "<Data>" + xmlData;
            Reader reader = new StringReader(xmlData.concat("</Data>"));
            Data user = serializer.read(Data.class, reader);

Für den Parser wir damit aus:
Version=1.0.0.0(Infowall)
<Interpret>Madonna</Interpret><Titel> Like a Virgin</Titel><Intro>0</Intro>

Das hier:
<Data>
<Interpret>Madonna</Interpret><Titel> Like a Virgin</Titel><Intro>0</Intro>
</Data>

Eleganter wäre es natürlich, man hätte gleich ein ordentliches XML. Da ich das aber nicht selbst schreibe, muss ich es vor dem Parsen korrigieren.

Außerdem braucht der Parser in der Data.java im Moment wohl noch für jedes Element eine Feld, daher war dies zu ergänzen:
Code:
@Element
private String Titel;
@Element
private int Intro;
 
Zuletzt bearbeitet:
Hallo,
will auch so etwas realisieren und bin grade mal über diesen Thread gestolpert.
Allerdings wird bei mir in einem Toast nur der Inhalt der XML nicht geparsed angezeigt und ein Fehler ausgespuckt, das war's.
Das ist mein Logcat:
Code:
03-14 21:40:07.930: D/libEGL(7147): loaded /system/lib/egl/libEGL_adreno200.so
03-14 21:40:07.940: D/libEGL(7147): loaded /system/lib/egl/libGLESv1_CM_adreno200.so
03-14 21:40:07.940: D/libEGL(7147): loaded /system/lib/egl/libGLESv2_adreno200.so
03-14 21:40:07.960: I/Adreno200-EGL(7147): <qeglDrvAPI_eglInitialize:294>: EGL 1.4 QUALCOMM build: AU_LINUX_ANDROID_JB.04.01.01.00.036_msm8960_JB_CL2644550_release_AU (CL2644550)
03-14 21:40:07.960: I/Adreno200-EGL(7147): Build Date: 07/31/12 Tue
03-14 21:40:07.960: I/Adreno200-EGL(7147): Local Branch: 
03-14 21:40:07.960: I/Adreno200-EGL(7147): Remote Branch: quic/master
03-14 21:40:07.960: I/Adreno200-EGL(7147): Local Patches: NONE
03-14 21:40:07.960: I/Adreno200-EGL(7147): Reconstruct Branch: AU_LINUX_ANDROID_JB.04.01.01.00.036 +  NOTHING
03-14 21:40:08.130: D/OpenGLRenderer(7147): Enabling debug mode 0
03-14 21:40:09.111: I/dalvikvm(7147): Could not find method javax.xml.stream.XMLInputFactory.newInstance, referenced from method org.simpleframework.xml.stream.StreamProvider.<init>
03-14 21:40:09.111: W/dalvikvm(7147): VFY: unable to resolve static method 3688: Ljavax/xml/stream/XMLInputFactory;.newInstance ()Ljavax/xml/stream/XMLInputFactory;
03-14 21:40:09.111: D/dalvikvm(7147): VFY: replacing opcode 0x71 at 0x0003
03-14 21:40:09.111: W/dalvikvm(7147): VFY: unable to find class referenced in signature (Ljavax/xml/stream/XMLEventReader;)
03-14 21:40:09.111: W/dalvikvm(7147): VFY: unable to find class referenced in signature (Ljavax/xml/stream/XMLEventReader;)
03-14 21:40:09.111: I/dalvikvm(7147): Could not find method javax.xml.stream.XMLInputFactory.createXMLEventReader, referenced from method org.simpleframework.xml.stream.StreamProvider.provide
03-14 21:40:09.111: W/dalvikvm(7147): VFY: unable to resolve virtual method 3686: Ljavax/xml/stream/XMLInputFactory;.createXMLEventReader (Ljava/io/InputStream;)Ljavax/xml/stream/XMLEventReader;
03-14 21:40:09.111: D/dalvikvm(7147): VFY: replacing opcode 0x6e at 0x0002
03-14 21:40:09.111: I/dalvikvm(7147): Could not find method javax.xml.stream.XMLInputFactory.createXMLEventReader, referenced from method org.simpleframework.xml.stream.StreamProvider.provide
03-14 21:40:09.111: W/dalvikvm(7147): VFY: unable to resolve virtual method 3687: Ljavax/xml/stream/XMLInputFactory;.createXMLEventReader (Ljava/io/Reader;)Ljavax/xml/stream/XMLEventReader;
03-14 21:40:09.111: D/dalvikvm(7147): VFY: replacing opcode 0x6e at 0x0002

Danke für euere Hilfe,
Yannik
 
Keiner 'ne Idee?
 

Ähnliche Themen

D
Antworten
23
Aufrufe
2.561
Data2006
D
B
Antworten
4
Aufrufe
496
bb321
B
FabianDev
Antworten
5
Aufrufe
561
swa00
swa00
Zurück
Oben Unten