I establish a BLE connection to send data between devices (each 10 seconds aproximately they makes a new connection, send data, and then desconnect) and normally works fine. However, after some minutes, the devices never connect again and the device that should connect with the other is in loop calling "ACTION_GATT_DISCONNECTED" (this String is refering to disconnected receiver action).
In my receiver I've 3 relevant actions:
@Override
public void onReceive(Context context, Intent intent) {
customBluetoothManager = customBluetoothManager.getInstance(context, null, null);
final String action = intent.getAction();
Log.d("test", "onReceive");
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
Log.d("test", action);
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
Log.d("test", action);
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
Log.d("test", action);
//....
//Code to send data after services discovered
//....
}
}
So, during the first minutes all is working fine. First is calling to the ACTION_GATT_CONNECTED, then ACTION_GATT_SERVICES_DISCOVERED action is invoked, then the device sends the data, and after that it disconnects and releases the bluetooth communication channel. The problem is that, sometimes, and not always at the same point (by this reason I can't be able to find any pattern to reproduce this issue), is in loop always calling to ACTION_GATT_DISCONNECTED, so the communication never will be established.
The ACTION_GATT_DISCONNECTED is assigned in the onConnectionSateChange callback from BluetoothGattCallback class:
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
mBluetoothGatt.close();
}
}
I have no idea of what can be the problem... Any suggestion?
---------- UPDATE --------------
Updated with the callback that makes the connection:
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
String name = device.getName();
long epoch = System.currentTimeMillis() / 1000;
SharedPreferences prefs = context.getSharedPreferences(
"epoch", Context.MODE_PRIVATE);
long epochStored = prefs.getLong("epoch", 0);
if (name != null && name.compareTo(bluetoothDeviceName) == 0 && (epochStored == 0 || epochStored < epoch - Utils.getDelay())) {
mac = device.getAddress();
mDeviceAddress = device.getAddress();
final Intent gattServiceIntent = new Intent(context, BluetoothLeService.class);
if (!connected) {
Utils.setMessageLog(ac, tv, "Binding service");
context.bindService(gattServiceIntent, mServiceConnection, context.BIND_AUTO_CREATE);
} else {
mBluetoothLeService.connect(mac);
}
}
}
};
Connect function:
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
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;
}
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
After the connection is succesfully, I receive a "SERVICES_DISCOVERED" action in my receiver and I write a characteristic through this code:
public void sendData() {
List<BluetoothGattService> listServices = mBluetoothLeService.getSupportedGattServices();
BluetoothGattService bluetoothGattService = null;
for (BluetoothGattService gattService : listServices) {
if (gattService.getUuid().compareTo(myUUID) == 0) {
bluetoothGattService = gattService;
}
}
if(bluetoothGattService != null) {
List<BluetoothGattCharacteristic> gattCharacteristics = bluetoothGattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<BluetoothGattCharacteristic>();
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
if (gattCharacteristic.getUuid().compareTo(myCharUUID)) == 0) {
charas.add(gattCharacteristic);
boolean status = mBluetoothLeService.writeCharacteristic(gattCharacteristic, Utils.getUserData(context, "id"));
}
}
}
}
The first times that the bluetooth communication is established works fine.
------------- 2nd update --------------
I'm calling close() to release the connection:
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
disconnect();
close();
}
close() function:
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
----------- UPDATE WITH ERROR LOG ------------
05-31 11:14:38.581 5897-6100/app D/OCSC: Status: 0
05-31 11:14:38.581 5897-6100/app D/OCSC: New State: 2
05-31 11:15:08.361 5897-6073/app D/OCSC: Status: 0
05-31 11:15:08.361 5897-6073/app D/OCSC: New State: 2
05-31 11:15:35.031 5897-6010/app D/OCSC: Status: 0
05-31 11:15:35.031 5897-6010/app D/OCSC: New State: 2
05-31 11:16:08.331 5897-5909/app D/OCSC: Status: 0
05-31 11:16:08.341 5897-5909/app D/OCSC: New State: 2
05-31 11:16:36.031 5897-5908/app D/OCSC: Status: 0
05-31 11:16:36.031 5897-5908/app D/OCSC: New State: 2
05-31 11:17:08.341 5897-6100/app D/OCSC: Status: 0
05-31 11:17:08.341 5897-6100/app D/OCSC: New State: 2
05-31 11:17:38.621 5897-6100/app D/OCSC: Status: 0
05-31 11:17:38.621 5897-6100/app D/OCSC: New State: 2
05-31 11:18:08.431 5897-6058/app D/OCSC: Status: 0
05-31 11:18:08.431 5897-6058/app D/OCSC: New State: 2
05-31 11:18:38.011 5897-6123/app D/OCSC: Status: 0
05-31 11:18:38.011 5897-6123/app D/OCSC: New State: 2
05-31 11:19:13.451 5897-6123/app D/OCSC: Status: 133
05-31 11:19:13.451 5897-6123/app D/OCSC: New State: 0
When the disconnect problem occurs, I've seen that always is shown the new state as 22 or 133 (only one time I've seen new state as 19).
D/OCSC: New State: 133
D/OCSC: Status: 0
D/OCSC: New State: 133
D/OCSC: Status: 0
D/OCSC: New State: 133
D/OCSC: Status: 0
D/OCSC: New State: 22
D/OCSC: Status: 0
D/OCSC: New State: 22
D/OCSC: Status: 0
D/OCSC: New State: 22
D/OCSC: Status: 0
Error that I've found on btsnoop_hci.log:
Rcvd Error Response - Attribute Not Found, Handle: 0x0005, Handle: 0x0005 (Generic Access Profile: Appearance)
Sent Read By Type Request, GATT Include Declaration, Handles: 0x0006..0x0008
Rcvd Error Response - Attribute Not Found, Handle: 0x0006, Handle: 0x0006 (Generic Attribute Profile)
....
Rcvd Error Response - Attribute Not Found, Handle: 0x0008, Handle: 0x0008 (Generic Attribute Profile: Service Changed)
....
Rcvd Error Response - Attribute Not Found, Handle: 0x0102, Handle: 0x0102 (Unknown: Unknown)
....
Rcvd Error Response - Invalid Attribute Value Length, Handle: 0x0102, Handle: 0x0102 (Unknown: Unknown)
Logcat (test 1):
BluetoothGatt: onClientConnectionState() - status=0 clientIf=10
OCSC : Status: 0
OCSC : New State: 2
OCSC : Connected to GATT server.
BluetoothGatt: discoverServices()
BluetoothLeService: Attempting to start service discovery:true
test : com.example.bluetooth.le.ACTION_GATT_CONNECTED
BluetoothGatt: onClientConnectionState() - status=22 clientIf=8
BluetoothGatt: onClientConnectionState() - status=22 clientIf=10
BtGatt.GattService: onDisconnected() - clientIf=12
luetoothGatt: onClientConnectionState() - status=22 clientIf=11
BluetoothGatt: onClientConnectionState() - status=22 clientIf=12
OCSC : Status: 22
OCSC : New State: 0
OCSC : Disconnected from GATT server.
OCSC : Status: 22
OCSC : New State: 0
OCSC : Disconnected from GATT server.
OCSC : Status: 22
OCSC : New State: 0
OCSC : Disconnected from GATT server.
OCSC : Status: 22
OCSC : New State: 0
OCSC : Disconnected from GATT server.
BluetoothGatt: close()
BluetoothGatt: close()
BluetoothGatt: close()
BluetoothGatt: close()
Logcat (test 2):
BluetoothGatt: onClientConnectionState() - status=133 clientIf=7
OCSC : Status: 133
OCSC : New State: 0
OCSC : Disconnected from GATT server.
BluetoothGatt: close()
BluetoothGatt: onClientConnectionState() - status=133 clientIf=7
OCSC : Status: 133
OCSC : New State: 0
OCSC : Disconnected from GATT server.
BluetoothGatt: close()
BluetoothGatt: onClientConnectionState() - status=22 clientIf=12
OCSC : Status: 22
OCSC : New State: 0
OCSC : Disconnected from GATT server.
BluetoothGatt: close()
Any ideas?