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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With