Nach empfang, weiter mit Variable arbeiten!?

  • 6 Antworten
  • Letztes Antwortdatum
M

mitch_HD2

Fortgeschrittenes Mitglied
1
Hallo..
ich empfange über UDP ein Byte....
nachdem ich das empfangen habe will ich damit weiter arbeiten...
aber wenn ich in meiner Receive() Funktion weiter arbeite stürzt meine app immer ab.
packe ich meine funktion mit den byte's hinter dem receive() dann arbeitet der mit dem leerem byte. also dem noch nicht


In meinen OnCreate()
Code:
....
...
..
if (new Ping().execute() != null){
				 	Log.d("MAtec","ping is OK");
					new UdpOnSend().execute(); 
					new TempSync().execute();
					
					if ((BufRec[14]&0x01)==1) Fragment2.btnlight1.setChecked(true);
					if ((BufRec[14]&0x02)==2) Fragment2.btnlight2.setChecked(true);
					if ((BufRec[14]&0x04)==4) Fragment3.btnlight3.setChecked(true);
					
					Log.d("MAtec","fertig");
					//bytetobool();
					
			}


und mein Receive() in einem Asynctask()
Code:
public static class TempSync extends AsyncTask<Object, Object, Object> {
	@Override
    protected Object doInBackground(Object... arg0) {
   
		try {
			Recieve();
			return true;
			//lampsync();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
        return null;
    }

}
..........
....
...
public static void Recieve() throws IOException{
	DatagramPacket p = new DatagramPacket(BufRec, BufRec.length);
	DatagramSocket s = new DatagramSocket(Port);
	s.receive(p);
	BufRecStr = new String(BufRec, 0, p.getLength());
	//Log.i("Udp Receive", BufRec);
	Log.d("Udp Receive", BufRecStr);
	TempRecIn = (BufRecStr.substring(0,5)+ " °C");
	TempRecOut = (BufRecStr.substring(6,11)+ " °C");

	Log.d("Udp Receive", Integer.toHexString(BufRec[14]));

//	if ((BufRec[14]&0x08)==8) Fragment3.btnlight4.setChecked(true);
	s.close();
	//bufrec2 = (byte) (BufRec[14]&0x01);
	//int test = BufRec[14]&1;
	Log.d("Udp Receive", "hallo "+ (BufRec[14]&0x01));
	Log.d("Udp Receive", "hallo "+ (BufRec[14]&0x02));
	Log.d("Udp Receive", "hallo "+ (BufRec[14]&0x04));
	Log.d("Udp Receive", "hallo "+ (BufRec[14]&0x08));

//	if ((byte) (BufRec[14]&0x01)==1)	Fragment2.btnlight1.setChecked(true);

	/// TESTLAUF
	fillTemps(TempRecIn,TempRecOut);
	///
}

Ich kann
if ((BufRec[14]&0x01)==1) Fragment2.btnlight1.setChecked(true);
nicht hinter
new TempSync().execute();
ausführen...

innerhalt der Receive() funktioniert es.. stürzt aber öfter ab
 
Hi,

was kommt denn für eine Fehlermeldung?
 
Ich vermute mal dein Hauptproblem ist das Verständnis von AsyncTask bzw. Threads allgemein.

Code:
new UdpOnSend().execute(); 
new TempSync().execute();
					
if ((BufRec[14]&0x01)==1) Fragment2.btnlight1.setChecked(true);
if ((BufRec[14]&0x02)==2) Fragment2.btnlight2.setChecked(true);
if ((BufRec[14]&0x04)==4) Fragment3.btnlight3.setChecked(true);

Der Sinn vom einem Thread liegt ja eben genau darin, dass der Code parallel ausgeführt wird. Nach der Zeile

Code:
new TempSync().execute();

wartet die Activity nicht darauf, das der Thread seine Arbeit fertig macht, sondern fährt gleich weiter mit der nächsten Zeile.

Wenn du aus dem AsyncTask etwas machen willst, was das GUI ändert, dann gibt es dafür extra die Methoden onPreExecute, onPostExecute und onProgressUpdate.

In deinem Fall könntest du zum Beispiel die Zeilen

Code:
if ((BufRec[14]&0x01)==1) Fragment2.btnlight1.setChecked(true);
if ((BufRec[14]&0x02)==2) Fragment2.btnlight2.setChecked(true);
if ((BufRec[14]&0x04)==4) Fragment3.btnlight3.setChecked(true);

in der onPostExecute Methode von TempSync ausführen. Zum einen garantierst du damit, dass der Code erst ausgeführt wird, nachdem doInBackground fertig ist. Zum Anderen änderst du damit dein GUI auch aus dem richtigen Thread.

Weitere Tipps:

Deine if-Abfrage wird nicht funktionieren. Erstens wartet (wie oben beschrieben) die Abfrage gar nicht darauf, bis der Ping abgeschlossen ist. Und zweitens macht der Null-Check auch keinen Sinn, weil die execute-Methode die Instanz des AsyncTask zurückgibt, die in diesem Moment gar nie null sein kann (sonst hätte man den Task gar nie instanzieren können).

Ich denke du hast beim Ping auch sowas wie bei TempSync gemacht, wo du in der doInBackground-Methode etwas zurückgibst. Der Wert wird aber an die Methode onPostExecute weitergegeben, und ist nicht der Rückgabewert von execute.

Ausserdem ist es keine gute Idee und auch unschön, alles static zu machen.
 
ui

danke für die tipps:)
ja bin ja eigentlich überhaupt kein programmierer...
mache das nur so bisschen nebenbei aber dafür bin ich schon ziemlich weit hehe..

nun zum thema...

wenn ich in meinen onPostExecute() etwas schreibe... irgendein Log oder kommentar...
der wird garnicht ausgeführt?
warum nicht?
hab ich was vergessen?

Code:
public static class TempSync extends AsyncTask<Object, Object, Object> {
	@Override
	protected Object doInBackground(Object... arg0) {
		try {
			Recieve();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
    }
	
	protected void onPostExecute(byte result){
		Log.d("Udp Receive", "onPostExecute");
		
	}
}
 
Schwer zu sagen was Receive() ist aber ich würde mal sagen das er gar nicht erst in die postexecute geht weil im doinbackground etwas schief geht und was durch die try catch abgefangen wird.
 
Was macht denn
fillTemps() ?

Wenn in Receive irgendwas schief geht müsste er eigentlich trotzdem in onPostExecute gehen, gerade wegen dem Abfangen der Exception (es sei denn es fliegt eine andere als IOException)
Und wie groß ist BufRec?
Das Problem könnte sein, dass die receive Methode vom DatagramSocket solange blockiert, bis die ganze nachricht angekommen ist (also bis BufRec.length erreicht ist), wenn dort nun weniger Daten ankommen wartet die einfach weiter bis genug Daten da sind.
Wenn nun auch nur ein Byte verloren geht und deine Nachricht somit kürzer ist als du planst blockiert die Methode quasi für immer und wird niemals fertig.
Du hängst also für immer in der Zeile:
s.receive(p);

Das müsstest du im Debugger eigentlich sehen können, wenn du in der Zeile einen Breakbpoint setzt und dann mit Einzelschritt weiter gehst, dann kommst du niemals in die nächste Zeile.

du kannst mit
setSoTimeout(time)
ein Timeout setzen (in millisekunden) wie lang maximal gewartet werden soll.
Dann geht die Methode zumindest weiter, aber es sind evtl nicht alle Daten angekommen.
Aktuell sehe ich sehr hohes blocking potential an der Stelle.
Ich weiß ja nicht wo deine Daten wann genau herkommen.

PS:
Noch ein Tipp Variablen und Methoden schreibt man in Java normalerweise klein, also bufRec, tempSync, udpOnSend
 
Danke zusammen,
läuft nun:)

denke das Problem waren die Typen von doinBackground bzw. onPostExecute

hätte da noch eine frage zu Fragmenten

habe 3 fragments...

und eine Activity dort werden die 3 fragments geladen
auf den layouts der fragmente befinden sich nun togglebutton die ich von der Activity (in onPostexecute) ändern will, also den Zustand...

wird das funktionieren? oder soll ich die lieber in der fragment selber ändern,
und wie bzw. wann werden die togglebuttons initialisiert?! beim starten der Activity? oder beim aufruf der fragment?
 
Zurück
Oben Unten