網(wǎng)站首頁 編程語言 正文
Android?BLE?藍(lán)牙開發(fā)之實(shí)現(xiàn)掃碼槍基于BLESSED開發(fā)_Android
作者:鍋叔 ? 更新時(shí)間: 2022-06-01 編程語言一、藍(lán)牙模式HID與BLE
當(dāng)掃碼槍與手機(jī)連接時(shí),通常采用的是藍(lán)牙HID(Human Interface Device)模式。本質(zhì)上是一個(gè)把掃碼槍作為一個(gè)硬件鍵盤,按照鍵盤協(xié)議把掃碼后的結(jié)果逐個(gè)輸入到對(duì)應(yīng)的控件上。
優(yōu)點(diǎn):無需開發(fā)集成,配對(duì)就可以立即作為鍵盤輸入使用。可以使用輸入框等組件直接接收掃碼結(jié)果。
缺點(diǎn):對(duì)非數(shù)字支持不佳,與輸入法相關(guān),在某些時(shí)候會(huì)觸發(fā)英文聯(lián)想-_-||,與虛擬鍵盤會(huì)發(fā)生沖突,連接掃碼槍時(shí)需要切換鍵盤輸入法輸入。
而我們要掃描的標(biāo)簽,不僅有英文,特殊符號(hào),還有中文,因此以HID模式接入的藍(lán)牙掃碼槍,最終是不能滿足要求的。于是重新選型了支持BLE模式的掃碼槍。
BLE模式掃碼槍
優(yōu)點(diǎn):兼容性好,遵循藍(lán)牙協(xié)議,與鍵盤輸入法無關(guān)。更底層,直接返回原始二進(jìn)制數(shù)據(jù)流,方便判定編碼以及進(jìn)行字符編碼轉(zhuǎn)換。
缺點(diǎn):需要進(jìn)行原生開發(fā), 處理設(shè)備掃描,連接,數(shù)據(jù)讀寫等操作。
二、BLE協(xié)議白話
好在有g(shù)ithub,其中的BLESSED for Android - BLE made easy 項(xiàng)目,就是一個(gè)致力于簡化android上BLE開發(fā)工作的開源庫。但在擼代碼前還是要簡單理解下BLE協(xié)議的主要概念。
較為重要的兩個(gè)東西是Service(服務(wù)) 與Characteristic(特性,譯為功能可能更好理解),簡而言之,一個(gè)設(shè)備可以提供多個(gè)服務(wù),每個(gè)服務(wù)可以提供多個(gè)特性功能,每個(gè)服務(wù)及特性對(duì)應(yīng)一個(gè)UUID。
與設(shè)備的通信通過功能進(jìn)行,每個(gè)功能通過Properties(屬性)表明該特性支持讀,寫或者通知。
為了便于理解BLE協(xié)議,推薦下載一個(gè)叫做“BLE調(diào)試助手”的APP。下面是APP的截圖。
截圖演示了如何從一個(gè)支持BLE協(xié)議的設(shè)備中讀取電量,不需要提前配對(duì),打開APP掃描到對(duì)應(yīng)設(shè)備后,點(diǎn)擊Connect, 隨后列出的就是一堆上面說的Service(服務(wù)),能夠顯示服務(wù)名稱的如“Battery Service”,是根據(jù)UUID的約定取得的。
如電池服務(wù)為0x180F。點(diǎn)開服務(wù)后是Characteristic,其中的Battery Level(也是UUID約定 0x2A19)的Properties為 READ NOTIFY,表明該特性支持讀取和通知。
點(diǎn)擊那個(gè)下箭頭,點(diǎn)擊讀取,顯示出返回?cái)?shù)據(jù)為0x5D(十進(jìn)制估計(jì)九十多:-0)。
電池服務(wù)是一個(gè)在協(xié)議中約定的標(biāo)準(zhǔn)服務(wù),但掃碼槍的似乎不是,我們還需要找到掃碼后,是通過哪個(gè)Service的哪個(gè)Characteristic進(jìn)行通知的,通過這個(gè)工具APP也不難找,注意,要打開那個(gè)接受通知數(shù)據(jù)。
掃碼后會(huì)有數(shù)據(jù)顯示,找到之后就可以開始編碼了。
三、第三方庫 BLESSED for Android的使用
https://github.com/weliem/blessed-android
下面進(jìn)入具體的擼代碼環(huán)節(jié)
安裝 gradle file加入
allprojects { repositories { ... maven { url 'https://jitpack.io' } } } dependencies { implementation 'com.github.weliem:blessed-android:2.0.6'
掃描設(shè)備
BluetoothCentralManager central = new BluetoothCentralManager(AppContext.baseAppContext, bluetoothCentralManagerCallback, new Handler(Looper.getMainLooper())); central.scanForPeripherals();
bluetoothCentralManagerCallback是掃描回調(diào)方法,重要的有下面三個(gè)
//發(fā)現(xiàn)了一個(gè)設(shè)備 @Override public void onDiscoveredPeripheral(BluetoothPeripheral peripheral, ScanResult scanResult) //連接設(shè)備 @Override public void onConnectedPeripheral(BluetoothPeripheral peripheral) //設(shè)備斷開 @Override public void onDisconnectedPeripheral(BluetoothPeripheral peripheral, HciStatus status)
發(fā)現(xiàn)設(shè)備后onDiscoveredPeripheral,連接設(shè)備,停止掃描 。bluetoothPeripheralCallback 為設(shè)備回調(diào),用于接受通知
central.autoConnectPeripheral(peripheral, bluetoothPeripheralCallback); central.stopScan();
onConnectedPeripheral連接后查詢提供的服務(wù)及特性
Log.i("BLE","onConnectedPeripheral"); List<BluetoothGattService> serviceList = peripheral.getServices(); for (int i = 0; i < serviceList.size(); i++) { Log.i("BLE", "Service: " + serviceList.get(i).getUuid()); if(serviceList.get(i).getUuid().toString().equals("6e400001-b5a3-f393-e0a9-e50e24dcca9e")){ List<BluetoothGattCharacteristic> list= serviceList.get(i).getCharacteristics(); for (int j = 0; j < list.size(); j++) { Log.i("BLE", "Characteristic: " + list.get(j).getUuid()); } } }
onConnectedPeripheral后,對(duì)特性開啟通知,接受掃碼結(jié)果,服務(wù)的和特性的UUID,需要對(duì)應(yīng)填寫,掃碼結(jié)果是以通知信息返回的。
BluetoothGattCharacteristic currentTimeCharacteristic = peripheral.getCharacteristic(SERVICE_UUID, CURRENT_TIME_CHARACTERISTIC_UUID); if (currentTimeCharacteristic != null) { //開啟通知 peripheral.setNotify(currentTimeCharacteristic, true); } //與設(shè)備通信需要?jiǎng)?chuàng)建綁定 boolean bret= peripheral.createBond();
斷開重連可以在onDisconnectedPeripheral中處理
接收掃碼結(jié)果 在設(shè)備回調(diào)類 bluetoothPeripheralCallback中的下列方法處理。其中value為掃到的二維碼值
@Override public void onCharacteristicUpdate(@NonNull BluetoothPeripheral peripheral, @NonNull byte[] value, @NonNull BluetoothGattCharacteristic characteristic, @NonNull GattStatus status)
另:
- 中文編碼通常為GBK或者UTF8,需要猜測判斷,最后附了個(gè)工具函數(shù)
- 因?yàn)锽LE默認(rèn)數(shù)據(jù)包較短,對(duì)大量數(shù)據(jù),會(huì)拆分多次發(fā)送,onCharacteristicUpdate會(huì)被調(diào)用多次,需要將value拼接后,進(jìn)行字符編碼判斷處理。
public static Boolean isUtf8(byte[] buffer) { boolean isUtf8 = true; int end = buffer.length; for (int i = 0; i < end; i++) { byte temp = buffer[i]; if ((temp & 0x80) == 0) {// 0xxxxxxx continue; } else if ((temp & 0xC0) == 0xC0 && (temp & 0x20) == 0) {// 110xxxxx 10xxxxxx if (i + 1 < end && (buffer[i + 1] & 0x80) == 0x80 && (buffer[i + 1] & 0x40) == 0) { i = i + 1; continue; } } else if ((temp & 0xE0) == 0xE0 && (temp & 0x10) == 0) {// 1110xxxx 10xxxxxx 10xxxxxx if (i + 2 < end && (buffer[i + 1] & 0x80) == 0x80 && (buffer[i + 1] & 0x40) == 0 && (buffer[i + 2] & 0x80) == 0x80 && (buffer[i + 2] & 0x40) == 0) { i = i + 2; } else if ((temp & 0xF0) == 0xF0 && (temp & 0x08) == 0) {// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx if (i + 3 < end && (buffer[i + 1] & 0x80) == 0x80 && (buffer[i + 1] & 0x40) == 0 && (buffer[i + 2] & 0x80) == 0x80 && (buffer[i + 2] & 0x40) == 0 && (buffer[i + 3] & 0x80) == 0x80 && (buffer[i + 3] & 0x40) == 0) { i = i + 3; } isUtf8 = false; break; } return isUtf8; }
原文鏈接:https://www.cnblogs.com/uncleguo/p/16067271.html
相關(guān)推薦
- 2022-06-04 Linux下使用Jenkins自動(dòng)化構(gòu)建.NET?Core應(yīng)用_基礎(chǔ)應(yīng)用
- 2022-11-29 ASP.NET?MVC把數(shù)據(jù)庫中枚舉項(xiàng)的數(shù)字轉(zhuǎn)換成文字_基礎(chǔ)應(yīng)用
- 2022-05-16 C++實(shí)現(xiàn)圖書管理系統(tǒng)源碼_C 語言
- 2023-04-07 React?Mobx狀態(tài)管理工具的使用_React
- 2022-08-17 詳解.NET中負(fù)載均衡的使用_實(shí)用技巧
- 2022-12-25 深入了解Go語言中g(shù)oioc框架的使用_Golang
- 2022-07-12 解決錯(cuò)誤:Cannot resolve symbol ‘JdbcTemplate‘
- 2022-05-18 C語言自定義類型超詳細(xì)梳理之結(jié)構(gòu)體?枚舉?聯(lián)合體_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支