
回复
BLE 是蓝牙低功耗的简称(Bluetooth Low Energy),生活中的很多场景都用到了BLE,如计步器、心率监视器、灯光控制、智能锁等。
BLE 设备间通信时会分为不同的角色:
说明
使用BLE实现设备间通信,需要蓝牙版本在4.0或以上,而且,您需要确保蓝牙已启用。
本教程将结合以下内容讲解如何使用BLE实现设备间通信:
在"entry\src\main\config.json"文件中的"reqPermissions"字段中声明以下3个权限:
"module": {
......
"reqPermissions": [
{
"name": "ohos.permission.USE_BLUETOOTH"
},
{
"name": "ohos.permission.DISCOVER_BLUETOOTH"
},
{
"name": "ohos.permission.LOCATION",
"reason": "$string:permreason_location",
"usedScene": {
"ability": [
".BleCentralAbility"
],
"when": "inuse"
}
}
]
}
此外,ohos.permission.LOCATION属于敏感权限,需要在代码中显式声明。代码示例如下:
public class MainAbility extends Ability {
@Override
public void onStart(Intent intent) {
String[] permissions = {"ohos.permission.LOCATION"};
requestPermissionsFromUser(permissions, 0);
super.onStart(intent);
}
}
// 实现BLE广播回调
private class MyBleAdvertiseCallback extends BleAdvertiseCallback {
@Override
public void startResultEvent(int result) {
if (result == BleAdvertiseCallback.RESULT_SUCC) {
// 开始BLE广播成功
}
}
}
// 创建广播数据
private BleAdvertiseData advertiseData = new BleAdvertiseData.Builder()
.addServiceData(SequenceUuid.uuidFromString(SERVICE_UUID), "12".getBytes())
.addServiceUuid(SequenceUuid.uuidFromString(SERVICE_UUID))
.build();
// 设置广播参数
private BleAdvertiseSettings advertiseSettings = new BleAdvertiseSettings.Builder()
.setConnectable(true)
.setInterval(BleAdvertiseSettings.INTERVAL_SLOT_MIN)
.setTxPower(BleAdvertiseSettings.TX_POWER_MAX)
.build();
// 获取BLE广播回调
private MyBleAdvertiseCallback advertiseCallback = new MyBleAdvertiseCallback();
// 获取BLE广播对象
private BleAdvertiser advertiser = new BleAdvertiser(this, advertiseCallback);
// 开始BLE广播
advertiser.startAdvertising(advertiseSettings, advertiseData, null);
// 实现中心设备管理回调
private class MyBleCentralManagerCallback implements BleCentralManagerCallback {
// 扫描结果的回调
@Override
public void scanResultEvent(BleScanResult bleScanResult) {
// 根据扫描结果获取外围设备实例
}
// 扫描失败回调
@Override
public void scanFailedEvent(int i) {
// 扫描失败
}
// 组扫描成功回调
@Override
public void groupScanResultsEvent(List list) {
// 使用组扫描时在此对扫描结果进行处理
}
}
// 获取中心设备管理回调
private MyBleCentralManagerCallback centralManagerCallback = new MyBleCentralManagerCallback();
// 获取中心设备管理对象
private BleCentralManager centralManager = new BleCentralManager(this, centralManagerCallback);
// 创建扫描过滤器
private List filters = new ArrayList<>();
// 开始扫描带有过滤器的指定BLE设备
centralManager.startScan(filters);
// 实现外围设备管理回调
private class MyBlePeripheralManagerCallback extends BlePeripheralManagerCallback {
// 连接状态变更的回调
@Override
public void connectionStateChangeEvent(
BlePeripheralDevice device, int interval, int latency, int timeout, int status) {
if (status == BlePeripheralDevice.OPERATION_SUCC) {
// 连接成功
}
}
// 远程GATT客户端已请求编写特征的回调
@Override
public void receiveCharacteristicWriteEvent(
BlePeripheralDevice device,
int transId,
GattCharacteristic characteristic,
boolean isPrep,
boolean needRsp,
int offset,
byte[] value) {
// 获取中心设备写入的数据
}
}
// 获取外围设备管理回调
private MyBlePeripheralManagerCallback peripheralManagerCallback = new MyBlePeripheralManagerCallback();
// 获取外围设备管理对象
private BlePeripheralManager blePeripheralManager = new BlePeripheralManager(this, peripheralManagerCallback, 1);
// 创建具有指定UUID的GattService实例
private GattService gattService = new GattService(UUID.fromString(SERVICE_UUID), true);
// 创建第1个GattCharacteristic实例,用于向中心设备发送数据
private GattCharacteristic notifyCharacteristic =
new GattCharacteristic(
UUID.fromString(NOTIFY_CHARACTER_UUID),
1 | 16,
GattCharacteristic.PROPERTY_READ
| GattCharacteristic.PROPERTY_WRITE
| GattCharacteristic.PROPERTY_WRITE_NO_RESPONSE);
// 创建第2个GattCharacteristic实例,用于接收中心设备发送的数据
private GattCharacteristic writeCharacteristic =
new GattCharacteristic(
UUID.fromString(WRITE_CHARACTER_UUID),
1 | 16,
GattCharacteristic.PROPERTY_READ
| GattCharacteristic.PROPERTY_WRITE
| GattCharacteristic.PROPERTY_WRITE_NO_RESPONSE);
public void startResultEvent(int result) {
if (result == BleAdvertiseCallback.RESULT_SUCC) {
// 为GattService添加一个或多个特征
gattService.addCharacteristic(notifyCharacteristic);
gattService.addCharacteristic(writeCharacteristic);
// 删除所有服务
blePeripheralManager.clearServices();
// 向外围设备管理对象添加GATT服务
blePeripheralManager.addService(gattService);
}
}
// 实现外围设备操作回调
private class MyBlePeripheralCallback extends BlePeripheralCallback {
// 在外围设备上发现服务的回调
@Override
public void servicesDiscoveredEvent(int status) {
super.servicesDiscoveredEvent(status);
// 发现服务操作成功后启用特征通知并获取GattCharacteristic实例
}
// 连接状态变更的回调
@Override
public void connectionStateChangeEvent(int connectionState) {
super.connectionStateChangeEvent(connectionState);
// 连接成功在外围设备上发现GATT服务
}
// 特征变更的回调
@Override
public void characteristicChangedEvent(GattCharacteristic characteristic) {
super.characteristicChangedEvent(characteristic);
// 接收外围设备发送的数据
}
}
// 获取外围设备操作回调
private MyBlePeripheralCallback blePeripheralCallback = new MyBlePeripheralCallback();
public void scanResultEvent(BleScanResult bleScanResult) {
if (peripheralDevice == null) {
// 获取广播数据中的服务uuids
List<UUID> uuids = bleScanResult.getServiceUuids();
for (UUID uuid : uuids) {
if (SERVICE_UUID.equals(uuid.toString())) {
// 根据扫描结果获取外围设备实例
peripheralDevice = bleScanResult.getPeripheralDevice();
}
}
}
}
// 与外围设备建立Gatt连接
peripheralDevice.connect(false, blePeripheralCallback);
public void connectionStateChangeEvent(int connectionState) {
super.connectionStateChangeEvent(connectionState);
if (connectionState == ProfileBase.STATE_CONNECTED) {
isConnected = true;
// 连接成功在外围设备上发现GATT服务
peripheralDevice.discoverServices();
}
}
public void servicesDiscoveredEvent(int status) {
super.servicesDiscoveredEvent(status);
if (status == BlePeripheralDevice.OPERATION_SUCC) {
for (GattService service : peripheralDevice.getServices()) {
checkGattCharacteristic(service);
}
}
}
private void checkGattCharacteristic(GattService service) {
for (GattCharacteristic tmpChara : service.getCharacteristics()) {
if (tmpChara.getUuid().equals(UUID.fromString(NOTIFY_CHARACTER_UUID))) {
// 启用特征通知
peripheralDevice.setNotifyCharacteristic(tmpChara, true);
}
if (tmpChara.getUuid().equals(UUID.fromString(WRITE_CHARACTER_UUID))) {
// 获取GattCharacteristic
writeCharacteristic = tmpChara;
}
}
}
public void characteristicChangedEvent(GattCharacteristic characteristic) {
super.characteristicChangedEvent(characteristic);
// 获取外围设备发送的数据:characteristic.getValue()
}
// 向外围设备发送数据
writeCharacteristic.setValue("我是中心设备".getBytes());
peripheralDevice.writeCharacteristic(writeCharacteristic);
public void receiveCharacteristicWriteEvent(
BlePeripheralDevice device,
int transId,
GattCharacteristic characteristic,
boolean isPrep,
boolean needRsp,
int offset,
byte[] value) {
// 获取中心设备写入的数据:value
}
// 向中心设备发送数据
notifyCharacteristic.setValue("我是外围设备".getBytes());
blePeripheralManager.notifyCharacteristicChanged(peripheralDevice, notifyCharacteristic, false);
说明
BLE设备间通信对数据大小有限制,一次性传输的数据最大不超过20字节,超过部分将无法传输。
外围设备(BlePeripheral)和中心设备(BleCentral)操作界面初始效果
外围设备开始BLE广播、中心设备开始BLE扫描
3. 连接设备
4. 外围设备发送数据、中心设备接收数据
5. 中心设备发送数据、外围设备接收数据
为了方便您的学习,我们提供了的BLE示例工程的完整代码,代码的工程结构如下:
首先在HUAWEI DevEco Studio创建一个Phone的Empty Feature Ability(Java)模板工程,然后新建名称为BleCentralAbility和BlePeripheralAbility的Empty Page Ability(Java)。
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:orientation="vertical">
<Button
ohos:id="$+id:ble_central"
ohos:height="50vp"
ohos:width="match_parent"
ohos:background_element="#33A1C9"
ohos:layout_alignment="center"
ohos:margin="20vp"
ohos:text="中心设备操作界面"
ohos:text_size="18fp"/>
<Button
ohos:id="$+id:ble_peripheral"
ohos:height="50vp"
ohos:width="match_parent"
ohos:background_element="#33A1C9"
ohos:layout_alignment="center"
ohos:margin="20vp"
ohos:text="外围设备操作界面"
ohos:text_size="18fp"/>
</DirectionalLayout>
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:background_element="#F0FFFF"
ohos:orientation="vertical">
<DirectionalLayout
ohos:height="60vp"
ohos:width="match_parent"
ohos:orientation="horizontal">
<Text
ohos:id="$+id:device_info"
ohos:height="match_parent"
ohos:width="0vp"
ohos:margin="8vp"
ohos:text="设备:暂无设备"
ohos:text_alignment="left"
ohos:text_size="18fp"
ohos:weight="3"/>
<Button
ohos:id="$+id:scan"
ohos:height="match_parent"
ohos:width="0vp"
ohos:background_element="#33A1C9"
ohos:margin="5vp"
ohos:text="开始扫描"
ohos:text_alignment="center"
ohos:text_size="18fp"
ohos:weight="1"/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="60vp"
ohos:width="match_parent"
ohos:orientation="horizontal">
<Text
ohos:id="$+id:status"
ohos:height="match_parent"
ohos:width="0vp"
ohos:margin="8vp"
ohos:text="状态:未连接"
ohos:text_alignment="left"
ohos:text_size="18fp"
ohos:weight="3"/>
<Button
ohos:id="$+id:connect"
ohos:height="match_parent"
ohos:width="0vp"
ohos:background_element="#33A1C9"
ohos:margin="5vp"
ohos:text="连接设备"
ohos:text_alignment="center"
ohos:text_size="18fp"
ohos:weight="1"/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="60vp"
ohos:width="match_parent"
ohos:orientation="horizontal">
<TextField
ohos:id="$+id:input"
ohos:height="match_parent"
ohos:width="0vp"
ohos:background_element="$graphic:textfield_element"
ohos:hint="请输入"
ohos:margin="8vp"
ohos:text_alignment="vertical_center|left"
ohos:text_size="18fp"
ohos:weight="3"/>
<Button
ohos:id="$+id:send"
ohos:height="match_parent"
ohos:width="0vp"
ohos:background_element="#33A1C9"
ohos:margin="5vp"
ohos:text="发送数据"
ohos:text_alignment="center"
ohos:text_size="18fp"
ohos:weight="1"/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="400vp"
ohos:width="match_parent"
ohos:background_element="#FFFFCD"
ohos:margin="10vp"
ohos:orientation="vertical">
<Text
ohos:height="40vp"
ohos:width="match_parent"
ohos:text="外围设备:"
ohos:text_size="18fp"/>
<Text
ohos:id="$+id:data"
ohos:height="320vp"
ohos:width="match_parent"
ohos:text_alignment="top|left"
ohos:text_size="18fp"/>
</DirectionalLayout>
</DirectionalLayout>
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:background_element="#F0FFFF"
ohos:orientation="vertical">
<DirectionalLayout
ohos:height="50vp"
ohos:width="match_parent"
ohos:orientation="horizontal">
<Text
ohos:id="$+id:status"
ohos:height="match_parent"
ohos:width="0vp"
ohos:margin="8vp"
ohos:text="状态:未开始广播"
ohos:text_alignment="left"
ohos:text_size="18fp"
ohos:weight="3"/>
<Button
ohos:id="$+id:advertise"
ohos:height="match_parent"
ohos:width="0vp"
ohos:background_element="#33A1C9"
ohos:margin="5vp"
ohos:text="开始广播"
ohos:text_alignment="center"
ohos:text_size="18fp"
ohos:weight="1"/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="50vp"
ohos:width="match_parent"
ohos:orientation="horizontal">
<TextField
ohos:id="$+id:input"
ohos:height="match_parent"
ohos:width="0vp"
ohos:background_element="$graphic:textfield_element"
ohos:hint="请输入"
ohos:margin="8vp"
ohos:text_alignment="vertical_center|left"
ohos:text_size="18fp"
ohos:weight="3"/>
<Button
ohos:id="$+id:send"
ohos:height="match_parent"
ohos:width="0vp"
ohos:background_element="#33A1C9"
ohos:margin="5vp"
ohos:text="发送数据"
ohos:text_alignment="center"
ohos:text_size="18fp"
ohos:weight="1"/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="400vp"
ohos:width="match_parent"
ohos:background_element="#FFFFCD"
ohos:margin="10vp"
ohos:orientation="vertical">
<Text
ohos:height="40vp"
ohos:width="match_parent"
ohos:text="中心设备:"
ohos:text_size="18fp"/>
<Text
ohos:id="$+id:data"
ohos:height="320vp"
ohos:width="match_parent"
ohos:text_alignment="top|left"
ohos:text_size="18fp"/>
</DirectionalLayout>
</DirectionalLayout>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
<corners
ohos:radius="50"/>
<solid
ohos:color="#D1FCFF"/>
</shape>
public class MainAbility extends Ability {
@Override
public void onStart(Intent intent) {
String[] permissions = {"ohos.permission.LOCATION"};
requestPermissionsFromUser(permissions, 0);
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
}
}
public class MainAbilitySlice extends AbilitySlice {
// BUNDLE_NAME、ABILITY_NAME开发者需要替换为自己项目对应的名称
private static final String BUNDLE_NAME = "com.huawei.blebluetooth";
private static final String CENTRAL_ABILITY_NAME = "com.huawei.blebluetooth.BleCentralAbility";
private static final String PERIPHERAL_ABILITY_NAME = "com.huawei.blebluetooth.BlePeripheralAbility";
// 获取 BluetoothHost 实例,管理本机蓝牙操作
private BluetoothHost bluetooth = BluetoothHost.getDefaultHost(this);
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
initComponent();
if (bluetooth.getBtState() != BluetoothHost.STATE_ON) {
bluetooth.enableBt();
}
}
private void initComponent() {
findComponentById(ResourceTable.Id_ble_central).setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName(BUNDLE_NAME)
.withAbilityName(CENTRAL_ABILITY_NAME)
.build();
intent.setOperation(operation);
startAbility(intent);
}
});
findComponentById(ResourceTable.Id_ble_peripheral).setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName(BUNDLE_NAME)
.withAbilityName(PERIPHERAL_ABILITY_NAME)
.build();
intent.setOperation(operation);
startAbility(intent);
}
});
}
}
public class BleCentralAbilitySlice extends AbilitySlice {
private static final String SERVICE_UUID = "00001887-0000-1000-8000-00805f9b34fb";
private static final String NOTIFY_CHARACTER_UUID = "00002a10-0000-1000-8000-00805f9b34fb";
private static final String WRITE_CHARACTER_UUID = "00002a11-0000-1000-8000-00805f9b34fb";
private BlePeripheralDevice peripheralDevice = null;
private GattCharacteristic writeCharacteristic;
private boolean isConnected = false;
private boolean isScanning = false;
private Text deviceText;
private Text statusText;
private TextField field;
private Text dataText;
private Button scanButton;
private Button connectButton;
private Button sendButton;
// 实现外围设备操作回调
private class MyBlePeripheralCallback extends BlePeripheralCallback {
// 在外围设备上发现服务的回调
@Override
public void servicesDiscoveredEvent(int status) {
super.servicesDiscoveredEvent(status);
if (status == BlePeripheralDevice.OPERATION_SUCC) {
for (GattService service : peripheralDevice.getServices()) {
checkGattCharacteristic(service);
}
}
}
private void checkGattCharacteristic(GattService service) {
for (GattCharacteristic tmpChara : service.getCharacteristics()) {
if (tmpChara.getUuid().equals(UUID.fromString(NOTIFY_CHARACTER_UUID))) {
// 启用特征通知
peripheralDevice.setNotifyCharacteristic(tmpChara, true);
}
if (tmpChara.getUuid().equals(UUID.fromString(WRITE_CHARACTER_UUID))) {
// 获取GattCharacteristic
writeCharacteristic = tmpChara;
}
}
}
// 连接状态变更的回调
@Override
public void connectionStateChangeEvent(int connectionState) {
super.connectionStateChangeEvent(connectionState);
if (connectionState == ProfileBase.STATE_CONNECTED && !isConnected) {
isConnected = true;
// 连接成功在外围设备上发现GATT服务
peripheralDevice.discoverServices();
updateComponent(statusText, "状态:已连接");
}
}
// 特征变更的回调
@Override
public void characteristicChangedEvent(GattCharacteristic characteristic) {
super.characteristicChangedEvent(characteristic);
// 接收外围设备发送的数据
updateComponent(dataText, new String(characteristic.getValue()));
}
}
// 获取外围设备操作回调
private MyBlePeripheralCallback blePeripheralCallback = new MyBlePeripheralCallback();
// 实现中心设备管理回调
private class MyBleCentralManagerCallback implements BleCentralManagerCallback {
// 扫描结果的回调
@Override
public void scanResultEvent(BleScanResult bleScanResult) {
// 根据扫描结果获取外围设备实例
if (peripheralDevice == null) {
// 获取广播数据中的服务uuids
List uuids = bleScanResult.getServiceUuids();
for (UUID uuid : uuids) {
if (SERVICE_UUID.equals(uuid.toString())) {
peripheralDevice = bleScanResult.getPeripheralDevice();
int length = peripheralDevice.toString().length();
String deviceId = peripheralDevice.toString().substring(length - 7, length);
updateComponent(deviceText, "设备:" + deviceId);
}
}
}
}
// 扫描失败回调
@Override
public void scanFailedEvent(int i) {
updateComponent(deviceText, "设备:扫描失败,请重新扫描!");
}
// 组扫描成功回调
@Override
public void groupScanResultsEvent(List list) {
// 使用组扫描时在此对扫描结果进行处理
}
}
// 获取中心设备管理回调
private MyBleCentralManagerCallback centralManagerCallback = new MyBleCentralManagerCallback();
// 获取中心设备管理对象
private BleCentralManager centralManager = new BleCentralManager(this, centralManagerCallback);
// 创建扫描过滤器
private List filters = new ArrayList<>();
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_ble_central);
initComponent();
initClickedListener();
}
// 初始化组件
private void initComponent() {
if (findComponentById(ResourceTable.Id_device_info) instanceof Text) {
deviceText = (Text) findComponentById(ResourceTable.Id_device_info);
}
if (findComponentById(ResourceTable.Id_status) instanceof Text) {
statusText = (Text) findComponentById(ResourceTable.Id_status);
}
if (findComponentById(ResourceTable.Id_data) instanceof Text) {
dataText = (Text) findComponentById(ResourceTable.Id_data);
}
if (findComponentById(ResourceTable.Id_input) instanceof TextField) {
field = (TextField) findComponentById(ResourceTable.Id_input);
}
if (findComponentById(ResourceTable.Id_scan) instanceof Button) {
scanButton = (Button) findComponentById(ResourceTable.Id_scan);
}
if (findComponentById(ResourceTable.Id_connect) instanceof Button) {
connectButton = (Button) findComponentById(ResourceTable.Id_connect);
}
if (findComponentById(ResourceTable.Id_send) instanceof Button) {
sendButton = (Button) findComponentById(ResourceTable.Id_send);
}
}
private void updateComponent(Text text, String content) {
getUITaskDispatcher().syncDispatch(new Runnable() {
@Override
public void run() {
text.setText(content);
}
});
}
// 初始化点击回调
private void initClickedListener() {
scanButton.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
if (!isScanning) {
isScanning = true;
scanButton.setText("停止扫描");
deviceText.setText("设备:正在扫描...");
// 开始扫描带有过滤器的指定BLE设备
centralManager.startScan(filters);
} else {
isScanning = false;
scanButton.setText("开始扫描");
deviceText.setText("设备:暂无设备");
// 停止扫描
centralManager.stopScan();
}
}
});
connectButton.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
if (peripheralDevice == null) {
statusText.setText("状态:请先扫描获取设备信息");
return;
}
if (!isConnected) {
connectButton.setText("断开连接");
statusText.setText("状态:连接中...");
// 连接到BLE外围设备
peripheralDevice.connect(false, blePeripheralCallback);
} else {
isConnected = false;
connectButton.setText("连接设备");
statusText.setText("状态:未连接");
deviceText.setText("设备:暂无设备");
writeCharacteristic.setValue("Disconnect".getBytes());
peripheralDevice.writeCharacteristic(writeCharacteristic);
// 断开连接
peripheralDevice.disconnect();
peripheralDevice = null;
}
}
});
sendButton.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
if (field.getText().isEmpty() || (peripheralDevice == null) || !isConnected) {
return;
}
// 向外围设备发送数据
writeCharacteristic.setValue(field.getText().getBytes());
peripheralDevice.writeCharacteristic(writeCharacteristic);
}
});
}
}
public class BlePeripheralAbilitySlice extends AbilitySlice {
private static final String SERVICE_UUID = "00001887-0000-1000-8000-00805f9b34fb";
private static final String NOTIFY_CHARACTER_UUID = "00002a10-0000-1000-8000-00805f9b34fb";
private static final String WRITE_CHARACTER_UUID = "00002a11-0000-1000-8000-00805f9b34fb";
private BlePeripheralDevice peripheralDevice = null;
private boolean isAdvertising = false;
private boolean isConnected = false;
private Text statusText;
private TextField field;
private Text dataText;
private Button advertiseButton;
private Button sendButton;
// 实现外围设备管理回调
private class MyBlePeripheralManagerCallback extends BlePeripheralManagerCallback {
// 连接状态变更的回调
@Override
public void connectionStateChangeEvent(
BlePeripheralDevice device, int interval, int latency, int timeout, int status) {
if (status == BlePeripheralDevice.OPERATION_SUCC && !isConnected) {
isConnected = true;
peripheralDevice = device;
updateComponent(statusText, "状态:已连接");
}
}
// 远程GATT客户端已请求编写特征的回调
@Override
public void receiveCharacteristicWriteEvent(
BlePeripheralDevice device,
int transId,
GattCharacteristic characteristic,
boolean isPrep,
boolean needRsp,
int offset,
byte[] value) {
if (Arrays.equals("Disconnect".getBytes(), value)) {
isConnected = false;
peripheralDevice = null;
updateComponent(statusText, "状态:已广播,等待连接");
return;
}
// 接收中心设备写入的数据
updateComponent(dataText, new String(value, Charset.defaultCharset()));
}
}
// 获取外围设备管理回调
private MyBlePeripheralManagerCallback peripheralManagerCallback = new MyBlePeripheralManagerCallback();
// 获取外围设备管理对象
private BlePeripheralManager blePeripheralManager = new BlePeripheralManager(this, peripheralManagerCallback, 1);
// 创建具有指定UUID的GattService实例
private GattService gattService = new GattService(UUID.fromString(SERVICE_UUID), true);
// 创建第1个GattCharacteristic实例,用于向中心设备发送数据
private GattCharacteristic notifyCharacteristic =
new GattCharacteristic(
UUID.fromString(NOTIFY_CHARACTER_UUID),
1 | 16,
GattCharacteristic.PROPERTY_READ
| GattCharacteristic.PROPERTY_WRITE
| GattCharacteristic.PROPERTY_WRITE_NO_RESPONSE);
// 创建第2个GattCharacteristic实例,用于接收中心设备发送的数据
private GattCharacteristic writeCharacteristic =
new GattCharacteristic(
UUID.fromString(WRITE_CHARACTER_UUID),
1 | 16,
GattCharacteristic.PROPERTY_READ
| GattCharacteristic.PROPERTY_WRITE
| GattCharacteristic.PROPERTY_WRITE_NO_RESPONSE);
// 实现BLE广播回调
private class MyBleAdvertiseCallback extends BleAdvertiseCallback {
// 开始广播回调
@Override
public void startResultEvent(int result) {
if (result == BleAdvertiseCallback.RESULT_SUCC) {
// 为GattService添加一个或多个特征
gattService.addCharacteristic(notifyCharacteristic);
gattService.addCharacteristic(writeCharacteristic);
// 删除所有服务
blePeripheralManager.clearServices();
// 向外围设备管理对象添加GATT服务
blePeripheralManager.addService(gattService);
}
}
}
// 创建广播数据
private BleAdvertiseData advertiseData = new BleAdvertiseData.Builder()
.addServiceData(SequenceUuid.uuidFromString(SERVICE_UUID), "12".getBytes())
.addServiceUuid(SequenceUuid.uuidFromString(SERVICE_UUID))
.build();
// 创建广播参数
private BleAdvertiseSettings advertiseSettings = new BleAdvertiseSettings.Builder()
.setConnectable(true)
.setInterval(BleAdvertiseSettings.INTERVAL_SLOT_MIN)
.setTxPower(BleAdvertiseSettings.TX_POWER_MAX)
.build();
// 获取BLE广播回调
private MyBleAdvertiseCallback advertiseCallback = new MyBleAdvertiseCallback();
// 获取BLE广播对象
private BleAdvertiser advertiser = new BleAdvertiser(this, advertiseCallback);
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_ble_peripheral);
initComponent();
initClickedListener();
}
// 初始化组件
private void initComponent() {
if (findComponentById(ResourceTable.Id_status) instanceof Text) {
statusText = (Text) findComponentById(ResourceTable.Id_status);
}
if (findComponentById(ResourceTable.Id_data) instanceof Text) {
dataText = (Text) findComponentById(ResourceTable.Id_data);
}
if (findComponentById(ResourceTable.Id_input) instanceof TextField) {
field = (TextField) findComponentById(ResourceTable.Id_input);
}
if (findComponentById(ResourceTable.Id_advertise) instanceof Button) {
advertiseButton = (Button) findComponentById(ResourceTable.Id_advertise);
}
if (findComponentById(ResourceTable.Id_send) instanceof Button) {
sendButton = (Button) findComponentById(ResourceTable.Id_send);
}
}
// 初始化点击回调
private void initClickedListener() {
advertiseButton.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
if (!isAdvertising) {
advertiseButton.setText("停止广播");
statusText.setText("状态:已广播,等待连接");
// 开始BLE广播
advertiser.startAdvertising(advertiseSettings, advertiseData, null);
isAdvertising = true;
} else {
advertiseButton.setText("开始广播");
statusText.setText("状态:已停止广播");
// 停止BLE广播
advertiser.stopAdvertising();
isAdvertising = false;
}
}
});
sendButton.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
if (field.getText().isEmpty() || (blePeripheralManager == null) || !isConnected) {
return;
}
// 向中心设备发送数据
notifyCharacteristic.setValue(field.getText().getBytes());
blePeripheralManager.notifyCharacteristicChanged(peripheralDevice, notifyCharacteristic, false);
}
});
}
private void updateComponent(Text text, String content) {
getUITaskDispatcher().syncDispatch(new Runnable() {
@Override
public void run() {
text.setText(content);
}
});
}
}
说明
以上代码示例仅供参考使用,产品化的代码需要考虑数据校验和国际化。
通过本教程的学习,您已学会如何使用BLE实现设备间通信。
微信扫码分享