簡介:
藍牙4.0分為標准藍牙和低功耗藍牙(BLE),標准藍牙就是手機上用的那種,低功耗藍牙由於其具有最大化的待機時間、快速連接和低峰值的發送和接收特性,被廣泛用於智能手表、智能手環等可穿戴設備上。在安卓4.3之前,安卓平台上的BLE開發相當難搞,好在谷歌在4.3之后發布了官方的API。在安卓5.0之后又引入了新的API,原來的API已經被廢棄。在新的系統里采用舊API開發的APP仍可使用,但采用新API開發的APP只能在Lollipop(Android 5.0 的前身蘿莉版(Lollipop) Android 開發者預覽)即安卓5.0及其以后的版本使用。
標准藍牙的的開發和BLE不同。標准藍牙連接里有兩個角色一個是客戶端一個是服務器,當客戶端搜索到藍牙服務器后並與之配對后,才能通過UUID(這個是唯一的,服務器端必須與客戶端一致)建立socket,然后使用流像文件讀寫和網絡通信那樣傳輸數據就行了。在BLE里,變成了中心設備(central)和外圍設備(peripheral),中心設備就是你的手機,外圍設備就是智能手環一類的東西。開發BLE的應用都得遵守Generic Attribute Profile (GATT),一個BLE藍牙設備包含多個service,每個service又包含多個characteristic。每個characteristic有一個value和多個descriptor,通過characteristic中心設備與外圍設備進行通信。descriptor顧名思義,包含了BLE設備的一些信息。不同service、characteristic和descriptor都有各自己唯一的UUID。想要跟BLE設備通信,首先通過UUID獲取目標服務,然后再通過UUID獲取characteristic,charateristic起着載體的作用,通過writeCharacteristic()和readCharacteristic(),可以寫入和讀出信息。每個characteristic都有一些自己的屬性,其中在property里,說明了該characteristic的屬性。
權限:
<!-- 使用藍牙的權限 -->
<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" />
<!--精准定位權限,僅作用於6.0+,需要動態申請權限-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
掃描方式
Android官方提供的藍牙掃描方式有三種,分別是:
BluetoothAdapter.startDiscovery()//可以掃描經典藍牙和ble藍牙兩種
BluetoothAdapter.startLeScan()//掃描低功耗藍牙,在api21已經棄用,不過還是可以使用
BluetoothLeScanner.startScan()//新的ble掃描方法
startDiscovery()方法在大多數手機上是可以同時發現經典藍牙和低功耗藍牙(BLE)的,但是startDiscovery()的回調無法返回BLE的廣播,所以無法通過廣播識別設備,而且startDiscovery()掃描BLE效率比startLeScan()低很多。因此需要根據具體的需求去做適配,才能更高效的搜尋藍牙。PS: startLeScan()和startScan()有重載方法可以指定規則,參數去搜索。
BluetoothLeScanner bluetoothLeScanner=BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
getBluetoothLeScanner()方法需要@SuppressLint("NewApi")注解,此時使用這個方法就需要開發者對版本進行區分,從而選擇不同的掃描方式。
藍牙操作:
可使用第三方庫有:
僅適用於BLE設備:https://github.com/Jasonchenlijian/FastBle
藍牙操作庫:https://github.com/a-voyager/BluetoothHelper
調試藍牙可用app:
蘋果版本的是:LightBlue
安卓版本的是:BLE調試工具,BLEDebugger這兩個都可在華為應用商城下載得到。
藍牙接收和寫入數據的類型:
FastBle第三方庫:
藍牙接收到的數據是十進制的字節數組,寫入時需要傳入的也是十進制的字節數組。
HexUtil.formatHexString(data,true);該方法是將十進制的字節數組,轉化成十六進制的字符串,其第一個參數是:十進制字節數組;第二個參數是:每個字節轉換后是否帶有空格。
方法一:
/**
* 將Java 中的 int 數值轉為字節數組
* @return
*/
public static byte[] int2Bytes(int x,ByteOrder byteOrder) {
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.order(byteOrder);
buffer.putInt(x);
return buffer.array();
}
方法二:
/**
* 將字節數組轉為 Java 中的 int 數值
* @return
*/
public static int bytes2Int(byte[] src,ByteOrder byteOrder){
ByteBuffer buffer = ByteBuffer.wrap(src);
buffer.order(byteOrder);
return buffer.getInt();
}
以上兩個方法;是十進制字節數組和int之間的轉換。byteOrder參數是字節序參數。
字節序說明:BIG-ENDIAN—-大字節序;LITTLE-ENDIAN—-小字節序;BIG-ENDIAN就是最低地址存放最高有效字節;LITTLE-ENDIAN是最低地址存放最低有效字節;java字節序:JAVA虛擬機中多字節類型數據的存放順序,JAVA字節序也是BIG-ENDIAN。
開發中遇到這樣的數據類型:int32_t、uint8_t、uint16_t。這樣的數據類型是c語言中用到的,其都是int類型,只是所占用的字節不同而已。
int32_t:4個字節
uint8_t:1個字節
uint16_t:2個字節
遇到這樣類型的數值時,我們要將其轉換為java中的int(4個字節)值,就需要用到上面的方法二。那么像uint8_t和uint16_t不足4個字節時,就要根據字節序來補零。
比如:一個字節,大端序方式,轉成java的int值
byte[] chars=new byte[4];
chars[0]= (byte) 0;
chars[1]= (byte) 0;
chars[2]= (byte) 0;
chars[3]=data[40];
configAnalogInputBean.setLower_alarm_hysteresis(CommonUtil.bytes2Int(chars, ByteOrder.BIG_ENDIAN)+"");
這里就涉及到java中int和byte之間的轉化:
int i=150;
byte bi=(byte)150;//正確
int ibi=bi>=0?bi:256+bi;//正確。說明:int強制轉換為byte型數據時,會產生一個-128~127的有符號字節,所以再把byte轉換到int時,需要做這樣的處理。
鳴謝:
https://www.cnblogs.com/witchiman/p/5320671.html
https://blog.csdn.net/panade/article/details/82620941
https://github.com/Jasonchenlijian/FastBle
https://github.com/a-voyager/BluetoothHelper
https://www.cnblogs.com/yulinfeng/p/5844151.html
https://blog.csdn.net/aloserbird/article/details/78089962