Reputation: 35
My gattServer advertise some data with paired bluetooth device and I run this gattServer with service.Everthing is well with Bluetooth state on but I turned off bluetooth and on again throw exception this line
sGattServer.notifyCharacteristicChanged(device, getCharacteristic(Constants.NOTIFICATION_SOURCE), false);
This is my connection Method
BluetoothAdapter bleAdapter = ((BluetoothManager) context.getSystemService(BLUETOOTH_SERVICE)).getAdapter();
final Set<BluetoothDevice> pairedDevices = bleAdapter.getBondedDevices();
for (BluetoothDevice d : pairedDevices) {
d.connectGatt(context, true, new BluetoothGattCallback() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onConnectionStateChange(BluetoothGatt
gatt, int status, int newState) {
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
gatt.getServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
if (gatt !=null){
gatt.close();
gatt.disconnect();
gatt.connect();
}
break;
}
}
});
}
Stuck trace here:
10-23 10:04:53.978 27768-27768/E/BluetoothGattServer: android.os.DeadObjectException
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:496)
at android.bluetooth.IBluetoothGatt$Stub$Proxy.sendNotification(IBluetoothGatt.java:1482)
at android.bluetooth.BluetoothGattServer.notifyCharacteristicChanged(BluetoothGattServer.java:539)
Upvotes: 1
Views: 1167
Reputation: 3504
When Bluetooth is turned off, Android restarts the Bluetooth stack to clean up its state. Kind of like cracking a walnut with a 40lb sledge hammer. See the Logcat
2019-08-02 11:56:29.274 10736-10736/? D/BluetoothAdapterService: onDestroy()
2019-08-02 11:56:29.281 10736-10736/? I/BluetoothAdapterService: Force exit to cleanup internal state in Bluetooth stack
In your GattServer Service you need to recreate the BluetoothGattServer object when the Bluetooth is powered back on.
You did not show the code from your service, which is where the problem lies, but you will need to do something like the following. Create a method createServerGattService which defines the service UUID and characteristics of you GATT server service, then registers it with the BLE stack. You already have this because you say the GATT server works fine until you turn the Bluetooth adapter off snd on.
Add a Bluetooth adapter power state receiver to your service:
private BluetoothGattServer gattServer;
private final BroadcastReceiver m_bluetoothAdapterPowerStateeceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR);
switch (state) {
case BluetoothAdapter.STATE_OFF:
gattServer = null;
break;
case BluetoothAdapter.STATE_TURNING_OFF:
gattServer.close();
break;
case BluetoothAdapter.STATE_ON:
gattServer = createServerGattService();
break;
case BluetoothAdapter.STATE_TURNING_ON:
break;
}
}
}
};
In the onCreate() method of your service, register the receiver and instantiate your gatt server if the Bluetooth adapter is powered on:
@Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(m_bluetoothAdapterPowerStateeceiver, filter);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
gattServer = createServerGattService();
}
}
In the onDestroy() method of your service, remove the receiver and close the GATT server connection:
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(m_bluetoothAdapterPowerStateeceiver);
if(gattServer != null)
gattServer.close();
}
For completeness sake of the answer, the createServerGattService() should look something like this:
private BluetoothGattServer createServerGattService() {
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
BluetoothGattServer server = null;
if(bluetoothManager != null) {
server = bluetoothManager.openGattServer(this, new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
}
@Override
public void onServiceAdded(int status, BluetoothGattService service) {
super.onServiceAdded(status, service);
}
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
}
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
}
@Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
}
@Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
}
@Override
public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
super.onExecuteWrite(device, requestId, execute);
}
@Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
}
@Override
public void onMtuChanged(BluetoothDevice device, int mtu) {
super.onMtuChanged(device, mtu);
}
@Override
public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
super.onPhyUpdate(device, txPhy, rxPhy, status);
}
@Override
public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
super.onPhyRead(device, txPhy, rxPhy, status);
}
});
BluetoothGattService service = new BluetoothGattService(serviceUuid, BluetoothGattService.SERVICE_TYPE_PRIMARY);
BluetoothGattCharacteristic characteristic1 = new BluetoothGattCharacteristic(
characteristic1Uuid,
BluetoothGattCharacteristic.PROPERTY_READ,
BluetoothGattCharacteristic.PERMISSION_READ);
service.addCharacteristic(characteristic1);
server.addService(service);
}
return server;
}
Upvotes: 1