Android-Ble蓝牙通讯开发–扫描,连接,发送和接收数据,分包解包(附源码)
前言
萬物互聯的物聯網時代的已經來臨,ble藍牙開發在其中扮演著舉重若輕的角色。最近剛好閑一點,抽時間梳理下這塊的知識點。
涉及ble藍牙通訊的客戶端(開啟、掃描、連接、發送和接收數據、分包解包)和服務端(初始化廣播數據、開始廣播、配置Services、Server回調操作)整個環節以及一些常見的問題即踩過的一些坑。
比如
1、在Android不同版本或不同手機的適配問題,掃描不到藍牙設備
2、如何避免ble藍牙連接出現133錯誤?
3、單次寫的數據大小有20字節限制,如何發送長數據
藍牙有傳統(經典)藍牙和低功耗藍牙BLE(Bluetooth Low Energy)之分,兩者的開發的API不一樣,本文主講Ble藍牙開發,傳統藍牙不展開,有需要的可以自行了解。
相對傳統藍牙,BLE低功耗藍牙,主要特點是快速搜索,快速連接,超低功耗保持連接和數據傳輸。
Demo效果展示
客戶端
服務端
API
Android4.3(API Level 18)開始引入BLE的核心功能并提供了相應的 API。應用程序通過這些 API 掃描藍牙設備、查詢 services、讀寫設備的 characteristics(屬性特征)等操作。
BLE藍牙協議是GATT協議, BLE相關類不多, 全都位于android.bluetooth包和android.bluetooth.le包的幾個類:
android.bluetooth.
.BluetoothGattService 包含多個Characteristic(屬性特征值), 含有唯一的UUID作為標識
.BluetoothGattCharacteristic 包含單個值和多個Descriptor, 含有唯一的UUID作為標識
.BluetoothGattDescriptor 對Characteristic進行描述, 含有唯一的UUID作為標識
.BluetoothGatt 客戶端相關
.BluetoothGattCallback 客戶端連接回調
.BluetoothGattServer 服務端相關
.BluetoothGattServerCallback 服務端連接回調
android.bluetooth.le.
.AdvertiseCallback 服務端的廣播回調
.AdvertiseData 服務端的廣播數據
.AdvertiseSettings 服務端的廣播設置
.BluetoothLeAdvertiser 服務端的廣播
.BluetoothLeScanner 客戶端掃描相關(Android5.0新增)
.ScanCallback 客戶端掃描回調
.ScanFilter 客戶端掃描過濾
.ScanRecord 客戶端掃描結果的廣播數據
.ScanResult 客戶端掃描結果
.ScanSettings 客戶端掃描設置
BLE設備分為兩種設備: 客戶端(也叫主機/中心設備/Central), 服務端(也叫從機/外圍設備/peripheral)
客戶端的核心類是 BluetoothGatt
服務端的核心類是 BluetoothGattServer 和 BluetoothLeAdvertiser
BLE數據的核心類是 BluetoothGattCharacteristic 和 BluetoothGattDescriptor
下面詳細講解下客戶端和服務端的開發步驟流程
一、BLE客戶端開發流程
1、申請權限
安卓手機涉及藍牙權限問題,藍牙開發需要在AndroidManifest.xml文件中添加權限聲明:
<!-- 藍牙權限 --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> 為適配安卓6.0以及以上版本需要添加一個模糊定位的權限<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 手機權限管理中允許此權限,否則會出現無法搜索到設備的情況;BLE權限增加了BEL支持檢查 (1).在manifest中添加權限 <!-- true 表示手機必須支持BLE,否則無法安裝!這里設為false, 運行后在Activity中檢查--> <uses-featureandroid:name="android.hardware.bluetooth_le"android:required="false" />(2).在Activity中設置藍牙 // 檢查是否支持BLE藍牙 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {Util.toast(this, "本機不支持低功耗藍牙!");finish();return; }2、打開藍牙
在搜索設備之前需要詢問打開手機藍牙:
//獲取系統藍牙適配器管理類 private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // 詢問打開藍牙 if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableBtIntent, 1); }// 申請打開藍牙請求的回調 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stubsuper.onActivityResult(requestCode, resultCode, data);if (requestCode == 1) {if (resultCode == RESULT_OK) {Toast.makeText(this, "藍牙已經開啟", Toast.LENGTH_SHORT).show();} else if (resultCode == RESULT_CANCELED) {Toast.makeText(this, "沒有藍牙權限", Toast.LENGTH_SHORT).show();finish();}} }3、搜索設備
注意: BLE設備地址是動態變化(每隔一段時間都會變化),而經典藍牙設備是出廠就固定不變了!
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // 下面使用Android5.0新增的掃描API,掃描返回的結果更友好,比如BLE廣播數據以前是byte[] scanRecord,而新API幫我們解析成ScanRecord類\ final BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner(); bluetoothLeScanner.startScan(mScanCallback); mHandler.postDelayed(new Runnable() {@Overridepublic void run() {bluetoothLeScanner.stopScan(mScanCallback); //停止掃描isScanning = false;} }, 3000);// 掃描結果Callback private final ScanCallback mScanCallback = new ScanCallback() {@Overridepublic void onScanResult(int callbackType, ScanResult result) {、BluetoothDevice dev = result.getDevice() 獲取BLE設備信息// result.getScanRecord() 獲取BLE廣播數據} };// 舊API是BluetoothAdapter.startLeScan(LeScanCallback callback)方式掃描BLE藍牙設備,如下: mBluetoothAdapter.startLeScan(callback); private LeScanCallback callback = new LeScanCallback() {@Overridepublic void onLeScan(BluetoothDevice device, int arg1, byte[] arg2) {//device為掃描到的BLE設備if(device.getName() == "目標設備名稱"){//獲取目標設備targetDevice = device;}} };4、連接設備
通過掃描BLE設備,根據設備名稱區分出目標設備targetDevice,下一步實現與目標設備的連接,在連接設備之前要停止搜索藍牙;停止搜索一般需要一定的時間來完成,最好調用停止搜索函數之后加以100ms的延時,保證系統能夠完全停止搜索藍牙設備。停止搜索之后啟動連接過程;
BLE藍牙的連接方法相對簡單只需調用connectGatt方法;
public BluetoothGatt connectGatt (Context context, boolean autoConnect, BluetoothGattCallback callback);參數說明
- 返回值 BluetoothGatt: BLE藍牙連接管理類,主要負責與設備進行通信;
- boolean autoConnect:建議置為false,能夠提升連接速度;
- BluetoothGattCallback callback 連接回調,重要參數,BLE通信的核心部分;
5、設備通信
與設備建立連接之后與設備通信,整個通信過程都是在BluetoothGattCallback的異步回調函數中完成;
BluetoothGattCallback中主要回調函數如下:
private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {//連接狀態改變的Callback}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {//服務發現成功的Callback}@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {//寫入Characteristic}@Overridepublic void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {//讀取Characteristic }@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {//通知Characteristic}@Overridepublic void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {//寫入Descriptor}@Overridepublic void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {//讀取Descriptor}};上述幾個回調函數是BLE開發中不可缺少的;
6、等待設備連接成功
當調用targetdDevice.connectGatt(context, false, gattCallback)后系統會主動發起與BLE藍牙設備的連接,若成功連接到設備將回調onConnectionStateChange方法,其處理過程如下:
@Override public void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {if (newState == BluetoothGatt.STATE_CONNECTED) {Log.e(TAG, "設備連接上 開始掃描服務");// 連接成功后,開始掃描服務mBluetoothGatt.discoverServices();}if (newState == BluetoothGatt.STATE_DISCONNECTED) {// 連接斷開/*連接斷開后的相應處理*/ } };判斷newState == BluetoothGatt.STATE_CONNECTED表明此時已經成功連接到設備;
7、開啟掃描服務
mBluetoothGatt.discoverServices();
掃描BLE設備服務是安卓系統中關于BLE藍牙開發的重要一步,一般在設備連接成功后調用,掃描到設備服務后回調onServicesDiscovered()函數,函數原型如下:
@Override public void onServicesDiscovered(BluetoothGatt gatt, int status) {private List<BluetoothGattService> servicesList;//獲取服務列表servicesList = mBluetoothGatt.getServices(); }- BLE藍牙協議下數據的通信方式采用BluetoothGattService、BluetoothGattCharacteristic和BluetoothGattDescriptor三個主要的類實現通信;
- BluetoothGattService 簡稱服務,是構成BLE設備協議棧的組成單位,一個藍牙設備協議棧一般由一個或者多個BluetoothGattService組成;
- BluetoothGattCharacteristic 簡稱特征,一個服務包含一個或者多個特征,特征作為數據的基本單元;
- 一個BluetoothGattCharacteristic特征包含一個數據值和附加的關于特征的描述;
- BluetoothGattDescriptor:用于描述特征的類,其同樣包含一個value值;
8、獲取負責通信的BluetoothGattCharacteristic
BLE藍牙開發主要有負責通信的BluetoothGattService完成的。當且稱為通信服務。通信服務通過硬件工程師提供的UUID獲取。獲取方式如下:
- BluetoothGattService service = mBluetoothGatt.getService(UUID.fromString(“藍牙模塊提供的負責通信UUID字符串”));
- 通信服務中包含負責讀寫的BluetoothGattCharacteristic,且分別稱為notifyCharacteristic和writeCharacteristic。其中notifyCharacteristic負責開啟監聽,也就是啟動收數據的通道,writeCharacteristic負責寫入數據;
具體操作方式如下:
BluetoothGattService service = mBluetoothGatt.getService(UUID.fromString("藍牙模塊提供的負責通信服務UUID字符串"));// 例如形式如:49535343-fe7d-4ae5-8fa9-9fafd205e455notifyCharacteristic = service.getCharacteristic(UUID.fromString("notify uuid"));writeCharacteristic = service.getCharacteristic(UUID.fromString("write uuid"));9、開啟監聽
開啟監聽,即建立與設備的通信的首發數據通道,BLE開發中只有當客戶端成功開啟監聽后才能與服務端收發數據。開啟監聽的方式如下:
mBluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true) BluetoothGattDescriptor descriptor = characteristic .getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); //若開啟監聽成功則會回調BluetoothGattCallback中的onDescriptorWrite()方法,處理方式如下: @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {if (status == BluetoothGatt.GATT_SUCCESS) {//開啟監聽成功,可以向設備寫入命令了Log.e(TAG, "開啟監聽成功");} };10、寫入數據
BLE單次寫的數據量大小是有限制的,通常是20字節,可以嘗試通過requestMTU增大,但不保證能成功。分包寫是一種解決方案,需要定義分包協議,假設每個包大小20字節,分兩種包,數據包和非數據包。對于數據包,頭兩個字節表示包的序號,剩下的都填充數據。對于非數據包,主要是發送一些控制信息。
監聽成功后通過向 writeCharacteristic寫入數據實現與服務端的通信。寫入方式如下:
其中:value一般為Hex格式指令,其內容由設備通信的藍牙通信協議規定;
11、接收數據
若寫入指令成功則回調BluetoothGattCallback中的onCharacteristicWrite()方法,說明將數據已經發送給下位機;
@Override public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {if (status == BluetoothGatt.GATT_SUCCESS) {Log.e(TAG, "發送成功");} }若發送的數據符合通信協議,則服務端會向客戶端回復相應的數據。發送的數據通過回調onCharacteristicChanged()方法獲取,其處理方式如下:
@Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {// value為設備發送的數據,根據數據協議進行解析byte[] value = characteristic.getValue(); }通過向服務端發送指令獲取服務端的回復數據,即可完成與設備的通信過程;
12、斷開連接
當與設備完成通信之后之后一定要斷開與設備的連接。調用以下方法斷開與設備的連接:
mBluetoothGatt.disconnect(); mBluetoothGatt.close();二、BLE服務端開發流程
1、設置廣播以及初始化廣播數據
//廣播設置(必須) AdvertiseSettings settings = new AdvertiseSettings.Builder().setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) //廣播模式: 低功耗,平衡,低延遲.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) //發射功率級別: 極低,低,中,高.setTimeout(0).setConnectable(true) //能否連接,廣播分為可連接廣播和不可連接廣播.build();//廣播數據(必須,廣播啟動就會發送) AdvertiseData advertiseData = new AdvertiseData.Builder().setIncludeDeviceName(true) //包含藍牙名稱.setIncludeTxPowerLevel(true) //包含發射功率級別.addManufacturerData(1, new byte[]{23, 33}) //設備廠商數據,自定義.build();//掃描響應數據(可選,當客戶端掃描時才發送) AdvertiseData scanResponse = new AdvertiseData.Builder().addManufacturerData(2, new byte[]{66, 66}) //設備廠商數據,自定義.addServiceUuid(new ParcelUuid(UUID_SERVICE)) //服務UUID // .addServiceData(new ParcelUuid(UUID_SERVICE), new byte[]{2}) //服務數據,自定義.build();2、開始廣播
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); //BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter(); BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();// ============啟動BLE藍牙廣播(廣告) =============== mBluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser(); mBluetoothLeAdvertiser.startAdvertising(settings, advertiseData, scanResponse, mAdvertiseCallback);// BLE廣播Callback private AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback() {@Overridepublic void onStartSuccess(AdvertiseSettings settingsInEffect) {logTv("BLE廣播開啟成功");}@Overridepublic void onStartFailure(int errorCode) {logTv("BLE廣播開啟失敗,錯誤碼:" + errorCode);} };3、配置Services以及Characteristic
// 注意:必須要開啟可連接的BLE廣播,其它設備才能發現并連接BLE服務端! // =============啟動BLE藍牙服務端====================================== BluetoothGattService service = new BluetoothGattService(UUID_SERVICE, BluetoothGattService.SERVICE_TYPE_PRIMARY);//添加可讀+通知characteristic BluetoothGattCharacteristic characteristicRead = new BluetoothGattCharacteristic(UUID_CHAR_READ_NOTIFY,BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ); characteristicRead.addDescriptor(new BluetoothGattDescriptor(UUID_DESC_NOTITY, BluetoothGattCharacteristic.PERMISSION_WRITE)); service.addCharacteristic(characteristicRead);//添加可寫characteristic BluetoothGattCharacteristic characteristicWrite = new BluetoothGattCharacteristic(UUID_CHAR_WRITE, BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_WRITE); service.addCharacteristic(characteristicWrite);if (bluetoothManager != null){mBluetoothGattServer = bluetoothManager.openGattServer(this, mBluetoothGattServerCallback); }mBluetoothGattServer.addService(service);4、Server回調以及操作
/** * 服務事件的回調 */ private BluetoothGattServerCallback mBluetoothGattServerCallback= new BluetoothGattServerCallback() {/*** 1.連接狀態發生變化時*/@Overridepublic void onConnectionStateChange(BluetoothDevice device, int status, int newState) {Log.e(TAG, String.format("1.onConnectionStateChange:device name = %s, address = %s", device.getName(), device.getAddress()));Log.e(TAG, String.format("1.onConnectionStateChange:status = %s, newState =%s ", status, newState));}@Overridepublic void onServiceAdded(int status, BluetoothGattService service) {Log.e(TAG, String.format("onServiceAdded:status = %s", status));}@Overridepublic void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {Log.e(TAG, String.format("onCharacteristicReadRequest:device name = %s, address = %s", device.getName(), device.getAddress()));Log.e(TAG, String.format("onCharacteristicReadRequest:requestId = %s, offset = %s", requestId, offset));mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());}/*** 3. onCharacteristicWriteRequest,接收具體的字節*/@Overridepublic void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] requestBytes) {Log.e(TAG, String.format("3.onCharacteristicWriteRequest:device name = %s, address = %s", device.getName(), device.getAddress()));Log.e(TAG, String.format("3.onCharacteristicWriteRequest:requestId = %s, preparedWrite=%s, responseNeeded=%s, offset=%s, value=%s", requestId, preparedWrite, responseNeeded, offset, requestBytes.toString()));mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, requestBytes);//4.處理響應內容onResponseToClient(requestBytes, device, requestId, characteristic);}/*** 2.描述被寫入時,在這里執行 bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS... 收,觸發 onCharacteristicWriteRequest*/@Overridepublic void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {Log.e(TAG, String.format("2.onDescriptorWriteRequest:device name = %s, address = %s", device.getName(), device.getAddress()));Log.e(TAG, String.format("2.onDescriptorWriteRequest:requestId = %s, preparedWrite = %s, responseNeeded = %s, offset = %s, value = %s,", requestId, preparedWrite, responseNeeded, offset, value.toString()));// now tell the connected device that this was all successfullmGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);}/*** 5.特征被讀取。當回復響應成功后,客戶端會讀取然后觸發本方法*/@Overridepublic void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {Log.e(TAG, String.format("onDescriptorReadRequest:device name = %s, address = %s", device.getName(), device.getAddress()));Log.e(TAG, String.format("onDescriptorReadRequest:requestId = %s", requestId));mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null);}@Overridepublic void onNotificationSent(BluetoothDevice device, int status) {super.onNotificationSent(device, status);Log.e(TAG, String.format("5.onNotificationSent:device name = %s, address = %s", device.getName(), device.getAddress()));Log.e(TAG, String.format("5.onNotificationSent:status = %s", status));}@Overridepublic void onMtuChanged(BluetoothDevice device, int mtu) {super.onMtuChanged(device, mtu);Log.e(TAG, String.format("onMtuChanged:mtu = %s", mtu));}@Overridepublic void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {super.onExecuteWrite(device, requestId, execute);Log.e(TAG, String.format("onExecuteWrite:requestId = %s", requestId));} };/** * 4.處理響應內容 * * @param reqeustBytes * @param device * @param requestId * @param characteristic */ private void onResponseToClient(byte[] reqeustBytes, BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic) {Log.e(TAG, String.format("4.onResponseToClient:device name = %s, address = %s", device.getName(), device.getAddress()));Log.e(TAG, String.format("4.onResponseToClient:requestId = %s", requestId));Log.e(TAG, "4.收到:");String str = new String(reqeustBytes) + " hello>";characteristicRead.setValue(str.getBytes());mGattServer.notifyCharacteristicChanged(device, characteristicRead, false);Log.i(TAG, "4.響應:" + str);MainActivity.handler.obtainMessage(MainActivity.DEVICE, new String(reqeustBytes)).sendToTarget(); }三、源碼下載
源碼上傳在CSDN上了,有需要的可以借鑒。
=====> Android藍牙Ble通訊Demo示例源碼–掃描,連接,發送和接收數據,分包解包
四、藍牙操作的注意事項
1、如何避免ble藍牙連接出現133錯誤?
- Android 連接外圍設備的數量有限,當不需要連接藍牙設備的時候,必須調用 BluetoothGatt#close 方法釋放資源;
- 藍牙 API 連接藍牙設備的超時時間大概在 20s 左右,具體時間看系統實現。有時候某些設備進行藍牙連接的時間會很長,大概十多秒。如果自己手動設置了連接超時時間在某些設備上可能會導致接下來幾次的連接嘗試都會在 BluetoothGattCallback#onConnectionStateChange 返回 state == 133;
- 能否避免android設備與ble設備連接/斷開時上報的133這類錯誤?
1、在連接失敗或者斷開連接之后,調用 close 并刷新緩存
2、盡量不要在startLeScan的時候嘗試連接,先stopLeScan后再去連
3、對同一設備斷開后再次連接(連接失敗重連),哪怕調用完close,需要等待一段時間(400毫秒試了1次,結果不 行;1000毫秒則再沒出現過問題)后再去connectGatt
4、可以在連接前都startLeScan一下,成功率要高一點
2、單次寫的數據大小有20字節限制,如何發送長數據?
BLE單次寫的數據量大小是有限制的,通常是20字節,可以嘗試通過requestMTU增大,但不保證能成功。分包寫是一種解決方案,需要定義分包協議,假設每個包大小20字節,分兩種包,數據包和非數據包。對于數據包,頭兩個字節表示包的序號,剩下的都填充數據。對于非數據包,主要是發送一些控制信息。
總體流程如下:
1、定義通訊協議,如下(這里只是個舉例,可以根據項目需求擴展)
| 01 | 01 | 01 | 0000 | – | 2D |
2、封裝通用發送數據接口(拆包)
該接口根據會發送數據內容按最大字節數拆分(一般20字節)放入隊列,拆分完后,依次從隊列里取出發送
3、封裝通用接收數據接口(組包)
該接口根據從接收的數據按協議里的定義解析數據長度判讀是否完整包,不是的話把每條消息累加起來
4、解析完整的數據包,進行業務邏輯處理
5、協議還可以引入加密解密,需要注意的選算法參數的時候,加密后的長度最好跟原數據長度一致,這樣不會影響拆包組包
3、在Android不同版本或不同的手機掃描不到藍牙設備
一般都是Android版本適配以及不同ROM機型(小米/紅米、華為/榮耀等)(EMUI、MIUI、ColorOS等)的權限問題
4、其它
- 藍牙的寫入操作, 讀取操作必須序列化進行. 寫入數據和讀取數據是不能同時進行的, 如果調用了寫入數據的方法, 馬上調用又調用寫入數據或者讀取數據的方法,第二次調用的方法會立即返回 false, 代表當前無法進行操作;
總結
藍牙開發中有很多問題,要靜下心分析問題,肯定可以解決的,一起加油;
總結
以上是生活随笔為你收集整理的Android-Ble蓝牙通讯开发–扫描,连接,发送和接收数据,分包解包(附源码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【python】计算圆周率到任意位支持任
- 下一篇: android sina oauth2.