Android SSH Verbindung mit JSCH, Fehler?

...komplette Frage anzeigen

1 Antwort

Aus dem Fehlerprotokoll:

    04-22 04:52:17.311 2327-2327/com.example.luick.boat_rc W/System.err: com.jcraft.jsch.JSchException: android.os. NetworkOnMainThreadException

In Android ist der main-Thread für das Benutzerinterface verantwortlich. Deswegen wird er auch oft UI-Thread genannt.

Dieser UI-Thread ist eine Schleife die Nachrichten aus einer message-queue abarbeitet - wobei die Nachrichten z.B. Events sind die generiert werden wenn der Nutzer den Touchscreen berührt.

Jede Operation die länger benötigt und im main/UI-Thread stattfindet würde die Verarbeitung solcher Nachrichten zeitweise blockieren - und löst dann auch nach einer gewissen Zeit einen ANR (Application not responding) Error aus.

Bei Operation die irgendetwas per Netzwerk machen wird generell unterstell dass sie womöglich lange dauern - und entsprechend sind sie im main-Thread verboten bzw. verursachen dort obige Exception...

Du mußt also einen separaten Thread erzeugen der sich um die Datenübertragung kümmert.....

Danke für die schnelle Antwort.

Aber und wie mach ich das?

0
@YellowEagle

Prinzipiell dadurch dass Du eine Unterklasse (z,B, "RaspberryThread") der Klasse "Thread" erstellst und dort die Methode run() überschreibst.
Innerhalb von run() findet dann die Netzwerkkommunikation statt-

Damit der Thread zum Laufen kommt erstellst Du ein entsprechenden Objekt

RaspberryThread x=new RaspberryThread();

und startest diesen Thread mit

x.start()

Nun führt Android die run() Methode im "Hintergrund" aus. Dieser Hintergrund-Thread läuft solange bis die run() Methode endet.
Je nach dem wie die Kommunikation aussehen soll kann die run() Methode als Endlosschleife angelegt sein.

Das Problem ist jetzt, dass der main-Thread normalerweise irgendwie mit dem Hintergrund-Thread kommunizieren muß.

Der Benutzer gibt z.B. irgendeinen Befehl ein (im UI-Thread)- der dann von diesem Hintergrund-Thread zum Raspberry gesendet werden soll.
Also muß der entsprechende Befehl vom main-Thread zum Hintergrund-Thread gelangen.
Eine simple Lösung wäre z.B. eine Member-Variable in der Unterklasse RaspberryThread wie "String executeCommand"

Mit 

x.executeCommand="Do something on the rasperry";

könnte man dann einen Befehl an den Thread (der ja durch x dargestellt wird übergeben

die run() Methode in RaspberryThread könnte dann z.B. so aussehen

void run(){

while (true){

if (executeCommand==null){

  Thread.sleep(100);

} else {

  SendCommandToRaspberry(executeCommand);

  executeCommand==null

}

}

}

Im UI-Thread muss man dann prüfen ob x.executeCommand==null ist bevor man den nächsten Befehl übergibt.
Sobald der dann vom Hintergrund-Thread abgearbeitet wurde wird executeCommand dann ja von diesem auf null gesetzt und der UI-Thread weiß dass er jetzt den nächsten Befehl übergeben darf.
Bei länger dauernden Befehlen möchte man dem Benutzer vielleicht eine Art Fortschrittsbalken anzeigen.
Dann muß der Hintergrund-Thread irgendeine Variable auf den aktuellen Fortschrittsstand in Prozenz setzen die dann vom UI-Thread z.B. alle 100 ms ausgelesen wird um ggf. dann einen entsprechend View (ProgressBar) auf den neuesten Stand zu bringen.

Wenn Du noch nie mit Threads zu tun hattest ist das anfangs eine ziemlich neue Denkweise mit Fehlermöglichkeiten die es bei normaler Programmierung gar nicht gibt...
Man sollte sich zumindest die wichtigsten Grundlagen aneignen und selbst dann ist das alles andere als trivial. 

0
@MalNachgedacht

Ok, die Frage ist vielleicht ein bissche dreist aber könntest du meinen Code so abändern das es passt. Ich weis das man durch Versuchen lernt aber ich habe keine Zeit mehr. Ich arbeite an einem größeren Projekt und sollte das bis morgen geschafft haben.... Ich hätte nicht gedacht das dass so kompliziert ist.

Ich habe zwar schon mit Threads zu tun gehabt also Multiblethread handling für Clientanfragen mit Java oder C++ doch habe ich keine Zeit mehr....

Ich würde mich über eine Antwort freuen.

MFG Luick.

0

Was möchtest Du wissen?