Bluetooth connectivity issues with IntentService

I need to transfer some data from my Android application via Bluetooth (in Arduino). I do not read or receive anything from Arduino. For my single threaded needs, I went with IntentService. After pairing, my code works fine when I connect and send data. I will disconnect after sending the data without errors. But when I try to connect a second time, I get the following error when trying myBluetoothSocket.connect ():

Read error, socket may be closed or timeout, read ret: -1

The only solution is to disconnect the Arduino device and reconnect (this does not help if I force-stop the application and try reconnecting).

Please note that everything works fine if I create 2 threads (one for reading and writing each), no matter how many times I connect and send data (thereby proving that there is nothing wrong on the Arduino side, โ€œholding backโ€ the old compound).

Here is my Android code:

import android.app.IntentService; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Intent; import android.content.Context; import android.os.Build; import android.os.ParcelUuid; import android.widget.Toast; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method; import java.util.UUID; public class DataTransmissionService extends IntentService { private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private static final String TAG = "DataTransmissionService"; private BluetoothAdapter btAdapter = null; private BluetoothSocket btSocket = null; private OutputStream outStream = null; private BluetoothDevice device = null; public DataTransmissionService() { super("DataTransmissionService"); } @Override protected void onHandleIntent(Intent intent) { cleanup(); if (intent != null){ btAdapter = BluetoothAdapter.getDefaultAdapter(); pairedDeviceAddress = "already_paired_device_mac_addr"; try { log.d(TAG, pairedDeviceAddress); device = btAdapter.getRemoteDevice(pairedDeviceAddress); log.d(TAG, "Device bond state : " + device.getBondState()); } catch (Exception e) { log.e(TAG, "Invalid address: " + e.getMessage()); return; } try { btSocket = createBluetoothSocket(device); } catch (IOException e) { log.e(TAG, "Socket creation failed: " + e.getMessage()); return; } try { if (!btSocket.isConnected()) { btSocket.connect(); log.d(TAG, "Connected"); } else { log.d(TAG, "Already Connected"); //flow never reaches here for any use case } } catch (IOException e) { log.e(TAG, "btSocket.connect() failed : " + e.getMessage()); return; } try { outStream = btSocket.getOutputStream(); } catch (IOException e) { log.e(TAG, "Failed to get output stream:" + e.getMessage()); return; } sendData("test"); //cleanup(); called in onDestroy() } } @Override public void onDestroy(){ cleanup(); //notify ui super.onDestroy(); } private void cleanup(){ try { if (outStream != null) { outStream.close(); outStream = null; } } catch (Exception e) { log.e(TAG, "Failed to close output stream : " + e.getMessage()); } try { if (btSocket != null) { btSocket.close(); btSocket = null; } }catch (Exception e) { log.e(TAG, "Failed to close connection : " + e.getMessage()); } } private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException { /*if(Build.VERSION.SDK_INT >= 10){ try { final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class }); return (BluetoothSocket) m.invoke(device, MY_UUID); } catch (Exception e) { log.e(TAG, "Could not create Insecure RFComm Connection",e); } }*/ return device.createRfcommSocketToServiceRecord(MY_UUID); } private void sendData(String message) { byte[] msgBuffer = message.getBytes(); log.d(TAG, "Sending : " + message); try { outStream.write(msgBuffer); } catch (IOException e) { log.e(TAG, "failed to write " + message); } } } 

I tested the Nexus 5 and Samsung S5 devices (it works 5.1 and 5.0 respectively).

+8
android bluetooth
source share
3 answers

I'm not sure why it works, but this approach finally worked:

 private BluetoothSocket createBluetoothSocket(BluetoothDevice bluetoothDevice) throws IOException { try { Method m = bluetoothDevice.getClass().getMethod( "createRfcommSocket", new Class[] { int.class }); btSocket = (BluetoothSocket) m.invoke(bluetoothDevice, 1); } catch (Exception e) { e.printStackTrace(); } return btSocket; } 
0
source share

When you try to connect a second time, you need to create the appropriate socket again.

You should also think that Arduino is a slow platform, there may be some significant delay between closing the connection and being able to open it again.

+2
source share

The onDestroy() method is called only when the garbage collector starts. You need to call cleanup() from onHandleIntent(Intent) , as before, otherwise the socket will remain open indefinitely. Since you left it open, you cannot reconnect.

The Android Bluetooth stack seems agnostic to the application life cycle: the socket will remain open even if you force the application to stop. In your current scenario, to close the socket, turn off the Bluetooth function in the settings.

-one
source share

All Articles