经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » HTML/CSS » LESS » 查看文章
Android BLE 蓝牙开发之实现扫码枪基于BLESSED开发
来源:jb51  时间:2022/3/29 8:43:36  对本文有异议

一、蓝牙模式HID与BLE

当扫码枪与手机连接时,通常采用的是蓝牙HID(Human Interface Device)模式。本质上是一个把扫码枪作为一个硬件键盘,按照键盘协议把扫码后的结果逐个输入到对应的控件上。

优点:无需开发集成,配对就可以立即作为键盘输入使用。可以使用输入框等组件直接接收扫码结果。

缺点:对非数字支持不佳,与输入法相关,在某些时候会触发英文联想-_-||,与虚拟键盘会发生冲突,连接扫码枪时需要切换键盘输入法输入。

而我们要扫描的标签,不仅有英文,特殊符号,还有中文,因此以HID模式接入的蓝牙扫码枪,最终是不能满足要求的。于是重新选型了支持BLE模式的扫码枪。

BLE模式扫码枪

优点:兼容性好,遵循蓝牙协议,与键盘输入法无关。更底层,直接返回原始二进制数据流,方便判定编码以及进行字符编码转换。

缺点:需要进行原生开发, 处理设备扫描,连接,数据读写等操作。

二、BLE协议白话

好在有github,其中的BLESSED for Android - BLE made easy 项目,就是一个致力于简化android上BLE开发工作的开源库。但在撸代码前还是要简单理解下BLE协议的主要概念。

较为重要的两个东西是Service(服务) 与Characteristic(特性,译为功能可能更好理解),简而言之,一个设备可以提供多个服务,每个服务可以提供多个特性功能,每个服务及特性对应一个UUID。

与设备的通信通过功能进行,每个功能通过Properties(属性)表明该特性支持读,写或者通知。

为了便于理解BLE协议,推荐下载一个叫做“BLE调试助手”的APP。下面是APP的截图。

截图演示了如何从一个支持BLE协议的设备中读取电量,不需要提前配对,打开APP扫描到对应设备后,点击Connect, 随后列出的就是一堆上面说的Service(服务),能够显示服务名称的如“Battery Service”,是根据UUID的约定取得的。

如电池服务为0x180F。点开服务后是Characteristic,其中的Battery Level(也是UUID约定 0x2A19)的Properties为 READ NOTIFY,表明该特性支持读取和通知。

点击那个下箭头,点击读取,显示出返回数据为0x5D(十进制估计九十多:-0)。

电池服务是一个在协议中约定的标准服务,但扫码枪的似乎不是,我们还需要找到扫码后,是通过哪个Service的哪个Characteristic进行通知的,通过这个工具APP也不难找,注意,要打开那个接受通知数据。

扫码后会有数据显示,找到之后就可以开始编码了。

三、第三方库 BLESSED for Android的使用

https://github.com/weliem/blessed-android

下面进入具体的撸代码环节

安装 gradle file加入

  1. allprojects {
  2. repositories {
  3. ...
  4. maven { url 'https://jitpack.io' }
  5. }
  6. }
  7.  
  8. dependencies {
  9. implementation 'com.github.weliem:blessed-android:2.0.6'

扫描设备

  1. BluetoothCentralManager central = new BluetoothCentralManager(AppContext.baseAppContext,
  2. bluetoothCentralManagerCallback,
  3. new Handler(Looper.getMainLooper()));
  4. central.scanForPeripherals();

bluetoothCentralManagerCallback是扫描回调方法,重要的有下面三个

  1. //发现了一个设备
  2. @Override
  3. public void onDiscoveredPeripheral(BluetoothPeripheral peripheral, ScanResult scanResult)
  4. //连接设备
  5. @Override
  6. public void onConnectedPeripheral(BluetoothPeripheral peripheral)
  7. //设备断开
  8. @Override
  9. public void onDisconnectedPeripheral(BluetoothPeripheral peripheral, HciStatus status)

发现设备后onDiscoveredPeripheral,连接设备,停止扫描 。bluetoothPeripheralCallback 为设备回调,用于接受通知

  1. central.autoConnectPeripheral(peripheral, bluetoothPeripheralCallback);
  2. central.stopScan();

onConnectedPeripheral连接后查询提供的服务及特性

  1. Log.i("BLE","onConnectedPeripheral");
  2. List<BluetoothGattService> serviceList = peripheral.getServices();
  3. for (int i = 0; i < serviceList.size(); i++) {
  4. Log.i("BLE", "Service: " + serviceList.get(i).getUuid());
  5. if(serviceList.get(i).getUuid().toString().equals("6e400001-b5a3-f393-e0a9-e50e24dcca9e")){
  6. List<BluetoothGattCharacteristic> list= serviceList.get(i).getCharacteristics();
  7. for (int j = 0; j < list.size(); j++) {
  8. Log.i("BLE", "Characteristic: " + list.get(j).getUuid());
  9. }
  10. }
  11. }

onConnectedPeripheral后,对特性开启通知,接受扫码结果,服务的和特性的UUID,需要对应填写,扫码结果是以通知信息返回的。

  1. BluetoothGattCharacteristic currentTimeCharacteristic = peripheral.getCharacteristic(SERVICE_UUID, CURRENT_TIME_CHARACTERISTIC_UUID);
  2. if (currentTimeCharacteristic != null) {
  3.    //开启通知
  4. peripheral.setNotify(currentTimeCharacteristic, true);
  5. }
  6. //与设备通信需要创建绑定
  7. boolean bret= peripheral.createBond();

断开重连可以在onDisconnectedPeripheral中处理

接收扫码结果 在设备回调类 bluetoothPeripheralCallback中的下列方法处理。其中value为扫到的二维码值

  1. @Override
  2. public void onCharacteristicUpdate(@NonNull BluetoothPeripheral peripheral, @NonNull byte[] value, @NonNull BluetoothGattCharacteristic characteristic, @NonNull GattStatus status)

另:

  • 中文编码通常为GBK或者UTF8,需要猜测判断,最后附了个工具函数  
  • 因为BLE默认数据包较短,对大量数据,会拆分多次发送,onCharacteristicUpdate会被调用多次,需要将value拼接后,进行字符编码判断处理。  
  1. public static Boolean isUtf8(byte[] buffer) {
  2. boolean isUtf8 = true;
  3. int end = buffer.length;
  4. for (int i = 0; i < end; i++) {
  5. byte temp = buffer[i];
  6. if ((temp & 0x80) == 0) {// 0xxxxxxx
  7. continue;
  8. } else if ((temp & 0xC0) == 0xC0 && (temp & 0x20) == 0) {// 110xxxxx 10xxxxxx
  9. if (i + 1 < end && (buffer[i + 1] & 0x80) == 0x80 && (buffer[i + 1] & 0x40) == 0) {
  10. i = i + 1;
  11. continue;
  12. }
  13. } else if ((temp & 0xE0) == 0xE0 && (temp & 0x10) == 0) {// 1110xxxx 10xxxxxx 10xxxxxx
  14. if (i + 2 < end && (buffer[i + 1] & 0x80) == 0x80 && (buffer[i + 1] & 0x40) == 0
  15. && (buffer[i + 2] & 0x80) == 0x80 && (buffer[i + 2] & 0x40) == 0) {
  16. i = i + 2;
  17. } else if ((temp & 0xF0) == 0xF0 && (temp & 0x08) == 0) {// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  18. if (i + 3 < end && (buffer[i + 1] & 0x80) == 0x80 && (buffer[i + 1] & 0x40) == 0
  19. && (buffer[i + 2] & 0x80) == 0x80 && (buffer[i + 2] & 0x40) == 0
  20. && (buffer[i + 3] & 0x80) == 0x80 && (buffer[i + 3] & 0x40) == 0) {
  21. i = i + 3;
  22. }
  23. isUtf8 = false;
  24. break;
  25. }
  26. return isUtf8;
  27. }

到此这篇关于Android BLE 蓝牙开发之实现扫码枪基于BLESSED开发的文章就介绍到这了,更多相关Android BLE 蓝牙开发内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号