这是我参与8月更文挑战的第30天,活动详情查看:8月更文挑战
Android BLE蓝牙——从机开发
随着物联网的兴起,蓝牙设备也越来越多,传统蓝牙功耗大是很大的诟病,在传统蓝牙的基础上,将频段数量降低,射频时间减少等,慢慢延伸出了低功耗蓝牙,一节5号电池可以待机一年。尽管如此,在Android上想把BLE蓝牙做好仍然需要很大的工具,因为Android的碎片化厂商多样化,蓝牙芯片使用的不一致情况。这就相应的提高了开发者的开发成本和难度。
一、什么是从机
在蓝牙中,分为主机和从机,也可以叫做中心设备和外围设备。
实际场景中,我们把被连接的叫做外围设备,主动连接的叫做中心设备。所以物联网中的设备一般是外围设备,比如智能音箱、摄像头、智能插座、智能门锁等等。
主设备模式:工作在主设备模式,可以与一个从设备进行连接。在此模式下可以对周围设备进行搜索并选择需要连接的从设备进行连接。理论上,一个蓝牙主端设备,可同时与多个蓝牙从端设备进行通讯。
从设备模式:工作在从机模式下的蓝牙模块只能被主机搜索,不能主动搜索。从设备跟主机连接以后,也可以和主机设备进行发送和接收数据。
二、Android中开发从机
实际上一般情况下,从机都是物联网设备,由单片机开发,单片机可操作性更高,像在Android中广播模式可选参数只有低功耗、平衡、低延迟,而在单片机中却可以设置固定的数值。高手玩的都很底层。
2.1 申请权限
首先在AndroidManifest中增加权限,值得注意的是,考虑到 LE 信标通常与位置相关联,您还须声明 ACCESS_FINE_LOCATION 权限。没有此权限,扫描将无法返回任何结果。
如果您的应用适配 Android 9(API 级别 28)或更低版本,则可以声明 ACCESS_COARSE_LOCATION 权限而非 ACCESS_FINE_LOCATION 权限。
<!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- LE Beacons位置相关权限 -->
<uses-permission android:name="android.perm ission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
2.2 设置从机的蓝牙名称
BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
bluetoothAdapter.setName(bleName); // 设置蓝牙名称
2.3 设置广播模式和发射功率
广播模式分为:ADVERTISE_MODE_LOW_POWER(低耗电)、ADVERTISE_MODE_BALANCED(均衡)、ADVERTISE_MODE_LOW_LATENCY(低延迟) 发射功率: ADVERTISE_TX_POWER_LOW(低)、ADVERTISE_TX_POWER_MEDIUM(中)、ADVERTISE_TX_POWER_HIGH(高)
广播模式改为低延迟时,被中心设备扫描到的速度大大提高。
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) //广播模式: 低功耗,平衡,低延迟
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) //发射功率级别: 极低,低,中,高
.setConnectable(true) // 能否连接, 广播分为可连接广播和不可连接广播
.build();
2.4 设置广播数据
如果需要分析广播包数据,在此处设置,当主机扫描的时候发送。
AdvertiseData scanResponse = new AdvertiseData.Builder()
.addManufacturerData(2, new byte[]{66, 66}) //设备厂商数据,自定义
.addServiceUuid(new ParcelUuid(AppConfig.UUID_SERVICE)) //服务UUID
.build();
2.5 指定该蓝牙的属性
根据UUID增加可写可读属性。
//添加可读+通知characteristic(添加读属性,通知属性)
BluetoothGattCharacteristic characteristicRead = new BluetoothGattCharacteristic(AppConfig.UUID_CHARACTERISTIC,
BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ);
characteristicRead.addDescriptor(new BluetoothGattDescriptor(AppConfig.UUID_DESCRIPTOR, BluetoothGattCharacteristic.PERMISSION_WRITE));
service.addCharacteristic(characteristicRead);
//添加可写characteristic(添加写属性)
BluetoothGattCharacteristic characteristicWrite = new BluetoothGattCharacteristic(AppConfig.UUID_CHAR_WRITE,
BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_WRITE);
service.addCharacteristic(characteristicWrite);
2.6 绑定回调
mBluetoothGattServer = bluetoothManager.openGattServer(mContext,
bluetoothGattServerCallback);
2.6 启动广播
mBluetoothGattServer.addService(service);