Daten von (Web)Server verarbeiten/anzeigen

  • 8 Antworten
  • Letztes Antwortdatum
D

dadom

Neues Mitglied
0
Hallo zusammen,

ich beschäftige mich erst seit wenigen Wochen mit dem entwickeln einer App für Android und habe deshalb ständig viele, viele Fragen.
Da man bei den meisten Fragen sich "einfach" nur Google wenden muss, aber leider ich halt nicht immer genau weiß nach was ich überhaupt suchen muss probiere ich es mal auf diesem Wege. Ich habe schon "viel" mit html/php gemacht konnte mir auch schon bei dem einen oder anderen Shell-Script für den Raspberry Pi weiterhelfen. Leider stehe ich nach wie vor mit Java auf Kriegsfuss...

Jetzt zu meinem Problem:

Ich würde gerne mit meiner App eine einfache/kurze Zeichenkette "live" anzeigen lassen, welche von einer php-Datei aus dem Internet stammt.

Die php-Datei wäre z.B. so aufgebaut:
PHP:
<?
[...]
print 'Wert1;'.$wert1;
?>

Diesen Wert1 möchte ich jetzt in ein TextView einbinden. Optimal wäre es wenn sich in der App der Wert ändern, sobald er sich Online auch ändert aber das wäre jetzt schon einen Schritt zu weit.

Hier im Forum bin ich auf folgenden Code gestossen bei dem ich dachte, dass er mir weiterhilft. Er stammt auf folgendem Thema klick
Code:
       try {
            URL url = new URL("http://domain.de/test/index.php");
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
            String line = "";
            while ((line = bufferedReader.readLine()) != null) {
                // Code zur Verarbeitung der Zeile
                String[] keyValueString = line.split("\\|");
                String[] keyValue1 = keyValueString[0].split(";");
                String[] keyValue2 = keyValueString[1].split(";");
                

                
                // Arbeite mit diesen Werten weiter...
            }
        } catch (MalformedURLException e) {
            // fange Fehler ab
        } catch (IOException e) {
            // fange Fehler ab
        } catch (ArrayIndexOutOfBoundsException e) {
            // fange Fehler ab
        }
        
       TextView ausgabe = (TextView) findViewById(R.id.textView5);
       ausgabe.setText(keyValue1);

Leider wird bei mir im Eclipse in der letzten Zeile das "keyValue1" immer rot unterstrichen mit der Meldung "Cannot be resolved". Aber die wird doch weiter oben mit String deklariert.

Wenn hier jemand eine Lösung hätte wäre ich sehr Dankbar. Da ich ja am Ende die Werte "live" von der Webseite anzeigen möchte ohne, dass der Anwender irgendeinen Button etc. drücken muss bin ich mir noch nicht so sicher ob dies überhaupt der richtige Weg ist. Wenn hier jemand ein Schlagwort oder gar einen Link zu einer besseren Lösung hätte wäre ich auch sehr dankbar.

Schon mal ein Danke fürs unterstützen.
 
Der Code war spezifisch für ein spezielles Problem, den kann man etwas vereinfachen (ungetestet):

Code:
[B]StringBuilder str = new StringBuilder();[/B]

try {
    URL url = new URL("http://domain.de/test/index.php");
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
    String line = "";
    while ((line = bufferedReader.readLine()) != null) {
        [B]str.append(line);[/B]
    }
} catch (MalformedURLException e) {
    // fange Fehler ab
} catch (IOException e) {
    // fange Fehler ab
} catch (ArrayIndexOutOfBoundsException e) {
    // fange Fehler ab
}

TextView ausgabe = (TextView) findViewById(R.id.textView5);
ausgabe.setText([B]str.toString()[/B]);

Der Grund, warum bei dir keyValue1 unresolved war: Es wird zwar weiter oben deklariert, aber innerhalb einer while-Schleife. Das heisst, die Variable existiert nur in diesem Block.

Ausserdem ist es gut möglich, dass deine App abstürzt, sobald sie versucht, Daten aus dem Internet zu laden. Das würde dann daran liegen, dass Android keine Netzwerkoperationen im Haupt-Thread der App erlaubt. Das müsste man dann in einen eigenen Thread auslagern. Stichwort: AsyncTask

Und zur Live-Darstellung: Die einfachste Lösung wäre ein Poll-Verfahren. Deine App würde einfach alle x Sekunden die Daten neu vom Server holen. Schöner wäre dann das Push-Verfahren, wo der Server die Daten an die App sendet, sobald sich etwas ändert. Das ist aber etwas aufwändiger zu entwickeln, weil es natürlich auch entsprechende Server-Anpassungen braucht.
 
Zoopa schrieb:
Der Code war spezifisch für ein spezielles Problem, den kann man etwas vereinfachen (ungetestet):

Der Grund, warum bei dir keyValue1 unresolved war: Es wird zwar weiter oben deklariert, aber innerhalb einer while-Schleife. Das heisst, die Variable existiert nur in diesem Block.

Und wenn mich nicht alles täuscht auch weil sie im try{} Block ist.
Und du den Wert hinterher ausserhalb des try-Blocks benutzt.

Das dürfte auch nicht funktionieren.
 
erstmal ein Danke an euch.

Zoopa schrieb:
Ausserdem ist es gut möglich, dass deine App abstürzt, sobald sie versucht, Daten aus dem Internet zu laden. Das würde dann daran liegen, dass Android keine Netzwerkoperationen im Haupt-Thread der App erlaubt. Das müsste man dann in einen eigenen Thread auslagern. Stichwort: AsyncTask

Und zur Live-Darstellung: Die einfachste Lösung wäre ein Poll-Verfahren. Deine App würde einfach alle x Sekunden die Daten neu vom Server holen. Schöner wäre dann das Push-Verfahren, wo der Server die Daten an die App sendet, sobald sich etwas ändert. Das ist aber etwas aufwändiger zu entwickeln, weil es natürlich auch entsprechende Server-Anpassungen braucht.

Das mit deinem Code hat gut funktioniert. Habe noch eine Anleitung für einen Thread gefunden, damit ich mit webContent.start(); alles wie gewollt anzeigen lassen kann.

Mit der automatischen Aktualisierung war ich heute noch nicht so erfolgreich. Da das ganze ja nur eine Spielerei ist habe ich versucht den Thread einfach jede Sekunde aufzurufen. Oder ist das zu oft? (Smartphone->AP->Router->Server->Router->AP->Smartphone)

Sobald ich eine Lösung gefunden habe meinen Thread regelmäßig zu starten poste ich das hier noch als komplette Lösung.
Mein Respeckt vor Java-Entwicklern wächst auf jeden Fall von Tag zu Tag ;)
 
Jede Sekunde dürfte zu oft sein.
Ich würde minimum 5 sekunden nehmen.
Wobei das deinen Akku ziemlich schnell ziemlich leer machen dürfte ;)

Bei einer Sekunde kann es sein, dass der Server die vorherige Anfrage noch gar nicht bearbeitet hat. Da muss das Netzwerk nur einmal "Schluckauf" haben ^^
 
Ich habe den Thread wie folgt aufgebaut:

Code:
	Thread testThread = new Thread(new Runnable() {
	    @Override
	    public void run() {    	
	        //doLongAndComplicatedTask();
	        StringBuilder str = new StringBuilder();

	        try {
	            URL url = new URL("http://domain.de/test/index.php");
	            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
	            String line = "";
	            while ((line = bufferedReader.readLine()) != null) {
	                str.append(line);
	            }
	            		        
	        } catch (MalformedURLException e) {
	            // fange Fehler ab
	        } catch (IOException e) {
	            // fange Fehler ab
	        } catch (ArrayIndexOutOfBoundsException e) {
	            // fange Fehler ab
	        }

	        TextView ausgabe = (TextView) findViewById(R.id.textView4);
	        ausgabe.setText(str.toString());
	        
	    }
	    
	});

Und mit folgendem Code rufe ich den Thread auf:

Code:
testThread.start();

Jetzt habe ich nur das problem, dass ich ja den Thread nur einmal aufrufen darf/kann. Zumindestens habe ich das so gelesen/verstanden. Und bei mir stürtzt die App auch immer ab sobald ich versuche den Thread erneut zu starten.

Da 5sec zum Warten eher zu lange ist und es trotzdem nicht Akku schonend ist, hätte ich das versucht manuel per Button anzustossen. Also die Activity wird geladen holt sich den aktuellen Wert aus dem Internet und wenn der Anwender den Button drück wird der Wert erneut abgeholt. Aber dafür müsste ich ja den Thread ebenfalls erneut starten was nicht geht (oder ich falsch machen).
 
Du kannst den Thread neustarten nur nicht das gleiche Objekt.
Wenn du den neu erstellst, kannst du den ganz normal nochmal starten.
Bau dir am besten eine Methode, die dir den Thread zurück gibt oder aber bau dir ne eigene Thread Klasse die du dann mit new DeinThread() neu baust.
 
Danke amfa.
Bin jetzt einen "großen" Schritt weiter gekommen.

Nach vielen Anläufen bei google und noch mehr Versuchen habe ich es wie folgt hinbekommen.
Läuft zwar jetzt doch Zeitgesteuert :unsure: aber anders habe ich es nicht hinbekommen. Läuft aber sogar noch bei 1sec.

Code:
[...] import [...]
@SuppressLint("HandlerLeak")
public class MainActivity extends Activity {

	private static final String TAG = MainActivity.class.getSimpleName();
	private Handler uiHandler = new UIHandler();

	
	class UIHandler extends Handler {
		
		@Override
		public void handleMessage(Message msg) {
			// a message is received; update UI text view
			TextView webContent = (TextView) findViewById(R.id.textView4);
			webContent.setText(msg.obj.toString());
			super.handleMessage(msg);
		}
	}
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);


			Runnable r = new Runnable() {
			@Override
			public void run() {
			while (true) {
			Log.d(TAG, "Daten abrufen");
		        StringBuilder str = new StringBuilder();

		        try {
		            URL url = new URL("http://domain/test/index.php");
		            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
		            String line = "";
		            while ((line = bufferedReader.readLine()) != null) {
		                str.append(line);
		            }
		            		        
		        } catch (MalformedURLException e) {
		            // fange Fehler ab
		        } catch (IOException e) {
		            // fange Fehler ab
		        } catch (ArrayIndexOutOfBoundsException e) {
		            // fange Fehler ab
		        }
		        Log.d(TAG, str.toString());
		        Message msg = Message.obtain(uiHandler);
	                   msg.obj = str.toString();
	                   uiHandler.sendMessage(msg);
		        
		        try {
		        Thread.sleep(1000);
		        }
		        catch (InterruptedException e) {
			finish();
		        }
		        
		        
			}
		      }
		};
        
		Thread t = new Thread(r);
		t.start();
		Log.d(TAG, "Thread wurde gestartet");
         }
}
Weiß zwar jetzt nicht ob das so die saubere Lösung ist aber zum probieren reicht es erst mal.

Als nächstes muss ich noch irgendwie die Ziffern welche ich nun erhalte und anzeige in einer if auswerten. Aber für heute reicht es erst mal :thumbsup:
 
Zurück
Oben Unten