在BLE蓝牙中一次写入超过20字节数据包的方法和技巧

        android是一个坑,蓝牙是android的坑中坑,BLE是蓝牙的坑中坑,而20字节数据包的限制是BLE中最不合理的坑,只要开发的APP需要与BLE通信,就绕不开这个坑,因为20字节的数据包的确太小了。如何跳出这个坑几乎是每一个开发者都要面临的问题。无论是网上还是论坛里关于跳这个坑的博文很多,当我也成为一个跳坑者的时候看了很多这样的博文,但是,这些博文中真正有过跳坑经历的作者很少,有知识、有营养的贴子很少,都是抄来抄去。本作者不做这样的搬运工,写的文章都是亲历的跳坑过程,如果所介绍的方法和技巧对你无效,那只可能设备和环境的个性差别所致。

        我现在所用的开发工具是android studio 3.5.2,具体的配置如下图:

在BLE蓝牙中一次写入超过20字节数据包的方法和技巧

       在版本为android 5.1.1的真实手机上实现手机与ble蓝牙模块JDY 16的通信,在手机与蓝牙建立起联系后,需要蓝牙模块透传一条72字节的数据时,发现模块只能接收到前20字节,因此掉入了这个坑。实验时是用两条链接的UUID作为数据传送到蓝牙模块,发现模块收到的信息是这样的:

在BLE蓝牙中一次写入超过20字节数据包的方法和技巧

收到的信息刚好是20字节。据商家说,JDY 16模块传送的数据包不受20字节的限制,因此,我把分包传送作为备选方案,先试试不分包的方法。网上说修改mtu数据就能够实现大于20字节数据包的传送,于是照葫芦画瓢地写了requestMtu()方法,并在requestMtu()方法的返回值和回调中捕捉到了mtu数据改变成功的信息,这个图是requestMtu()方法的返回值为真时信息:

在BLE蓝牙中一次写入超过20字节数据包的方法和技巧

这个图是回调后的控制台显示的信息,从最后一行看,mtu已经改变为100字节了。在这里,有些情况我已经确认,在发出修改mtu值的请求后,requestMtu()方法会返回一个判断结果,回调也会有一个mtu修改的结果,它们有时会有矛盾,看下图:

在BLE蓝牙中一次写入超过20字节数据包的方法和技巧

我发出了一个把mtu值修改成512字节的请求,requestMtu()方法返回了真,就是说我已经获得了512字节的mtu,但再看图的最后一行,控制台显示的mtu只有244,这个现象说明了一个事实:这个蓝牙4.2模块的最大mtu只有244,回调中的mtu值是正确的mtu值,requestMtu()方法返回值只能作为参考,并非你请求的mtu值就是你最后得到的mtu值,这个需要注意,如果发送的信息超过模块mtu的最大值,恐怕还是逃不出分包的命运哈。

        再回到实验中来,虽然上面的返馈信息都反映出我修改mtu的请求已经获得批准,应该可以发送超过20字节的数据包了,但是,app实际运行时蓝牙模块反而一个字节的信息都没有收到,看来连20字节的信息都没有发送出去,别说超过20字节啦。这坑真有点深了,看了很多文章,几乎没有文章说到这种情况,好像有一篇文章说到requestMtu()不工作,他怀疑是方法问题后也没有下文,似乎没有人解决过这个问题。我分析后认为,app和手机端的设置都已经成功了,问题应该出在蓝牙模块端,是不是哪个参数没有设置对?咨询了商家,回复说这款JDY 16模块默认就是无字节限制发送,无需进行设置。这样一来貌似走进了死胡同,找不到问题原因。不过,从一篇国外的文章中看到一个开发者说,请求修改了mtu后,需要updata mtu,只有updata后,新的mtu才能起作用,至于如何updata mtu,他只字未提。这个又给了一个提示,是不是有个updata mtu的方法?一番寻找后无果,就在我准备暂时放一放这个问题在坑里睡一觉的时候,突然灵机一动,难道是在回调成功后系统需要时间来重新布置新的mtu环境吗?于是,在收到回调信息后我加了一条sleep(200)语句:延时200毫秒等等,再运行app时奇迹出现了:

在BLE蓝牙中一次写入超过20字节数据包的方法和技巧

这个16进制显示的图,能看到有多少字节:

在BLE蓝牙中一次写入超过20字节数据包的方法和技巧

       这个免分包一次发送超20字节的方法终于成功了!这真的是踏破铁鞋无觅处,来得全不费功夫啊,成与不成之间就是一层纸。以下贴出关键的代码,供需要者参考。

调用requestMtu()方法后延时的代码:

在BLE蓝牙中一次写入超过20字节数据包的方法和技巧

 

这个是requestMtu()方法的代码:

在BLE蓝牙中一次写入超过20字节数据包的方法和技巧

这个是改变mtu请求发生后回调的处理代码:

在BLE蓝牙中一次写入超过20字节数据包的方法和技巧

这个是往JDY 16写的方法:

在BLE蓝牙中一次写入超过20字节数据包的方法和技巧

嗯,就是这么多了,有问题可以留言讨论。