乐趣区

安卓如何提高ble传输速度

关于安卓传输最大只能传输 20 个 byte 的数据问题

前面这个问题答案是从网上取来,具体链接忘记了,如有冒犯,敬请原谅,这只是用来提醒自己以防忘记,链接 http://blog.csdn.net/sinat_19…。
做安卓开发的时候经常会遇到下面一个问题:
想在 gatt client 上(一般是手机上)传输长一点的数据给 gatt server(一般是一个 Bluetooth smart 设备,即只有 BLE 功能的设备),但通过 writeCharacteristic(BluetoothGattCharacteristic) 来写的时候发现最多只能写入 20 个 byte 的数据。

这篇文章会回答下面几个问题:

为什么会是 20?

core spec 里面定义了 ATT 的默认 MTU 为 23 个 bytes,除去 ATT 的 opcode 一个字节以及 ATT 的 handle2 个字节之后,剩下的 20 个字节便是留给 GATT 的了。考虑到有些 Bluetooth smart 设备功能弱小,不敢太奢侈的使用内存空间,因此 core spec 规定每一个设备都必须支持 MTU 为 23。
在两个设备连接初期,大家都像新交的朋友一样,不知对方底细,因此严格的按照套路来走,即最多一次发 20 个字节,是最保险的。
由于 ATT 的最大长度为 512byte,
因此一般认为 MTU 的最大长度为 512 个 byte 就够了,再大也没什么意义,你不可能发一个超过 512 的 ATT 的数据,就像是孙猴子跑不过五行山一样。
所以 ATT 的 MTU 的最大长度可视为 512 个 bytes。

如何突破 20?

很简单嘛,改变传输的 ATT 的 MTU 就行了,大家经过友好的协商,得到双方都想要的结果,是最好的。在 Android 上(API 21),改变 ATT MTU 的接口为:

    public boolean requestMtu (int mtu)  
      
    Added in API level 21  
    Request an MTU size used for a given connection.  
      
    When performing a write request operation (write without response), the data sent is truncated to the MTU size. This function may be used to request a larger MTU size to be able to send more data at once.  
      
    A onMtuChanged(BluetoothGatt, int, int) callback will indicate whether this operation was successful.  
      
    Requires BLUETOOTH permission.  
      
    Returns  
    true, if the new MTU value has been requested successfully  

大声的说出来你想要一下子传多少,调用上面的接口就可以了,然后在下面的函数中看最终结果(当然了,如果你的 peripheral 申请改变 MTU 并且成功的话,那这个回调也会被调用):

    @Override  
    public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {super.onMtuChanged(gatt, mtu, status);  
      
        if (status == BluetoothGatt.GATT_SUCCESS) {this.supportedMTU = mtu;//local var to record MTU size}  
    }  

之后你就可以快乐的发送 supportedMTU- 3 的长度的数据了。

如何更优雅的来实现?

俗话说得好,郎有情就怕妾无意。万一对方设备不同意你的请求怎么办?

对于 app 来说,一般是知道自己要最大发送多少数据的,例如一次要发 100 个 bytes,那么就首先试试申请一下 103,失败的话,则申请一下 53,即二分法,剩下的只能自己分段拆着发了。

一般来讲,app 的开发者和对端设备的开发者都是同一伙儿人,这是好事儿,他们可以根据自己设备的硬件情况,来商量 MTU 应该是多少。

总之,把事儿摆到桌面上,提前做好,会使得你的程序更加 professional。

另外,cc2540/1 是属于蓝牙 4.0 规范的,所以不支持修改 mtu,但是 cc2640 以后的 ble 4.1 规范就可以修改这个特性了,所以 2640 以后的传输速度是一个飞跃的提升

硬件使用 2540 的情况下安卓如何提升速度呢?

鉴于 2540 现在价格比较低,市场上大多数产品都是用这样的 4.0 协议的芯片的,所以这种情况下开发安卓应用,你总不能和客户说安卓发送接收比较慢,苹果的比较快,请你去买苹果手机吧!这样客户不请你吃拳头才怪。
所以我们可以使用下面的代码修改一下下,还是以 simpleBLEPeripheral 工程为例子:

// Minimum connection interval (units of 1.25ms, 80=100ms) if automatic parameter update request is enabled
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL     16//80

// Maximum connection interval (units of 1.25ms, 800=1000ms) if automatic parameter update request is enabled
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL     16//800

simpleBLEPeripheral.c 下面宏定义有以上 2 条信息,是定义最小和最大连接间隔的,我们要定义到最小值 16,让安卓设备和 BLE 设备保持连接,这样传输就能好好地了;实测如果进行 OAD 的话,不修改要 30-60min,如果修改后就变成 8min 了,对比苹果还是有距离,但是已经缩小很多了

退出移动版