Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: BluetoothSocket receives its own output

I have an app that connects to a RaspberryPi via Bluetooth and loops the same data to it while it receives some data back.

I had some issues with the connection so this workaround is needed to connect my android phone to the RaspberryPi: IOException: read failed, socket might be closed - Bluetooth on Android 4.3

For some reason, the android phone is receiving its own output. The String "Hello Raspberry. It's me, AndroidPhone" is sent to the output in a never-ending loop. The incoming data (from the RaspberryPi) is also read in a never-ending loop.

But somehow I don't only receive the data from the RaspberryPi but also the string sends via smartphone. This is my code:

public class MainActivity extends AppCompatActivity {     private BluetoothAdapter bluetoothAdapter;     UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");      @Override     protected void onCreate(Bundle savedInstanceState) {         // (...)         // Only GUI-stuff until this point          bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();         BluetoothDevice raspberryPi = bluetoothAdapter.getRemoteDevice("B8:27:EB:56:DC:B2");         BluetoothSocket btSocket;          try {             btSocket = raspberryPi.createRfcommSocketToServiceRecord(SERIAL_UUID);             btSocket.connect();         } catch (IOException e) {             Log.e("BTError", e.getMessage());             // Workaround, found on: https://stackoverflow.com/questions/18657427/ioexception-read-failed-socket-might-closed-bluetooth-on-android-4-3             try {                 Log.e("BTError", "Trying fallback...");                 btSocket = (BluetoothSocket) raspberryPi.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(raspberryPi, 1);                 btSocket.connect();                  (new Thread(new SendingThread(btSocket))).start();                 (new Thread(new ReceivingThread(btSocket))).start();             } catch (Exception e2) {                 Log.e("BTError", e2.getMessage());                 Log.e("BTError", "Couldn't establish Bluetooth connection!");             }         }     }      private class SendingThread extends Thread {         private OutputStream out;          public SendingThread(BluetoothSocket btSocket) {             try {                 out = btSocket.getOutputStream();             } catch (IOException e) {                 e.printStackTrace();             }         }          @Override         public void run() {             try {                 int delay = 100000000;                 while (true) {                     if (delay == 0) {                         Log.i("WRT", "Written to RaspberryPi");                         out.write("Hello Raspberry. It's me, AndroidPhone".getBytes());                         delay = 100000000;                     }                     delay--;                 }             } catch (IOException e) {                 e.printStackTrace();             }         }     }      private class ReceivingThread extends Thread {         private InputStream in;          public ReceivingThread(BluetoothSocket btSocket) {             try {                 in = btSocket.getInputStream();             } catch (IOException e) {                 e.printStackTrace();             }         }          @Override         public void run() {             int data = 0;             while (true) {                 try {                     data = in.read();                 } catch (IOException e) {                     e.printStackTrace();                 }                 Log.i("RCV", String.valueOf((char) data));             }         }     } 

On the RaspberryPi end, everything looks normal. A simple java program starts the Linux command rfcomm listen /dev/rfcomm0 and reads from/writes to the file /dev/rfcomm0 with FileReader and FileWriter. The only relevant lines on this end are:

run {     // Inside writer-thread     bluetoothWriter = new BufferedWriter(new FileWriter("/dev/rfcomm0"));     while(true) {         bluetoothWriter.write("This is RaspPi");         bluetoothWriter.flush();     } } 

and

run {     // Inside reader-thread     bluetoothReader = new BufferedReader(new FileReader("/dev/rfcomm0"));     while(true) {         int incData = bluetoothReader.read();         System.out.print((char) incData);     } } 

Thank you for your help!

edit: Still no solution to this problem. I suspected that the RaspberryPi is somehow sending back what it received. But when I disabled that it sends out anything, the smartphone still directly receives what it has sent out.

like image 653
DeMo Avatar asked Apr 12 '18 09:04

DeMo


1 Answers

I scoured over the Bluetooth classes sources. The workaround seems legit from the first glances. Try this first:

if (delay == 0) {     Log.i("WRT", "Written to RaspberryPi");     out.write("Hello Raspberry. It's me, AndroidPhone".getBytes());     out.flush(); // <-- You are not flushing      delay = 100000000; } 

And the message sticks in you socket for you to read over and over again.

If that does not fix it the other option I can think of is that somehow the socket is initialized to be a socket to your Android device. The .createRfcommSocket() method seems to create a socket to your own device if the Bluetooth device is null when the socket was being created. I'm not sure how this would exactly happen, but if the Raspberry Pi's state is somehow mangled after exception I suppose it could be something to look into.

On the raspy side: If you are just starting both of those threads doesn't it mean that you are constantly sending messages to /dev/rfcomm0 and flushing. I recommend that you change it so that raspy reacts to a received message by sending back the wanted message instead of spamming all the time. I'm not sure if this is part of your problem but it would at least make debugging & development a bit easier.

like image 77
KinGin Avatar answered Oct 11 '22 12:10

KinGin