什么是MTU
MTU(Maximum Transmission Unit),最大传输单元,是指一种通信协议的某一层上面所能通过的最大数据报大小(以字节为单位)。而在Android BLE开发中,则指每包数据能携带的最大字节上限。
为什么要设置MTU
Android BLE传送数据时,MTU的默认值是23byte,除掉GATT协议往包头加上的3个字节,留给开发人员的就是20byte,也就是说正常情况下,App通过BLE每包传输的数据最多只能是20byte。当某个功能需要传输大量的数据时,比如固件升级,我们的固件虽然只有几百KB大小,却居然要分上万个包,传输需要十多分钟,显然效率太低。而通过设置MTU,最高可以将MTU调整到512Byte,从而大大提高数据传输的效率。
前提条件
动态设置MTU,需要传输的双方都支持才行,此外还有一些前提条件:
- 软件层面,Android API版本>=21(Android 5.0),才支持设置MTU。
- 硬件层面,蓝牙4.2及以上的模块,才支持设置MTU。
对于第一个限制,比较好适配,编码时只需要判断手机系统版本,API>=21才走动态设置MTU的逻辑即可。
对于第二个限制,稍微麻烦,因为目前没有接口可以查询手机蓝牙的版本,只能在请求设置MTU的回调里进行判断,如果设置失败,则仍然走默认的逻辑,相当于仍然使用默认的20byte。
代码实例
private void setMtu(int setMtu) {
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
bluetoothAdapter.startLeScan(new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
device.connectGatt(DemoActivity.this, true, new BluetoothGattCallback() {
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (setMtu > 23 && setMtu < 512) {
gatt.requestMtu(setMtu);
}
}
}
@Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
mMtu = mtu;
if (BluetoothGatt.GATT_SUCCESS == status && setMtu == mtu) {
LogUtils.d("MTU change success = " + mtu);
} else {
LogUtils.d("MTU change fail!");
}
}
});
}
});
}
网友评论