# Socket Verbindung AsycTask



## Rhymen (1. Feb 2014)

Hey Leute,

wollte mal ne Android App schreiben mir der ich Daten zwischen meinem Computer und meinem Handy austauschen kann. Um zu vermeiden das ich Netzwerkaktionen auf dem UI-Thread ausführe habe ich jetzt also auf einen AsyncTask zurückgegriffen.


```
package src.musicplayer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

import android.os.AsyncTask;
import android.util.Log;

public class Connection extends AsyncTask<Void, String, Void> {

	private Socket socket;
	private BufferedReader in;
	private PrintStream out;
	private Controller controller;

	Connection(Controller c) {
		this.controller = c;
	}

	@Override
	protected Void doInBackground(Void... params) {
		try {
			socket = new Socket("ip", 4444);
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			out = new PrintStream(socket.getOutputStream());
			while (socket.isConnected()) {
				publishProgress(in.readLine());
			}
		} catch (IOException e) {
			Log.d("Network Error", e.getLocalizedMessage());
		}
		return null;
	}

	@Override
	protected void onProgressUpdate(String... cmds) {
		for (String cmd : cmds) {
			controller.handleInput(cmd);
		}
	}

	public void send(final String cmd) {
		if (socket.isConnected()) {
			new Thread() {
				@Override
				public void run() {
					out.println(cmd);
				}
			}.start();
		}
	}

}
```

So funktioniert es nur leider nicht. Ich kann zwar Daten von meinem Computer zum Handy schicken, aber leider andersherum nicht. Problem ist das ich meinen Socket in 'doInBackground()' initialisiere und daher nicht auf ihn durch 'send' zugreifen kann. Sollte ich keinen AsyncTask verwenden oder mache ich einfach etwas falsch? Habe auch schon versucht meinem Socket in einem eigenen Thread via 'postExecute()' zu initialisieren aber dann bekomme ich folgenden Error:

```
02-01 14:36:18.904: I/dalvikvm-heap(15925): Grow heap (frag case) to 12.611MB for 1127536-byte allocation
02-01 14:36:18.914: D/dalvikvm(15925): GC_FOR_ALLOC freed <1K, 14% free 11301K/13024K, paused 10ms, total 10ms
02-01 14:36:18.924: D/AbsListView(15925): Get MotionRecognitionManager
```

Hoffe das mir wer Helfen kann. Danke schon mal und ein schönes Wochenende!


----------



## MF (1. Feb 2014)

Hallo,  
ist nicht direkt die Antwort auf Deine Frage, aber villeicht hift es Dir:
Ich hatte das so gelöst:

1) Verbindung definieren
Klasse ClientSocket 
mit Klassenveriablen:
InputStream in; 
OutputStream out;
... und was du sonst noch definieren willst: port, Netzwerkadresse  (Ich übergebe die Adresse des Servers an den Konstruktor)
Im Konstruktor weise ich in und out zu

2) Lesen
class SocketReader extends Thread
Der Konstruktor bekommt den InputStream in
Dann einen Thread aufbauen
 public void run() {
 // Code vom Socket lesen
}
Dem Thread die Möglichkeit geben sich sauber zu beenden ( z.B. zu Beginn  while (!stoprequested) )
stoprequested ist eine Klassenvariable von SocketReader zur Kontrolle des Threads
also Thread z.B. beenden mit Methode
public synchronized void requestStop() {
        stoprequested = true;
    }

2) Schreiben genau umgekehrt:
class SocketWriter extends Thread
Der Konstruktor bekommt den OutputStream out
etc. (wie bei Lesen)

Nach diesem Grundprinzip (also "klassisch", ohne Async Task) funktioniert es bei mir einwandfrei.  In meiner App bekommt bzw. liest der SocketWriter bzw. SocketReader die Daten aus einer LinkedBlockingQueue - so daß z.B. der Parser, der auch in einem eigenen  Thread läuft, sich die Daten aus der LinkedBlockingQueue holt. Andert aber nichts an dem Grundprinziip.


Um ab Android 3.0 den Socket aufzubauen setze ich noch: 
(ist vermutlich nicht die feine englische Art)


```
if (Build.VERSION.SDK_INT >= 9) {
        	StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        	StrictMode.setThreadPolicy(policy); 
        	}
this.sock = new Socket(adr,port); 
....
```

Wie gesagt, ist nicht direkt die Antwort auf Deine Anfrage aber eine Lösung die funktioniert.

Viele Grüße
MF


----------



## Rhymen (3. Feb 2014)

Hey MF,

danke schon mal für die Antwort. Das mit der Policy war mir bekannt, jedoch sehe ich sehr gegen diese Lösung an. Habe die App bereits fertig, aber am Ende kommt dann ja immer das Feintuning. Würde halt gerne wissen wie es 'richtig' gemacht wird. Natürlich könnte ich auch einfach alles in Threads laufen lassen, aber so wie ich das Verstanden habe wurde AsyncTask ja extra dafür entworfen. 

Liebe Grüße Rhymen!


----------



## dzim (3. Feb 2014)

AsyncExec ist bereits selbst ein anderer Thread, als der UI-Thread. Hier noch mal einen weiteren Thread zu verwenden ist nur in Empfangsrichtung sinnvoll.
Was ich damit sagen möchte, ist: Du brauchst ja ein ServerSocket - deinem Aufbau nach ist das im Moment auf dem PC zu finden, also kann die Verbindung nur von Android-Gerät aus aufgemacht werden. Wenn du davon unabhängig auch vom PC aus Daten senden möchtest, muss also entweder die Verbindung zuerst durch das Telefon aufgemacht werden, oder aber auf dem Telefon muss ebenfalls ein ServerSocket offen sein. Das du dort den Empfang und die Verarbeitung der Daten dann in andere Threads schiebst, ist dann durchaus sinnvoll.


----------



## Rhymen (3. Feb 2014)

Im Grunde mache ich es momentan so:
ServerSocket auf meinem PC wartet auf Antwort. 
Handy baut Verbindung auf.
PC schickt Initialisierungsdaten an mein Handy.
Handy und PC tauschen Daten aus.
Sobald ich die App auf meinem Handy pausiere/schließe wird die Verbindung aufgelöst.
ServerSocket auf meinem PC wartet auf Antwort. 

Trotzdem auf beiden Geräten einen ServerSocket verwenden? Es ist nicht so das ich bewusst Daten von meinem Computer zu meinem Handy schicken will. Ich will erst ein Datenaustausch ausführen sobald er vom Handy verlangt wird.

Liebe Grüße Rhymen


----------



## dzim (3. Feb 2014)

Na dann ist doch alles i.O., oder verstehe ich jetzt das Problem nicht mehr?


----------

