安卓蓝牙开发基础知识
2019-09-18
蓝牙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>
<!--— 扫描蓝牙设备或者操作蓝牙设置 —-->
<uses-permission android:name="”android.permission.BLUETOOTH_ADMIN”"></uses-permission>
<!--—模糊定位权限,仅作用于6.0+,需要动态申请权限—-->
<uses-permission android:name="”android.permission.ACCESS_COARSE_LOCATION”"></uses-permission>
<!--—精准定位权限,仅作用于6.0+,需要动态申请权限—-->
<uses-permission android:name="”android.permission.ACCESS_FINE_LOCATION”"></uses-permission>
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设备:github.com/Jasonchenlijian/FastBle
蓝牙操作库:github.com/a-voyager/BluetoothHelper
苹果版本的是: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参数是字节序参数。
字节序说明:
这样的数据类型是c语言中用到的,其都是int类型,只是所占用的字节不同而已。
遇到这样类型的数值时,我们要将其转换为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时,需要做这样的处理。
标准蓝牙,低功耗蓝牙
Related recommendations