Outputstream Inputstream

Hallo Leute, leider wieder mal ich

Ich habe einen InputStream und Outputstream erfolgreich geholt.
Danach erstelle ich mir einen eigene AsyncTask-Klasse damit wohl meine GUI nicht blockiert wird.

Diese sieht so aus:

    private TextView textview;
    private BufferedReader fromServer;

    public inputStreamRead(TextView textview,BufferedReader fromServer) {
         this.textview = textview;
         this.fromServer = fromServer;
    }


    @Override
    protected Object doInBackground(Object... params) {
        String line = "";
        while(fromServer != null) {
            try {
                line = fromServer.readLine();
                line += "
";
                publishProgress(line);
            } catch (IOException e) {
                System.out.println("inputStreamRead Fehler");
                break;
            }
        }
        return true;
    }

    @Override
    protected void onProgressUpdate(Object... values) {
        for(Object einObject : values)
        {
            textview.setText(textview.getText()+einObject.toString());
        }

    }```

Ich hole mir einfach alles was ich vom Inputstream bekomme und gebe es auf die textView aus.
Ich weiß jetzt nicht ob ich schreiben soll es funktioniert denn, wenn ich diese Klasse aufrufe bekomme ich alles und wird auch schön ausgegeben, die GUI hängt sich auch nicht auf, aber lest mal bitte weiter.

In der Main möchte ich jetzt gern einen Befehl an den Linuxrechner senden:
```    public void befehleAnLirc(View view)
    {
        EditText com = (EditText) findViewById(R.id.editText_KEYWords);
        String command = com.getText().toString();
        try{
            toServer.write(command.getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();
        }catch (Exception ex)
        {
            System.out.println("bin hier XXX");
        }
    }```
Wird gemacht ohne Fehler. Das Problem ist, meine nebenher laufende AsyncTaskklasse verhält sich so, also würde sie nichts bekommen. Sie steht auf readLine() und wartet. Schön und gut, aber eigentlich sollte ja nachdem ich einen Befehl abgegeben habe, auch etwas zurück kommen??

Hier habe ich noch die Methode, wo ich erfolgreich eine Session und Channel bekomme:
```    @Override
    public void onTaskCompleted(Object[] values) {
        session = (Session)values[1];
        channel = (Channel)values[2];

        try{
            fromServer = new BufferedReader(new InputStreamReader(channel.getInputStream()));
            toServer = channel.getOutputStream();
            toServer.write("test".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();
            new inputStreamRead(textViewOutput,fromServer).execute();
        }catch (Exception ex)
        {
            System.out.println("bin hier shit");
        }
    }```

Verläuft auch ohne eine Exception zu werfen.
Wo ist nun bitte mein Fehler? Das komische ist dass der "test" funktioniert.
Also oben steht toServer.write("test".getBytes()) muss funktionieren denn danach wird der inputStreamRead geöffnet und ich sehe dass er mir zurückgibt "bash: test command not found"

Bin etwas ratlos

Danke für jeden Tipp

was für commands tippst du ein?
führe Gegentests durch: da wo du ein ‘nicht genanntes reguläres Kommando’ eintippst, tippe test ein, kommt dann dort “bash: test command not found”?

und da wo du bisher “test” testet mit Antwort, teste auch bestimmte Kommandos, kommen dazu passende Antworten?

ich schätze es ist so, dass an der einen Stelle (onTaskCompleted) sowohl “test” als auch anderes geht,
an der anderen (befehleAnLirc) gar nichts

dann wäre genauer zu untersuchen, was der Unterschied ist,

  • wie wird toServer gesetzt? der untere Code-Ausschnitt hat eine Zeile dazu, der obere nicht
  • wird der Sende-Code überhaupt ausgeführt, loggen
  • wird vielleicht erfolgreich Antwort gelesen, aber dort wo es nicht geht, selber wenn die gleiche inputStreamRead-Klasse benutzt wird, nicht korrekt weitergeleitet, falsche View?
    auch wieder loggen was bei readLine() rauskommt, direkt System.out.println() dahinter, das geht anscheinend

zu den genauen Prozesse bei Android kann ich leider nicht mitreden,
nur an so allgemeine Punkte erinnern, strukturell untersuchen was der Unterschied ist

So Zeug kann man schön in Unit-Tests auslagern. Sind zwar keine Unit-Tests aber du sparst dir mal den ganzen AsyncTask-Kram und musst die App nicht dauernd neu starten. Ich hab das bei meinen Netzwerktests auch immer so gehandhabt.

So jetzt bin ich noch verwirrter X)

Wie SlaterB gesagt hat habe ich nun mehrere Test gemacht, nun habe ich mal hier die Mainklasse:
Ich habe nur mal die befehleAnLirc umgeändert. Habe dort nur noch eine test()-Methode eingebaut und einfach den Code der früher in befehleAnLircSenden(View view) drinnen gestanden ist in test() hinein gepackt.

Die onTaskCompleted-Methode habe ich wie man sehen kann auch umgebaut. Zuerst mache ich in der Methode eine .write(“test1”) danach wird die Methode aufgerufen test() dort steht “test2” drinnen. Danach wird die AsyncTask Klasse aufgerufen, um den InputStream abzuhorchen.

Wird auch gemacht, doch komischerweiße kommt nur das heraus:
pi@raspberry: test1
-bash: test1: command not found
pi@raspberry: test2
-bash: test2: command not found

Danach nichts mehr. Er sollte aber noch test3 ausgeben und dann weil ich unter test3 nochmal test() aufrufe (in der onTaskCompleted-Methode) sollte nochmal test2 kommen.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.infrarotspeichern);

        textViewOutput = (TextView) findViewById(R.id.textView_LircMeldungen);

        establishConn();
    }

    public void establishConn()
    {
        Context context = getApplicationContext();
        CharSequence text = "Verbindet - bitte warten";
        Toast toast = Toast.makeText(context, text, 20);
        toast.show();

        if(channel != null || session!= null)
        {
            channel.disconnect();
            session.disconnect();
        }
        new establishConnection(this,this).execute();
    }

public void befehleAnLirc(View view)
    {
        test();
    }
    public void test(){
        EditText com = (EditText) findViewById(R.id.editText_KEYWords);
        String command = com.getText().toString();
        try{
            toServer.write("test2".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();
        }catch (Exception ex)
        {
            System.out.println("bin hier XXX");
        }
    }

    @Override
    public void onTaskCompleted(Object[] values) {
        session = (Session)values[1];
        channel = (Channel)values[2];

        try{
            fromServer = new BufferedReader(new InputStreamReader(channel.getInputStream()));
            toServer = channel.getOutputStream();
            toServer.write("test1".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();
            test();
            new inputStreamRead(textViewOutput,fromServer).execute();
            toServer.write("test3".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();
        }catch (Exception ex)
        {
            System.out.println("bin hier shit");
        }
    }
    public void onTaskCompleted(Object[] values) {
        session = (Session)values[1];
        channel = (Channel)values[2];

        try{
            fromServer = new BufferedReader(new InputStreamReader(channel.getInputStream()));
            toServer = channel.getOutputStream();
            toServer.write("test1".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();
            test();
            new inputStreamRead(textViewOutput,fromServer).execute();
            toServer.write("test3".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();
            test();
        }catch (Exception ex)
        {
            System.out.println("bin hier shit");
        }
    }```

Die AsyncTask Klasse inputStreamRead macht keinen Absturz verhält sich eigentlich so wie es sollte. Steht auf readLine() und wartet.

Was ich zuerst gedacht habe, dass er vlt niemals zu test3 und zu test() kommt nach dem new inputStreamRead(...), doch er geht wunderbar weiter, schreibt test3 und danach nochmal test2 raus. (Mal durch debuggt)

So, also vlt noch irgendwelche Ratschläge?
Unten die inputStreamRead-Klasse, weiß nicht ob man sie gebrauchen kann aber mal angehängt.

inputStreamRead-Klasse
[spoiler]
```public class inputStreamRead extends AsyncTask<Object,Object,Object> {
    private TextView textview;
    private BufferedReader fromServer;

    public inputStreamRead(TextView textview,BufferedReader fromServer) {
         this.textview = textview;
         this.fromServer = fromServer;
    }


    @Override
    protected Object doInBackground(Object... params) {
        String line = "";
        while(fromServer != null) {
            try {
                line = fromServer.readLine();
                line += "
";
                System.out.println(line);
                publishProgress(line);
            } catch (IOException e) {
                System.out.println("inputStreamRead Fehler");
                break;
            }
        }
        return true;
    }

    @Override
    protected void onProgressUpdate(Object... values) {
        for(Object einObject : values)
        {
            textview.setText(textview.getText()+einObject.toString());
            System.out.println("Habe "+einObject.toString()+" geschrieben");
        }
    }
}```[/spoiler]

wenn du das

new inputStreamRead(textViewOutput,fromServer).execute();
in der Mitte wegläßt, dann kommen die weiteren Ausgaben der hinteren Tests?

von wem wird überhaupt empfangen, läuft bereits ein inputStreamRead?
mir fällt nicht recht ein, wie ein zweites stören könnte,
aber an und für sich ist das ja komisch, sollen dann zwei gleichzeitig laufen?

außerdem:
fromServer wird ja erst vor den ersten Tests angelegt, wie könnte ein inputStreamRead daraus schon lesen?
werden wirklich die Antworten der ersten Tests bereits gelesen oder was bedeutet

Wird auch gemacht, doch komischerweiße kommt nur das heraus:
pi@raspberry: test1
-bash: test1: command not found
pi@raspberry: test2
-bash: test2: command not found

genau, was sind diese 4 Zeilen, welche System.out.println() sind dafür jeweils verantwortlich?

Okay, tut mir leid dass ich so kompliziert erklärt habe, also:

[QUOTE=SlaterB]wenn du das

new inputStreamRead(textViewOutput,fromServer).execute();
in der Mitte wegläßt, dann kommen die weiteren Ausgaben der hinteren Tests?[/QUOTE]
Wenn ich das inputStreamRead(…) weglasse kommt überhaupt keine Ausgabe heraus, denn die inpuStreamRead gibt mir die Ausgaben auf die TextView(die TextView ist vergleichbar mit der jTextArea) aus.
Diese Ausgaben:
pi@raspberry: test1
-bash: test1: command not found
pi@raspberry: test2
-bash: test2: command not found
habe ich von meiner TextView abgeschrieben.

Also genauen Ablauf:
Ich verbinde mich mit dem Pi(linux) new establishConnection(this,this).execute();, diese Klasse habe ich nicht gepostet, da sie einwandfrei funktioniert. Wenn diese Klasse fertig ist bekomme ich in der onTaskCompleted()methode den channel und die session. (Diese sind gültig)

    public void onTaskCompleted(Object[] values) {
        session = (Session)values[1];
        channel = (Channel)values[2];

        try{
            fromServer = new BufferedReader(new InputStreamReader(channel.getInputStream()));
            toServer = channel.getOutputStream();
            toServer.write("test1".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();
            test();
            new inputStreamRead(textViewOutput,fromServer).execute();
            toServer.write("test3".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();

        }catch (Exception ex)
        {
            System.out.println("bin hier shit");
        }
    }```

Ich erstelle dann den einen BufferedReader damit mir keine von den folgenden Befehle abhanden kommt.
```fromServer = new BufferedReader(new InputStreamReader(channel.getInputStream()));```
Danach schreibe ich den ersten Befehl raus:
```            toServer = channel.getOutputStream();
            toServer.write("test1".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();```
Die Rückgaben von Pi gehen nicht verloren da ich den BufferedReader davor schon initialisiert habe. 
danach wird die methode test() ausgeführt wo test2 hinaus geschrieben wird.
Jetzt möchte ich endlich meine Daten mal "ansehen"
somit starte ich:
```new inputStreamRead(textViewOutput,fromServer).execute();```
Hier gebe ich die textViewOutput(TextView, also fast eine jTextArea) mit. als nächsten Parameter gebe ich den BufferedReader mit (fromServer) den wir gerade oben initialisiert haben.
So der Thread läuft nun (Klasse inputStreamRead):
```    @Override
    protected Object doInBackground(Object... params) {
        String line = "";
        while(fromServer != null) {
            try {
                line = fromServer.readLine();
                line += "
";
                System.out.println(line);
                publishProgress(line);
            } catch (IOException e) {
                System.out.println("inputStreamRead Fehler");
                break;
            }
        }
        return true;
    }```
Er durchläuft die while-Schleife mehrmals. Wenn es nichts mehr zu lesen gibt, bleibt er bei readLine() stehen.
Da er die Schleife mehrmals durchläuft bekomme ich auch auf der TextView die Ausgaben zu sehen:
pi@raspberry: test1
-bash: test1: command not found
pi@raspberry: test2
-bash: test2: command not found
habe ich von meiner TextView abgeschrieben. Diese Zeilen werden hier ausgegeben:
Klasse InputStreamRead:
```    @Override
    protected void onProgressUpdate(Object... values) {
        for(Object einObject : values)
        {
            textview.setText(textview.getText()+einObject.toString());
            System.out.println(einObject.toString());
        }
    }```


So jetzt schreibe ich eigentlich test3 raus in meiner onTaskCompleted-Methode:
```            fromServer = new BufferedReader(new InputStreamReader(channel.getInputStream()));
            toServer = channel.getOutputStream();
            toServer.write("test1".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();
            test();
            new inputStreamRead(textViewOutput,fromServer).execute();
            toServer.write("test3".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();```
Es gibt aber anscheinend keinen Rückgabewert vom Pi denn die inputStreamRead-Klasse bleibt immmer noch auf readLine() stehen und wartet bis etwas kommt.

So ich hoffe jetzt mal etwas Licht ins dunkl gebracht zu haben

//EDIT hoffentlich mache ich es nicht komplizierter X)

eieiei, die ersten Rückgaben gehen natürlich nicht verloren auch wenn erst später aus dem Stream gelesen wird,
da habe ich ja was geschossen,

jetzt frage ich mich, wie nebenläufig dieses inputStreamRead abläuft,
werden die beiden ersten Antworten durch inputStreamRead im Moment immer vor dem Senden der letzten beiden Tests gelesen?

teste mal ein wenig mit Thread.sleep() zu verzögern, so dass zwischendurch einer oder beide restlichen Tests gesendet werden, macht das einen Unterschied?

du sprichst von Debuggen, ein System.out.println(“fertig mit Senden von test3”); wäre mir lieber,
dann man auch alles besser zeitlich einordnen

:smiley: also du kommst mit fragen

jetzt frage ich mich, wie nebenläufig dieses inputStreamRead abläuft,
werden die beiden ersten Antworten durch inputStreamRead im Moment immer vor dem Senden der letzten beiden Tests gelesen?

Habe das mal getestet mit dieser „Aufstellung“:

            toServer = channel.getOutputStream();
            toServer.write("test1".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();
            test();
            new inputStreamRead(textViewOutput,fromServer).execute();
            System.out.println("Vor Test 3");
            toServer.write("test3".getBytes());
            toServer.write(("
").getBytes());
            toServer.flush();
            System.out.println("Nach Test 3");```
Das lesen mit dem InputStreamRead ist schneller als das schreiben von test3.


> teste mal ein wenig mit Thread.sleep() zu verzögern, so dass zwischendurch einer oder beide restlichen Tests gesendet werden, macht das einen Unterschied?

auch wenn ich das "lesen" hinauszögere, und Vor Test 3 und Nach test 3 zuerst ausgeführt wird ändert es nichts an der Ausgabe.

*** Edit ***

Warte warte

new inputStreamRead(textViewOutput,fromServer).execute();

Es scheint, dass fromServer nur eine Kopie des aktuellen Standes mitgibt.
Ich habe gedacht ich gebe eine Referenz mit.

Wie kann ich bitte eine Referenz mitgeben?!?!?!!?

//EDIT
So jetzt habe ich versucht den Channel mitzugeben statt den BufferedReader.
Habe dann dort den BufferedReader in der doInBackground-Methode erstellt. Leider auch nicht die Lösung.

So jetzt bin ich doch schon etwas am verzweifeln

**//EDIT - DIE LÖSUNG**
Gut, um es klar mal zu sagen - ich liebe Android aber ich hasse es darauf zu programmieren!!
Ich habe in der AndroidManifest.xml Datei die MinSDKVersion von 10 auf 14 gestellt und nun funktionierts!!!

Ich weiß zwar nicht warum das so ist, aber hauptsache es funktioniert!!

Ich habe in der AndroidManifest.xml Datei die MinSDKVersion von 10 auf 14 gestellt und nun funktionierts!!!

WTF?

Aber so Versions-Geschichten hatte ich auch schon. Entweder mit URLConnection oder mit NetworkOnMainExceptions.