I have implemented BLE communications on Android. I'm negotiating the MTU on the client side using requestMtu. This works well, as the client gets the MTU change on onMtuChanged. However, I still don't have the means to know the MTU on the server side, only the client. I implement my own mechanism for fragmentation/segmentation as sometimes I'm sending reasonable amounts of data. I'd like to segment the data according to MTU size for faster communications. I'm currently sending 20 bytes at a time on the server side, which works but is slower. Is there a way to get the MTU on the server?
The way I made this work was to wait for a connection, then create a connection with the device that connected via the onConnectionStateChange(...)
function.
private final BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
if (newState == Bluetooth.STATE_CONNECTED)
device.connectGatt(MainActivity.this, false, mGattCallback);
super.onConnectionStateChange(device, status, newState);
}
This allowed me to requestMtu() on the resulting successful connection.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == Bluetooth.STATE_CONNECTED) {
gatt.requestMtu(512);
}
super.onConnectionStateChange(gatt, status, newState);
}
};
The requestMtu call will lead to a Gatt MTU exchange between the client & server。The smaller mtu will be the final one in use。 If you want to know the mtu size on the server side, just give a parameter big enough to the “requestMtu” call, and get the result in “onMtuChanged”。 Alternatively,see your btsnoop file on the platform & you will get exactly what the mtu size on the server is.
BluetoothGattServerCallback
has the method onMtuChanged
that you can override and directly obtain the MTU once negotiated (after request from central side):
@Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
this.mtu = mtu;
Log.i(TAG, "New MTU: " + mtu + " , Status: " + status + " , Succeed: " + (status == BluetoothGatt.GATT_SUCCESS));
}
Per the Bluetooth Core specification document, in 3.F 3.2.8:
A device that is acting as a server and client at the same time shall use the same value for Client Rx MTU and Server Rx MTU.
Therefore, use MTU you get through GATT client API, it has to be the same.
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