一个Android SPP数据传输的坑

一、项目背景

最近负责一个项目,由音箱端录音,经Opus编码后,通过BLE/SPP传输给手机端,手机APP负责接收数据,然后对数据进行Opus解码,还原PCM数据,再提交到各云平台。对于Android手机,则使用SPP通道传输。



二、问题的产生

APP与蓝牙外设备交互分两种:

  • 指令控制数据:10 00 长度 控制指令ID
  • 音频数据:10 80 长度 音频数据

对于控制指令,没有什么疑问,因为都是单独的一条指令,且不需要解码。问题出在音频数据上,一直怀疑是Opus编码的问题,通过各种对比分析(IOS正常,所以用同一个数据包经两个客户解析,得到的数据如下),把Opus扒的只剩下一条小裤了,验证解析后的音频数据还是有问题。



好吧,那可能出在数据包上,丢包。

首先,因为音频数据比较多,怀疑是SPP数据来不及接收, 所以建立了接收缓存,然后再从队列中取数据进行解码,折腾了半天,解板出来的音频还是异常。此时的无奈和郁闷无法言语,睡觉中都在思考这个问题,最终天无绝人之路,把APP端接收到的数据全部打出来,发现音频数据跟之前定义的一次一包有差别。真实的数据是:

  • 几个音频数据包(10 80 长度 音频数据)合成一个SPP数据包,而按之前约定,只提取前面一包,后面的就没去考虑
  • 一个音频数据包被拆成两个SPP数据包,这种情况也会造成丢包

解决的办法:开启线程全部接收数据,再进行匹配,而不是一个一个SPP数据包处理。

到此,解析出来的音频数据终于听起来正常。

三、结论

Android SPP数据传输,特别是高频的数据传输,很可能不按原始数据一包一包发,而是重新组包,如一次给你发多包或拆包发送;出现问题时,要把传输数据打出来,站在不同的位置,看的问题会不一样。