# float wert von Smartphone per Bluetooth empfangen



## Javaman91 (5. Jan 2019)

Hallo,

ich bin mir nicht sicher, ob ich nicht schon mal das Thema „Bluetooth“ hier angesprochen habe.
Ich habe eine App erstellt die mir vom Neigungssensor den Wert ausgibt. Dieser Wert soll dann an meine Java-Software gesendet werden per Bluetooth.

Jetzt suche ich schon echt lange nach einem funktionierenden Beispiel, was wirklich funktioniert.
Wie man Bluetooth in Android nutzt ist ganz gut erklärt im Netz. Nur wie man in einer Java-Desktop-Applikation die Daten empfangen kann so gut wie gar nicht bzw. haben die Beispiele die ich gefunden habe nicht wirklich funktioniert. Mein Java-Programm erkennt das Smartphone, nur empfängt es keine Daten vom Smartphone. Der Bluecove stack wird gleich wieder beendet und ich sehe keinen Wert. Warum weiß ich leider nicht, da ich kein brauchbares Tutorial gefunden habe wo erklärt wird was man alles benötigt. Leider! Momentan probiere ich nur herum.

Nun hoffe ich, das hier Leute sind die sich damit auskennen und schon mal was damit gemacht haben und mir weiterhelfen können. Momentan komme ich gar nicht mehr weiter.

Hat jemand ein funktionierendes Beispiel, wo auch die wichtigsten schritte erklärt sind?

Vielen Dank im Voraus.

Schöne Grüße


----------



## Barista (6. Jan 2019)

Das Thema Bluetooth ist ziemlich umfangreich.

Die Android-App muss in diesem Fall als Peripheral arbeiten, Deine Desktop-App als Central.

Ich habe schon mal nach Bluetooth unter Win und so gegooglet, aber noch nie gearbeitet.

Ohne JNI-Lib kommst Du nicht an die APIs in Win ran.

Ich habe Erfahrung mit Bluetooth unter Android als Central.

Da könnte ich mit Antworten helfen.


----------



## Javaman91 (7. Jan 2019)

Hy, danke für deine Antwort!

Wie gesagt, sollte es mit Bluecove Snapshot funktionieren.
Die Desktop-Anwendung in Eclipse erkennt ja das Smartphone.
Smartphone ist mit dem Laptop gekoppelt
Es wird der Gerätename, Bluetooth-Adresse usw. angezeigt.
Nur die Datenübertragen funktioniert nicht, dabei soll meine Desktop-Applikation nur die Daten empfangen.
Es werden vom Laptop keine Daten an das Smartphone gesendet. Das Programm soll ständig die neuen Sensorwerte vom Smartphone erhalten und fürs erste einfach mal in der Eclipse Konsole ausgeben.

Bluetooth wird doch wirklich überall eingesetzt und ist nicht wirklich neu, warum gibt es so gut wie keine Programmbeispiele bzw. Anleitungen wo erklärt wird wie das funktioniert?

So komme ich im Moment nicht weiter.

SG


----------



## httpdigest (7. Jan 2019)

Javaman91 hat gesagt.:


> Bluetooth wird doch wirklich überall eingesetzt und ist nicht wirklich neu, warum gibt es so gut wie keine Programmbeispiele bzw. Anleitungen wo erklärt wird wie das funktioniert?


Bluetooth ist lange nicht so ubiquitous wie z.B. WLAN. Z.B. kommt eigentlich kein Desktop-PC standardmäßig mit einem Bluetooth-Adapter, wohl aber die meisten mit einem WLAN-Adapter.
Ähnlich sah es lange bei Laptops aus. Es gibt keine Tutorials für Bluetooth, weil der Einsatz von Bluetooth-fähigen Anwendungen nicht wirklich zum Jedermannentwickler vorgedrungen ist - die ja dann hauptsächlich entweder Smartphone-Apps (die Bluetooth-Adapter mitbringen und für die es durchaus Tutorials gibt) oder Desktop-Apps (deren Geräte kaum Bluetooth-Adapter mitbringen) entwickeln - sondern hauptsächlich für embedded und Entertainment Devices (TV, Car-Infotainment, Smartphones, ...) eingesetzt wird, die nicht jedermann entwickelt. Ganz anders sieht es da bei WLAN aus.
Also ich würde das Fehlen von Tutorials für die Zielplattform Desktop (PC oder Laptop) darauf zurückführen, dass man in solchen Systemen eben kein Bluetooth einsetzt, da solche Systeme meist sowieso stationär betrieben werden und die Verfügbarkeit von LAN/WLAN in solchen Situationen sehr wahrscheinlich ist.


----------



## Javaman91 (7. Jan 2019)

Also meinst du, es wäre besser mit WLAN zu arbeiten?
Mir ist es eigentlich egal ich dachte nur am Anfang, das sich Bluetooth sehr gut anbietet.
Ich war der Meinung, das Bluetooth sicherlich einfacher zu programmieren ist als eine WLAN verbindung.

Nur mal angenommen ich verwende jetzt WLAN, dann möchte ich aber schon eine direkte Verbindung zwischen meinen PC und dem Smartphone herstellen können. Ohne jetzt einen Router dazwischen haben zu müssen. Somit müsste dann mein PC auch als Server fungieren, oder liege ich da falsch?

Sorry, aber WLAN in der programmierung ist für mich Neuland.
Ich bin zwar Netzwerktechniker, doch mit der programmierung in diesem Bereich hatte ich noch nie was zu tun.

SG


----------



## httpdigest (7. Jan 2019)

Naja, "WLAN"-Programmierung an sich gibt es ja nicht. Du verwendest die standardisierte Berkeley-Socket API, die in eigentlich allen Programmiersprachen, insbesondere Java, noch ordentlich durch Klassen gekapselt ist. Und ein Socket kann dabei eben ein X-beliebiges Netzwerk-Socket an einem beliebigen Netzwerkadapter (_außer_ Bluetooth) sein, wie etwa LAN, WLAN, Loopback-Device, IPC/Unix sockets, etc.
In Java würdest du dafür die ganz normalen Socket bzw. ServerSocket Klassen nutzen. Aber ja, du brauchst dafür Netzwerkadapter, die imselben IP/Ethernet-Netzwerk angemeldet sind, üblicherweise über einen Access Point wie etwa einen WLAN-Router.
Dein Smartphone kann mit hoher Wahrscheinlichkeit auch als Access Point fungieren, mit einer SSID und Passwort, an den sich dann dein PC anmelden kann. Beide Devices wären dann imselben Netzwerk und du kannst stinknormale Java-Netzwerk-Programmierung mit besagten Klassen oder diversesten Frameworks/Abstraktionen dafür verwenden.


----------



## Javaman91 (15. Jan 2019)

Hallo,

ich habe nun folgenden Code:

Desktop-Applikation:

public static void receiveValue() throws IOException{

        ServerSocket serverSocket = new ServerSocket(999);
        Socket socket = serverSocket.accept();

        InputStreamReader streamReader = new     InputStreamReader(socket.getInputStream());
        BufferedReader bufferReader = new BufferedReader(streamReader);

        String temp = bufferReader.readLine();
        System.out.println(temp);
}

Android:

Zuerst die Permission in der manifest.xml:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

Hier wird eine Nachricht an den PC gesendet bzw. sollte.

public void senden() throws IOException {

        Socket socket = new Socket("192.168.0.1",999);
        DataOutputStream send = new DataOutputStream(socket.getOutputStream());
        send.writeUTF("Hello");
        socket.close();
}

Irgendwas mache ich falsch, oder habe ich nicht im Code.
Es passiert leider nichts, wenn ich die App starte und die Applikation.
In der eclipse konsole sollte "Hello" stehen.

Bitte dich um Hilfe.

SG


----------



## httpdigest (15. Jan 2019)

Es ist seeehr unwahrscheinlich, dass dein Server die IP Adresse 192.168.0.1 hat. Solche Adressen haben normalerweise Router. Finde erstmal die IP-Adresse des Servers in diesem Netzwerk heraus. ifconfig/ipconfig.
Du willst ja schließlich keine Ende-zu-Ende Verbindung mit deinem Router herstellen (dein Server-Programm läuft ja nicht auf deinem Router), sondern dieser soll die Pakete weiter zu deinem Server-Rechner routen.


----------



## Javaman91 (16. Jan 2019)

Upps, da habe ich im cmd wohl die falsche Adresse abgelesen. Sie lautet 192.168.0.103
Habs geändert, funktioniert aber trotzdem nicht. 
Was habe ich falsch gemacht?

SG


----------



## Javaman91 (17. Jan 2019)

Ich bin jetzt nochmal alles durchgegangen.
Im Beispiel was ich gefunden habe steht auch nicht mehr.
Eigentlich sollte es funktionieren.


----------



## Javaman91 (27. Jan 2019)

Hallo Leute,

ich konnte jetzt mal eine Verbindung zwischen meiner Desktop-Application und meiner App herstellen.
Das funktioniert schon mal.
Sobald die Verbindung akzeptiert wurde und die Daten übertragen werden kann ich in der Desktop-Application nur "Null" lesen. Irgendwie wird der Sting nicht übertragen.

Ich habe keine Ahnung, was da jetzt nicht passt.

SG

Android Source:


```
class BackgroundTask extends AsyncTask<String,Void,Void>
{
    @Override
    protected Void doInBackground(String... voids){

        BackgroundTask b1 = new BackgroundTask();
        b1.execute(text1);
        text1 = "Hallo";

        try{
            socket = new Socket("192.168.0.164", 6000);
            writer = new PrintWriter(socket.getOutputStream());
            writer.write(text1);
            writer.close();
            socket.close();
        }catch(IOException e){
            e.printStackTrace();
        }
        return null;
    }
}

Desktop-Application:
    public static void main(String[] args){

       WLAN wlan = new WLAN();
  
       try {
           sSocket = new ServerSocket(6000);
           socket = sSocket.accept();
          
           while(true){
              
           InputStreamReader reader = new InputStreamReader(socket.getInputStream());
           BufferedReader br = new BufferedReader(reader);
           System.out.println(br.readLine());
       }              
      
       } catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }
      
   }
```


----------



## Flown (28. Jan 2019)

Code in code-tags posten: [code=java]//JAVA CODE HERE[/code]


----------



## Javaman91 (28. Jan 2019)

Sorry.

Woran liegt es, das ich immer nur "Null" erhalte?


----------



## mihe7 (29. Jan 2019)

Mach mal vor writer.close() noch ein writer.flush() rein.


----------



## petebocs (29. Jan 2019)

Hast du Firewall? Port ist blockiert eventuell.


----------



## Javaman91 (29. Jan 2019)

Ruft close nicht auch automatisch ein flush auf?
Ich werde es heute nochmal versuchen.
Firewall habe ich deaktiviert zum testen. Möglicherweise blockt der Router da noch was.


----------



## mihe7 (29. Jan 2019)

Javaman91 hat gesagt.:


> Ruft close nicht auch automatisch ein flush auf?


Ja, richtig. Mach mal text = "Hallo\n".


----------



## Javaman91 (5. Feb 2019)

Hallo,

"\n" hat nichts gebracht.
Aber ich habe was herausgefunden.
Wenn man beim Start die Eclipse-Konsole genau betrachtet, dann wird das "Hallo" 1 Mal übertragen und scheinbar nur ganz kurz angezeigt (Bruchteil einer Sekunde). Ist in der Konsole danach nicht mehr aufzufinden.

Daraufhin habe einfach mal zum testen ein "Thread.sleep(2000);" in den Code eingefügt und siehe da, das "Hallo" wird 1 Mal angezeigt. Danach kommt aber wieder Null.

Warum wird das "Hallo" nur ein einziges Mal übertragen.

SG


----------



## httpdigest (5. Feb 2019)

Du erzeugst in deiner while (true) {...} Schleife in der "Desktop-Application" den InputStreamReader und den BufferedReader jede Schleifeniteration aufs neue aus dem Socket InputStream. Das solltest du nicht tun, da der BufferedReader mehrere Zeichen intern puffert und aus dem darunterliegenden InputStream liest. Das heißt, wenn der Peer dir zwei Zeilen überträgt (in einen TCP-Socket schreiben, puffert ebenfalls auf Senderseite per Default - Stichwort: Nagle-Algorithmus), wirst du die erste Schleifeniteration nur die erste Zeile sehen (der BufferedReader hat aber bereits die zweite Zeile gepuffert). Dann in der nächsten Iteration erzeugst du einen neuen BufferedReader, und dieser blockiert in readLine() entweder, weil nichts mehr zu lesen ist (die zweite Zeile ging durch den ersten BufferedReader "verloren") oder er returned dir bei readLine() null, weil der Socket geschlossen wurde.
Erzeuge den InputStreamReader und den BufferedReader also nur einmal außerhalb der while-Schleife.


----------



## Javaman91 (9. Feb 2019)

Hallo,

ich habe jetzt den Code geändert.
Immer noch das selbe Problem.


```
try {
           sSocket = new ServerSocket(6000);
           socket = sSocket.accept();
           
           InputStreamReader reader = new InputStreamReader(socket.getInputStream());
           BufferedReader br = new BufferedReader(reader);
           String test;
           
           while(true){
               test = br.readLine();
               System.out.println(test);
               //Thread.sleep(5000);
       }               
       } catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }
```


----------



## mihe7 (9. Feb 2019)

Test erst mal den Server:

Bau eine Testausgabe ein, z. B. nach sSocket.accept(). Die sollte ausgegeben werden, sobald eine Verbindung zustande kommt. 
Nimm einen Client wie putty (oder, wenn Du unter Linux unterwegs bist geht auch telnet). Verbinde Dich mit Deinem Server, Tipp eine Zeile ein, schau was der Server macht.
Wenn das funktioniert, liegt der Fehler beim Client.


----------



## Javaman91 (6. Mrz 2019)

Hallo,

was bedeuten diese Fehlermeldungen:

java.io.EOFException
0.0
   at java.io.DataInputStream.readFully(DataInputStream.java:197)
   at java.io.DataInputStream.readLong(DataInputStream.java:416)
   at java.io.DataInputStream.readDouble(DataInputStream.java:468)
   at WLAN.main(WLAN.java:25)

Bei "at WLAN.main(WLAN.java:25)" wird immer diese Zeile markiert:


```
test = reader.readDouble();
```


----------



## mihe7 (6. Mrz 2019)

Du versuchst ein Double aus dem Stream zu lesen aber der Stream endet, bevor es komplett gelesen werden konnte.


----------



## Javaman91 (7. Mrz 2019)

Danke für deine Antwort.

Das muss dann aber ein Android seitiges Problem sein.
Ich muss mir das nochmal genau ansehen.

SG


----------



## mihe7 (7. Mrz 2019)

Javaman91 hat gesagt.:


> Das muss dann aber ein Android seitiges Problem sein.


Theoretisch möglich, halte ich aber für weniger wahrscheinlich. Poste doch mal den Code, den Du bisher verwendest (Server und Client).


----------



## Javaman91 (7. Mrz 2019)

Hier der Code:

Android:

```
class BackgroundTask extends AsyncTask<String, Void, String>
{
    @Override
    protected String doInBackground(String... voids) {

        while (true){
            try {
            socket = new Socket("192.168.0.164", 6000);
            writer = new PrintWriter(socket.getOutputStream());
            writer.write(String.valueOf(probieren));
            writer.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    }
}
```

Eclipse: (Die while-Schleife fehlt hier noch)

```
public static void main(String[] args){
      
       try {
           sSocket = new ServerSocket(6000);
           socket = sSocket.accept();       
           reader = new DataInputStream(socket.getInputStream());
           test = reader.readDouble();
           System.out.println(test);
                 
       } catch (IOException e) {
           e.printStackTrace();
       }
   }
```

Mit dem String hat es funktioniert.
Nur mit einem double nicht.


----------



## mihe7 (7. Mrz 2019)

Naja, du kannst nicht einfach ein Double per PrintWriter rausschreiben und per DataInputStream einlesen.


----------



## Javaman91 (7. Mrz 2019)

Ich habe das so in einem Beispiel gesehen. Mit "String.valueOf (double variable)" sollte es funktionieren.


----------



## mihe7 (7. Mrz 2019)

Du schreibst die Textdarstellung einer Zahl und liest einen binären Wert. Das funktioniert nicht - Beispiel hin oder her 

Wenn Du zum Beispiel "1.0" (als Text) rausschreibst, sind das 3 Bytes. Ein double benötigt 8 Bytes, daher liest DataInputStream 8 Bytes ein. Es sind nur 3 verfügbar -> EOFException. Wenn Du "1.000000" rausschreiben würdest, würde zwar keine EOFException geworfen, aber ein völlig anderer Wert rauskommen.

Nimm statt PrintWriter z. B. einen DataOutputStream.


----------



## Javaman91 (10. Mrz 2019)

Es hat funktioniert mit dem DataOutputStream, vielen Dank!

Jetzt brauche ich noch eine While-Schleife damit die Werte ständig ausgegeben werden.
Sobald ich diese einfüge bekomme ich wieder die gleichen Fehler wie zuvor.
Das gelingt mir einfach nicht, egal wie ich sie einsetze es kommt immer der gleiche Fehler.

Wie kann ich hier eine Schleife einbauen?

SG


----------



## mihe7 (10. Mrz 2019)

Dein Client verbindet sich, liest einen Wert aus und beendet dann die Verbindung. Dein Server muss im Prinzip das gleiche machen: accept, write, close, accept, write, close, ...


----------



## Javaman91 (7. Mai 2019)

Hallo Leute,

das Programm funktioniert mittlerweile, die Werte werden übertragen.
Nachdem ich ich mein kleines Testprogramm in mein Game eingebaut habe, läuft das Spiel nur mehr in Zeitlupe ab.
Es liegt definitiv am Wlan sourcecode.
Was genau der Grund ist, konnte ich noch nicht feststellen.

Danke für die Hilfe!

SG


----------



## kneitzel (3. Aug 2019)

Wenn du immer die Verbindung aufbaust und nach einem Wert beendest, dann ist das natürlich langsam.

Bau die Verbindung ein mal auf und nutze sie dann solange wie du sie brauchst.


----------

