I've got a Bluetooth device that has connected on all versions of Android that I have tried prior to 4.4.2. Now, it's not connecting on the Galaxy Tab 4 or the S3. The Tab 3 connects fine with 4.1.2. The problem seems to occur in the AcceptThread
while trying to initialize the BluetoothSocket
. The code I'm using is based off of the chat example in the sdk.
My Accept code
private class AcceptThread extends Thread { // The local server socket private BluetoothServerSocket mmServerSocket; public boolean successInit = false; public AcceptThread() { closeAllConnections(); BluetoothServerSocket tmp = null; // Create a new listening server socket while(!successInit) { try { tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); successInit= true; Log.i("TAG", "Socket Server Created"); } catch(Exception e) { Log.i("TAG", e.getMessage()); successInit = false; } } mmServerSocket = tmp; } public void run() { BluetoothSocket socket = null; // Listen to the server socket if we're not connected Log.i("BluetoothComService", String.valueOf(mState)); while (mState != STATE_CONNECTED) { try { // This is a blocking call and will only return on a // successful connection or an exception mAdapter.cancelDiscovery(); socket = BluetoothAdapter.getDefaultAdapter() .getRemoteDevice(getThermMAC()) .createRfcommSocketToServiceRecord(UUID .fromString("00001101-0000-1000-8000-00805F9B34FB")); // socket = mmServerSocket.accept(); // here socket might be closed or timeout Log.e("BluetoothComService", "No accept Exception"); }catch (IOException e) { Log.e("TAG", e.getMessage()); }
getThermMAC()
above is my method to return the address of the bonded device.
In run()
, if I use
socket=BluetoothAdapter.getDefaultAdapter() .getRemoteDevice(getThermMAC()) .createRfcommSocketToServiceRecord(UUID .fromString("00001101-0000-1000-8000-00805F9B34FB"));
then I get a NPE
at line 501 of BluetoothSocket.java
in the Android framework which is this line
int left = b.length;
So it would appear that b
is null
but it doesn't appear to be after debugging. b
is a byte[]
which is sent from my BluetoothService
class which sends a brand new, initialized byte[]
from within the ConnectedThread
just as the sdk example does and as I've been doing on older versions.
If I comment that out and try to use
socket = mmServerSocket.accept();
which has been working in the past, then I get
bt socket is not in listen state
So, I don't know how to put it in "listen state" or why it wouldn't be. Has anyone experienced this or know how to workaround it? Or how to keep from getting the NPE
if I use the first snippet (if that is even correct).
I found
When I was getting an IOException
I found this post which led me here but this hasn't gotten me anywhere.
Notice: The bounty message says 4.4.4 but it is 4.4.2 on the Tab 4
Device Errors
I also notice these Bluetooth errors when I first connect my device to the computer through USB
09-05 15:18:03.217: E/BluetoothServiceJni(15148): SOCK FLAG = 0 *********************** 09-05 15:18:13.177: E/BluetoothServiceJni(15148): SOCK FLAG = 0 *********************** 09-05 15:18:13.217: E/BluetoothServiceJni(15148): SOCK FLAG = 0 ***********************
but I have not been able to find out what that flag means.
I realize there are known bugs in the BT stack 4.x (See one of many bug reports)
minSDK
is currently 10. Though, if I find a working solution then I can work around that.
Try this code, this is working android 4.4.2 on nexus 7
private boolean refreshDeviceCache(BluetoothGatt gatt){ try { BluetoothGatt localBluetoothGatt = gatt; Method localMethod = localBluetoothGatt.getClass().getMethod("refresh", new Class[0]); if (localMethod != null) { boolean bool = ((Boolean) localMethod.invoke(localBluetoothGatt, new Object[0])).booleanValue(); return bool; } } catch (Exception localException) { Log.e(TAG, "An exception occured while refreshing device"); } return false; } public boolean connect(final String address) { if (mBluetoothAdapter == null || address == null) { Log.w(TAG,"BluetoothAdapter not initialized or unspecified address."); return false; } // Previously connected device. Try to reconnect. if (mBluetoothGatt != null) { Log.d(TAG,"Trying to use an existing mBluetoothGatt for connection."); if (mBluetoothGatt.connect()) { return true; } else { return false; } } final BluetoothDevice device = mBluetoothAdapter .getRemoteDevice(address); if (device == null) { Log.w(TAG, "Device not found. Unable to connect."); return false; } // We want to directly connect to the device, so we are setting the // autoConnect // parameter to false. mBluetoothGatt = device.connectGatt(MyApp.getContext(), false, mGattCallback)); refreshDeviceCache(mBluetoothGatt); Log.d(TAG, "Trying to create a new connection."); return true;
}
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