[关闭]
@zifeng328573112 2021-03-17T02:04:50.000000Z 字数 7625 阅读 458

蓝牙SDK技术

Android-BLE蓝牙框架,提供了扫描、连接、使能/除能通知、发送/读取数据、接收数据,读取rssi,设置mtu等蓝牙相关的所有操作接口,内部优化了连接队列,以及快速写入队列,并支持多服务通讯,可扩展配置蓝牙相关操作。

1. Android-BLE API

2. 异常状态码

  1. public static final int NotInit = 2000; //初始化失败
  2. public static final int InitAlready = 2001; //已初始化
  3. public static final int NotSupportBLE = 2005;// 不支持BLE
  4. public static final int BluetoothNotOpen = 2006; // 蓝牙未打开
  5. public static final int NotAvailable = 2007; // 无法使用
  6. public static final int BlePermissionError = 2008; // 蓝牙权限错误
  7. public static final int NotFindDevice = 2009; // 未查找到设备
  8. public static final int InvalidAddress = 2010; // 无效地址
  9. public static final int ScanAlready = 2020; // 已扫描
  10. public static final int ScanStopAlready = 2021; // 已扫描停止
  11. public static final int ScanFrequentlyError = 2022; // 扫描出现异常
  12. public static final int ScanError = 2023; // 扫描异常
  13. public static final int ConnectedAlready = 2030; // 已连接
  14. public static final int ConnectFailed = 2031; // 连接失败
  15. public static final int ConnectError = 2032; // 连接错误
  16. public static final int ConnectException = 2033; // 连接异常
  17. public static final int ConnectTimeOut = 2034; // 连接超时
  18. public static final int MaxConnectNumException = 2035; // 最大连接数异常
  19. public static final int NoService = 2040; // 没有信号
  20. public static final int DeviceNull = 2041; // 设备为空
  21. public static final int NotInitUuid = 2045;// 未初始化Uuid
  22. public static final int CharaUuidNull = 2050; //Chara Uuid为空

3. 接入前提示

1) 如果项目中的设备是统一类型(服务,特征uuid相同),则推荐在初始化时把服务,特征的uuid配置完整。
2) 如果项目中需要兼容多种设备类型(服务,特征uuid不相同),则在通信时需要使用byUuid的方式进行。

4. 接入文档

1)build.gradle 中添加下面依赖. Download(https://bintray.com/superliu/maven/BleLib/_latestVersion)

implementation 'cn.com.superLei:blelibrary:latestVersion'

2) 在Application中初始化.

  1. private void initBle() {
  2. Ble.options()//开启配置
  3. .setLogBleEnable(true)//设置是否输出打印蓝牙日志(非正式打包请设置为true,以便于调试)
  4. .setThrowBleException(true)//设置是否抛出蓝牙异常 (默认true)
  5. .setAutoConnect(false)//设置是否自动连接 (默认false)
  6. .setIgnoreRepeat(false)//设置是否过滤扫描到的设备(已扫描到的不会再次扫描)
  7. .setConnectTimeout(10 * 1000)//设置连接超时时长(默认10*1000 ms)
  8. .setMaxConnectNum(7)//最大连接数量
  9. .setScanPeriod(12 * 1000)//设置扫描时长(默认10*1000 ms)
  10. .setScanFilter(scanFilter)//设置扫描过滤
  11. .setUuidService(UUID.fromString(UuidUtils.uuid16To128("fd00")))//设置主服务的uuid(必填)
  12. .setUuidWriteCha(UUID.fromString(UuidUtils.uuid16To128("fd01")))//设置可写特征的uuid (必填,否则写入失败)
  13. .setUuidReadCha(UUID.fromString(UuidUtils.uuid16To128("fd02")))//设置可读特征的uuid (选填)
  14. .setUuidNotifyCha(UUID.fromString(UuidUtils.uuid16To128("fd03")))//设置可通知特征的uuid (选填,库中默认已匹配可通知特征的uuid)
  15. .setUuidServicesExtra(new UUID[]{BATTERY_SERVICE_UUID})//设置额外的其他服务组,如电量服务等
  16. .setFactory(new BleFactory() {//实现自定义BleDevice时必须设置
  17. @Override
  18. public MyDevice create(String address, String name) {
  19. return new MyDevice(address, name);//自定义BleDevice的子类
  20. }
  21. })
  22. .setBleWrapperCallback(new MyBleWrapperCallback())//设置全部蓝牙相关操作回调(例: OTA升级可以再这里实现,与项目其他功能逻辑完全解耦)
  23. .create(mApplication, new Ble.InitCallback() {
  24. @Override
  25. public void success() {
  26. BleLog.e("MainApplication", "初始化成功");
  27. }
  28. @Override
  29. public void failed(int failedCode) {
  30. BleLog.e("MainApplication", "初始化失败:" + failedCode);
  31. }
  32. });
  33. }

3. 开始使用

  1. ble.startScan(scanCallback);
  1. BleScanCallback<BleDevice> scanCallback = new BleScanCallback<BleDevice>() {
  2. @Override
  3. public void onLeScan(final BleDevice device, int rssi, byte[] scanRecord) {
  4. //Scanned devices
  5. }
  6. @Override
  7. public void onStart() {
  8. super.onStart();
  9. }
  10. @Override
  11. public void onStop() {
  12. super.onStop();
  13. }
  14. @Override
  15. public void onScanFailed(int errorCode) {
  16. super.onScanFailed(errorCode);
  17. Log.e(TAG, "onScanFailed: "+errorCode);
  18. }
  19. };
  1. //连接设备
  2. ble.connect(device, connectCallback);
  3. //连接多个设备
  4. ble.connects(devices, connectCallback);
  5. //取消正在连接的设备
  6. ble.cancelConnecting(device);
  7. //取消正在连接的多个设备
  8. ble.cancelConnectings(devices);
  9. //断开设备
  10. ble.disconnect(device);
  11. //断开所有设备
  12. ble.disconnectAll();
  13. 连接/断开回调
  14. private BleConnCallback<BleDevice> connectCallback = new BleConnCallback<BleDevice>() {
  15. @Override
  16. public void onConnectionChanged(BleDevice device) {
  17. }
  18. @Override
  19. public void onConnectTimeOut(BleDevice device) {
  20. super.onConnectTimeOut(device);
  21. Log.e(TAG, "onConnectTimeOut: " + device.getBleAddress());
  22. }
  23. @Override
  24. public void onConnectCancel(BleDevice device) {
  25. super.onConnectCancel(device);
  26. Log.e(TAG, "onConnectCancel: " + device.getBleName());
  27. }
  28. @Override
  29. public void onServicesDiscovered(BleDevice device, BluetoothGatt gatt) {
  30. super.onServicesDiscovered(device, gatt);
  31. }
  32. @Override
  33. public void onReady(BleDevice device) {
  34. super.onReady(device);
  35. //connect successful to enable notification
  36. ble.enableNotify(...);
  37. }
  38. @Override
  39. public void onConnectException(BleDevice device, int errorCode) {
  40. super.onConnectException(device, errorCode);
  41. }
  42. };
  1. ble.enableNotify(device, true, new BleNotifyCallback<BleDevice>() {
  2. @Override
  3. public void onChanged(BleDevice device, BluetoothGattCharacteristic characteristic) {
  4. UUID uuid = characteristic.getUuid();
  5. BleLog.e(TAG, "onChanged==uuid:" + uuid.toString());
  6. BleLog.e(TAG, "onChanged==data:" + ByteUtils.toHexString(characteristic.getValue()));
  7. }
  8. @Override
  9. public void onNotifySuccess(BleDevice device) {
  10. super.onNotifySuccess(device);
  11. BleLog.e(TAG, "onNotifySuccess: "+device.getBleName());
  12. }
  13. });
  1. ble.read(device, new BleReadCallback<BleRssiDevice>() {
  2. @Override
  3. public void onReadSuccess(BleRssiDevice dedvice, BluetoothGattCharacteristic characteristic) {
  4. super.onReadSuccess(dedvice, characteristic);
  5. }
  6. @Override
  7. public void onReadFailed(BleRssiDevice device, int failedCode) {
  8. super.onReadFailed(device, failedCode);
  9. }
  10. })
  1. //写入一包数据
  2. ble.write(device, data, new BleWriteCallback<BleRssiDevice>() {
  3. @Override
  4. public void onWriteSuccess(BleRssiDevice device, BluetoothGattCharacteristic characteristic) {
  5. }
  6. @Override
  7. public void onWriteFailed(BleRssiDevice device, int failedCode) {
  8. super.onWriteFailed(device, failedCode);
  9. }
  10. });
  11. //写入大数据(文件、图片等)
  12. byte[]data = toByteArray(getAssets().open("WhiteChristmas.bin"));
  13. ble.writeEntity(mBle.getConnectedDevices().get(0), data, 20, 50, new BleWriteEntityCallback<BleDevice>() {
  14. @Override
  15. public void onWriteSuccess() {
  16. }
  17. @Override
  18. public void onWriteFailed() {
  19. }
  20. override void onWriteProgress(double progress) {
  21. }
  22. override void onWriteCancel() {
  23. }
  24. });
  25. //写入数据到队列中 (默认发送间隔50ms)
  26. ble.writeQueue(RequestTask.newWriteTask(address, data));
  27. //写入数据到队列中 (自定义间隔时间)
  28. ble.writeQueueDelay(delay, RequestTask.newWriteTask(address, data));
  29. //通过特定服务和特征值uuid写入数据
  30. ble.writeByUuid(device, data, serviceUuid, charUuid, new BleWriteCallback<BleRssiDevice>() {
  31. @Override
  32. public void onWriteSuccess(BleRssiDevice device, BluetoothGattCharacteristic characteristic) {
  33. }
  34. @Override
  35. public void onWiteFailed(BleRssiDevice device, int failedCode) {
  36. super.onWiteFailed(device, failedCode);
  37. }
  38. });
  1. ble.cancelCallback(connectCallback);
  2. ble.cancelCallback(scanCallback);
  1. ble.released();

5. 连接常见问题

1. BLE设备扫描不到

2. BLE能扫描到连接不上或者连接数量不固定

用BLE的API去连接非BLE的设备,其次就是导致这个问题的原因很多,比如蓝牙协议栈异常,最常见的就是底层返回蓝牙连接状态status为133、257、19等等,出现这个问题的时候最好去排查下自己的代码中有没有在断开的回调中手动释放gatt对象(bluetoothGatt.close()),如果有做的话,更换不同型号的手机继续测试,如果还是这样,那么很可能就不是客户端这边的问题,你就要去同硬件去沟通了,需要硬件那边调整下连接参数,优化设置BLE连接过程中的传输速度和功耗。

注意:有的在这块出了问题就一直在应用层找原因,一直以为是自己代码哪里做错了,弄到最后才发现并不是自己的问题,而是硬件那边的问题,具体问题我也不是很懂,要问硬件咯!所以我建议出了问题从两点去测试,
1、同一个硬件分别和不同的手机去测试。
2、同一个手机分别和不同的硬件进行测试。因为关于蓝牙这块,特别是BLE协议这块是比较坑的,因为Android手机被各大手机各种深度定制,手机蓝牙硬件模块每个手机厂商都是不太一致的,稳定性更是不同,举个例子:有的手机可能同时连接4个或者4个以上的BLE设备都没有问题,但是有的手机可能连接3个还是比较稳定的,连接第4个的时候也能连接上,但是会出现偶尔断开这种现象,这个就确实没有办法解决的,所以有的小伙伴经常会问我,有没有办法让连接10个啊? 确实没有办法,如果有办法的话,那麻烦请你纠正我。

3. 连接成功后会自动断开

这个问题并不是客户端的问题,所以不要一味的在代码中找问题了,建议与硬件沟通,让其进行优化,如可以调整设备的连接参数(ConnectionInterval(连接间隔)、SlaveLatency(从设备延迟或者从设备时延)、SupervisionTimeout(超时时间或者监控超时)),这三个参数是低功耗蓝牙中十分重要的连接参数,一起决定了BLE的功耗,一般硬件设备会在APP连接成功时主动去更新一下这三个参数,以保证不同手机的差异性得到一致,但是APP端是没办法控制这三个参数的。

4. 该库的连接状态的状态码

5. 为什么要分包发送

BLE4.0蓝牙发送数据,单次最大传输20个byte,如果是一般的协议命令,如:开关灯、前进左右等等,是不需要分包的,如果是需要发送如:图片、BIN文档、音乐等大数据量的文件,则必须进行分包发送,BLE库中已经提供了发送大数据包的接口,需要的小伙伴可以去下载DEMO查看用法。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注