Webseitenquelltext anzeigen

B

beginner98

Neues Mitglied
0
Hey Leute,
ich arbeite zurzeit an einer App, die eine Zahl aus einer Webseite anzeigen soll.
Als Java Applikation hat der Code funktioniert, doch als eine Android Applikation scheitert der Code. Die Applikation stürzt jedes Mal ab, sobald der Code durch einen Klick auf einen Button verarbeitet wird.

Ich hoffe auf Hilfe,
Danke im Voraus!

Code:
package irfendwas;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.Window;
import android.widget.TextView;

public class MainActivity extends Activity {
	
	@Override
	 protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
          
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
       
      /*this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                  WindowManager.LayoutParams.FLAG_FULLSCREEN);//int flag, int mask 
      */  
        setContentView(R.layout.activity_main);
       
    }  

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	public void retros(View view) throws Exception {
		 String nummer = "wasauchimmer";
		    URL url = new URL("http://xy.z/b.php?a=" + nummer);
		    HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();

		    InputStream inStrm = httpCon.getInputStream();
		    TextView text = (TextView) findViewById(R.id.textView2);
		    int ch;
		 
			while (((ch = inStrm.read()) != -1))
		text.setText((char) ch);
		inStrm.close();
			}
		 }
 
Jap, ist richtig!
 
Hi,

ich glaube was StefMa damit ausdrücken wollte war:
Es fehlt die Fehlermeldung/Locat.

Es gibt aber mehrere Fehlerursachen.
Hast du die Internetpermission in der Manifest?
Du machst einen HTTP-Aufruf nicht in einerm AsynchTask
Ohne dein layout-XML File kann man nicht sehen wann retros() aufgerufen wird.
Einfach eine Exception weiterzuwerfen ist in diesem Fall auch nicht gut.
 
Kardroid schrieb:
Hi,

ich glaube was StefMa damit ausdrücken wollte war:
Es fehlt die Fehlermeldung/Locat.

Es gibt aber mehrere Fehlerursachen.
Hast du die Internetpermission in der Manifest?
Du machst einen HTTP-Aufruf nicht in einerm AsynchTask
Ohne dein layout-XML File kann man nicht sehen wann retros() aufgerufen wird.
Einfach eine Exception weiterzuwerfen ist in diesem Fall auch nicht gut.

Hallo Kardroid,
die Methode retros wird durch einen Klick auf einen Button aufgerufen.
Die Internetpermission ist bereits im Manifest.
Wenn nicht in einem AsynchTask, wo dann?
 
@Beginner

Du musst Netzwerkzugriffe seit Android 3.x aus dem Haupt Thread auslagern. Sprich GUI Sachen und Netzwerksachen müssen getrennt laufen, damit deine App immer >responsive< bleibt und nicht den User "ausbremst".

Das Auslagern erreichst du mit einem AsyncTask oder auch durch das Nutzen eines Threads.

Wobei Asynctask eine recht nette Lösung ist, er stellt Dir einige Helpermethoden zur Verfügung welche vor, während und nach dem Starten des Hintergrundoperation aufgerufen werden (Stichwort: Fortschrittsbalken / Progressbar ect pp)
 
killphil75 schrieb:
@Beginner

Du musst Netzwerkzugriffe seit Android 3.x aus dem Haupt Thread auslagern. Sprich GUI Sachen und Netzwerksachen müssen getrennt laufen, damit deine App immer >responsive< bleibt und nicht den User "ausbremst".

Das Auslagern erreichst du mit einem AsyncTask oder auch durch das Nutzen eines Threads.

Wobei Asynctask eine recht nette Lösung ist, er stellt Dir einige Helpermethoden zur Verfügung welche vor, während und nach dem Starten des Hintergrundoperation aufgerufen werden (Stichwort: Fortschrittsbalken / Progressbar ect pp)

Danke dir.
Ich habe jetzt sehr viel mithilfe von Suchmaschinen gefunden, allerdings sind alle Tutorials unverständlich. Könnte mir jemand Asynctask erklären?
 
Ungern, dann lernst du ja nix.

Was genau verstehst du denn nicht?
Die Seite von Android Developers erklärt doch eigentlich ziemlich gut wie es geht.

EDIT:
Ich konnte es doch nicht lassen
Ungetestet und ohne Garantie und versprich mir, das du versuchst zu verstehen was das Ding macht ;)
Du kannst auch wenn es damit funktionieren sollte gerne nachfragen was wie warum gemacht wird.
Code:
    public void retros(View view) throws Exception {
        new AsyncTask<String, Void, String>() {

            @Override
            protected String doInBackground(String... params) {
                URL url;
                try {
                    url = new URL("http://xy.z/b.php?a=" + params[0]);
                    HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
    
                    InputStream inStrm = httpCon.getInputStream();
                    StringBuilder result = new StringBuilder();
                    int ch;
                 
                    while (((ch = inStrm.read()) != -1)) {
                        result.append((char)ch);
                    }
                    inStrm.close();
                
                    return result.toString();
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return "Fehler";
            }
            
            @Override
            protected void onPostExecute(String result) {
                TextView text = (TextView) findViewById(R.id.textView2);
                text.setText(result);
            }
            
        }.execute("deinenummer");
 
amfa schrieb:
Ungern, dann lernst du ja nix.

Was genau verstehst du denn nicht?
Die Seite von Android Developers erklärt doch eigentlich ziemlich gut wie es geht.

EDIT:
Ich konnte es doch nicht lassen
Ungetestet und ohne Garantie und versprich mir, das du versuchst zu verstehen was das Ding macht ;)
Du kannst auch wenn es damit funktionieren sollte gerne nachfragen was wie warum gemacht wird.
Code:
    public void retros(View view) throws Exception {
        new AsyncTask<String, Void, String>() {

            @Override
            protected String doInBackground(String... params) {
                URL url;
                try {
                    url = new URL("http://xy.z/b.php?a=" + params[0]);
                    HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
    
                    InputStream inStrm = httpCon.getInputStream();
                    StringBuilder result = new StringBuilder();
                    int ch;
                 
                    while (((ch = inStrm.read()) != -1)) {
                        result.append((char)ch);
                    }
                    inStrm.close();
                
                    return result.toString();
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return "Fehler";
            }
            
            @Override
            protected void onPostExecute(String result) {
                TextView text = (TextView) findViewById(R.id.textView2);
                text.setText(result);
            }
            
        }.execute("deinenummer");
Hey amfa, vielen Dank!!
Der Code hat einwandfrei funktioniert, es wird nun "Spieler Elvo ist auf Level 3" ausgegeben.

Hat jemand eine Idee, wie ich nun das Level von mehreren Spielern anzeigen lasse? Es sind 10 Spieler, die Anzeige sollte nach dem Level sortiert werden.

Ich habe bereits mit einigen Arraylists rumgeknobelt, jedoch nichts erreicht.
 
Verstehe jetzt dein Problem nicht.

Du liest doch aus der Webseite den Zahlenwert aus.
Was hindert Dich daran das Skript mehrmals aufzurufen und die Ergebnisse in eine Arraylist zu packen ??
Diese Liste sortierst du dann.

Stichwort: Comparable
 
killphil75 schrieb:
Verstehe jetzt dein Problem nicht.

Du liest doch aus der Webseite den Zahlenwert aus.
Was hindert Dich daran das Skript mehrmals aufzurufen und die Ergebnisse in eine Arraylist zu packen ??
Diese Liste sortierst du dann.

Stichwort: Comparable

Nehmen wir an, ich würde folgenden Code benutzen:
Code:
}.execute("spieler-elox", "spieler-hydra");

Was müsste ich dann anstatt params[0] im folgenden Code verwenden:
Code:
url = new URL("http://xy.z/b.php?a=" + params[0]);

Und wie könnte ich die results dann unterscheiden?
Ich müsste sie in eine Arrayliste eintragen, das sähe dann ungefähr folgendermaßen aus:
result1, resul2, result3

Die Werte in der Arrayliste zu ordnen würde ich, denke ich mal, auch selber schaffen.
 
hmm.. was heißt nichts erreicht?
Du musst doch nur statt einem parameter 10 übergeben.
Dann in einer schleife 10 mal den webservice aufrufen (wobei hier eine Methode besser wäre, die dir sofort alle Spieler zurück gibt, das musst du aber auf webservice seite machen.)
und statt
return result.toString()
machst du
deineArrayListe.add(result.ToString()).

Oder aber noch besser wäre es wenn du dir eigene Spieler Klasse erstellst, diese haben dann erst mal nur 2 eigenschaften "Name" und "Level"
dann kannst du nämlich comparable implementieren bzw die compare Methode und kannst da sagen du willst die Level vergleichen.

wenn du nur die Strings so komplett in die ArrayList packst wird das mit dem sortieren schwieriger da musste auch einen eigene Comparator schreiben

Code:
Collections.sort(list, new Comparator<String>() {     public int compare(String a, String b) {
    //hier musst du die Strings vergleichen und schauen welches level vorhanden ist
   return vergleichsErgebnis     }

Hier gibts ne deutsche Anleitung zum Comparator
Java Blog Buch : D) Objekte sortieren Comparator und Comparable
 
amfa schrieb:
hmm.. was heißt nichts erreicht?
Du musst doch nur statt einem parameter 10 übergeben.
Dann in einer schleife 10 mal den webservice aufrufen (wobei hier eine Methode besser wäre, die dir sofort alle Spieler zurück gibt, das musst du aber auf webservice seite machen.)
und statt
return result.toString()
machst du
deineArrayListe.add(result.ToString()).

Oder aber noch besser wäre es wenn du dir eigene Spieler Klasse erstellst, diese haben dann erst mal nur 2 eigenschaften "Name" und "Level"
dann kannst du nämlich comparable implementieren bzw die compare Methode und kannst da sagen du willst die Level vergleichen.

wenn du nur die Strings so komplett in die ArrayList packst wird das mit dem sortieren schwieriger da musste auch einen eigene Comparator schreiben

Code:
Collections.sort(list, new Comparator<String>() {     public int compare(String a, String b) {
    //hier musst du die Strings vergleichen und schauen welches level vorhanden ist
   return vergleichsErgebnis     }

Hier gibts ne deutsche Anleitung zum Comparator
Java Blog Buch : D) Objekte sortieren – Comparator und Comparable

Hey amfa,
wäre es möglich, nur ein mal die Seite aufzurufen und sofort alle Spielerlevel in eine Arrayliste zu packen o.ä.?

Ich habe es jetzt so versucht:
Code:
static List<String> array = new ArrayList<String>();

Im doInBackground String:
Code:
array.add(result.toString());

Und in der onPostExecute Methode:
Code:
int total = 0;
	            	
total += array.size();	            		            	
TextView text = (TextView) findViewById(R.id.textView2);
text.setText(total);


Leider stürzt meine App beim Aufruf nun ab, es wird in einem Alert ausgegeben: "angehalten".
 
Natürlich kannst du alle auf einmal abrufen, dazu musst du aber an der website was ändern. Hast du zugriff da drauf?
url = new URL("http://xy.z/b.php?a=" + params[0]);
Hier brauchst du halt einen passenden aufruf, ich kenn den Webservice halt nicht
Aber wenn der sowas hat wie http://xy.z/b.php=a=all
oder all.php ka das musst du selbst rausfinden.


Zum anderen funktioniert
text.setText(total) nicht, da total ein String ist und die Methode
setText(int) (also wenn du eine zahl übergibst)
setzt nicht die zahl da rein sondern sucht einen String mit der Id dieser Zahl.
String.valueOf(total) sollte funktionieren.

Ausserdem sollte deine Liste nicht static sein.


ansonsten musst du halte mehrere params an die doInBackground methode übergeben

dann kannst du mit
for (String parameter: params) {
//hier das gleiche machen wie für einen einzelnen user
url = new URL("http://xy.z/b.php?a=" + parameter);
//usw.
//statt return sb.toString()
list.add(sb.toString())
}

damit solltest du zumindest alle Spieler in die Liste bekommen
zum sortieren hab ich oben ja schon was geschrieben.
 
amfa schrieb:
Natürlich kannst du alle auf einmal abrufen, dazu musst du aber an der website was ändern. Hast du zugriff da drauf?
url = new URL("http://xy.z/b.php?a=" + params[0]);
Hier brauchst du halt einen passenden aufruf, ich kenn den Webservice halt nicht
Aber wenn der sowas hat wie http://xy.z/b.php=a=all
oder all.php ka das musst du selbst rausfinden.


Zum anderen funktioniert
text.setText(total) nicht, da total ein String ist und die Methode
setText(int) (also wenn du eine zahl übergibst)
setzt nicht die zahl da rein sondern sucht einen String mit der Id dieser Zahl.
String.valueOf(total) sollte funktionieren.

Ausserdem sollte deine Liste nicht static sein.


ansonsten musst du halte mehrere params an die doInBackground methode übergeben

dann kannst du mit
for (String parameter: params) {
//hier das gleiche machen wie für einen einzelnen user
url = new URL("http://xy.z/b.php?a=" + parameter);
//usw.
//statt return sb.toString()
list.add(sb.toString())
}

damit solltest du zumindest alle Spieler in die Liste bekommen
zum sortieren hab ich oben ja schon was geschrieben.

Super!! Ich habe das Button Event entfernt und lasse die Methode jede 10 Sekunden von einem Thread aufrufen.
So aktualisieren sich die Statistiken jede 10 Sekunden. Nun erhöht sich textView2 jede 10 Sekunden um 2, das heißt, dass unsere Arrayliste sich jetzt immer um 2 erhöht. Dann sind wir schon mal einen Schritt weiter.

Nun müsste unsere Arrayliste aber bei jedem neuen Aufruf der Methode geleert werden, oder? Damit wir das Ordnen später gut hinkriegen. Wäre es richtig, wenn ich dies mit der clear() Methode erledigen würde?

Wie rufe ich nun einen Wert von der Arrayliste auf?
Ich möchte die Werte ja in textViews ausgeben.

Zu deiner Frage: Ja, ich habe vollen Zugriff auf die Webseite.
Sie zieht die Daten direkt aus meiner Datenbank.
 
Zuletzt bearbeitet:
Dann bau dir auf der Webseite einfach einen Service, der dir alle Spieler als JSON zurück gibt, dann packst du die einfach in ein Spieler Objekt dort implentierst du comparable und baust die comparte methode so, dass er die level vergleicht.
Um Json zu verarbeiten empfehle ich Gson von Google super Framework, das den umgang mit Json extrem vereinfacht.
https://code.google.com/p/google-gson/


Was den Thread angeht:
Klingt erst mal nach einer schlechten Lösung, ändern sich die Werte denn so oft?
Wenn du alle 10 Sekunden eine HTTP Anfrage rausschickst kostet das Strom (Batterie) und Netzwerkverkehr der evtl unnötig ist.

Besser wäre da GCM, dann kann der Server beim handy bescheid sagen, wenn es neue Daten gibt:
Google Cloud Messaging for Android | Android Developers

Oder zumindest eine Methode mit der du abfragen kannst, ob es neue Daten gibt und nur dann den kompletten Abruf machst.

Die Arraylist kannst du mit .clear() leeren oder du erzeugst einfach jedesmal eine neue mit arrayList = new ArrayList().

Um Werte aus der ArrayList aufzurufen arrayList.get(i).

Ansonsten guck in die Doku dafür ist die ja vorhanden.
List (Java Platform SE 6)
 
amfa schrieb:
Dann bau dir auf der Webseite einfach einen Service, der dir alle Spieler als JSON zurück gibt, dann packst du die einfach in ein Spieler Objekt dort implentierst du comparable und baust die comparte methode so, dass er die level vergleicht.
Um Json zu verarbeiten empfehle ich Gson von Google super Framework, das den umgang mit Json extrem vereinfacht.
https://code.google.com/p/google-gson/


Was den Thread angeht:
Klingt erst mal nach einer schlechten Lösung, ändern sich die Werte denn so oft?
Wenn du alle 10 Sekunden eine HTTP Anfrage rausschickst kostet das Strom (Batterie) und Netzwerkverkehr der evtl unnötig ist.

Besser wäre da GCM, dann kann der Server beim handy bescheid sagen, wenn es neue Daten gibt:
Google Cloud Messaging for Android | Android Developers

Oder zumindest eine Methode mit der du abfragen kannst, ob es neue Daten gibt und nur dann den kompletten Abruf machst.

Die Arraylist kannst du mit .clear() leeren oder du erzeugst einfach jedesmal eine neue mit arrayList = new ArrayList().

Um Werte aus der ArrayList aufzurufen arrayList.get(i).

Ansonsten guck in die Doku dafür ist die ja vorhanden.
List (Java Platform SE 6)

So, sorry für die später Antwort, mir war es nicht möglich, an meiner App weiterzumachen.

Ich mache es lieber auf die einfache Art und rufe den Thread einfach jede Minute ab.

Meine Frage ist, wenn ich beim execute Befehl nun 2 Parameter einfüge:
Code:
execute("spieler-1", "spieler-2");

Dann wird der url String nicht verwendet, wie ich es will, er gibt dem Get Parameter 2 mal den Parameter spieler-1:
Code:
url = new URL("http://retroforce.de/retros2.php?retro=" + params[0]);

Wie kann ich den jetzigen Parameter aufrufen? D.h. der Parameter, der gerade den doInBackground String benutzt.
 
Liest du auch was ich schreibe?

for (String parameter: params) {
//hier das gleiche machen wie für einen einzelnen user
url = new URL("http://xy.z/b.php?a=" + parameter);
//usw.
//statt return sb.toString()
list.add(sb.toString())
}

natürlich hast du immer spieler-1 da stehen, wenn du immer params[0] nutzt.
spieler-2 steht vermutlich in params[1].

Oder du guckst in die Doku
AsyncTask | Android Developers
Da werden halt komplette URLs übergeben aber auch mehrere.

Es werden immer ALLE parameter in der doInBackground methode benutzt du bekommst ein Array mit den Parametern. Musst du nur noch da rausholen die Werte.
 
Ich habe ja alles soweit fertig, nur ich will noch die Werte der beiden TextViews ändern:

TextView textx = (TextView) findViewById(R.id.spieler-x);

text.setText(result);

Somit zeigt die TextView mit dem namen textx bzw. spieler-x schon mal das Level des Spielers X an, jetzt möchte ich aber noch, dass das Level vom Spieler - y auch noch in eine TextView kommt.
 
Zuletzt bearbeitet von einem Moderator:

Ähnliche Themen

D
  • Data2006
3 4 5
Antworten
84
Aufrufe
3.653
jogimuc
J
softwaretk
Antworten
3
Aufrufe
1.201
swa00
swa00
D
Antworten
1
Aufrufe
940
swa00
swa00
Zurück
Oben Unten