android蓝牙BLE(三) —— 广播
在蓝牙技术的应用中,有些场景下设备无需建立连接,而是通过广播方式发送数据,例如苹果的 iBeacon 技术。自从 Android 5.0 引入新的蓝牙 API 后,用户端的php 7源码设备得以扮演外设角色,对外广播信息。
广播数据包分为两种类型:广播包和响应包。广播包是每个外设必须发送的,而响应包是可选的。广播包的数据长度固定为字节,如果数据长度不足,则需用0字节填充至字节,emlog源码修复版超出的部分无效。广播数据单元是构成广播数据的基础,由长度值、类型和数据三部分组成。长度值位于数据单元的起始字节,指示后续数据的长度。
广播数据单元的结构为:长度值 + 类型 + 数据。长度值占用一个字节,并且位于数据单元的第一个字节。广播数据单元的数据部分,第一个字节代表数据类型(AD Type),决定了其后的彩虹云盘源码数据表示什么内容(即广播数据单元的第二个字节为AD type)。
广播数据的格式较为抽象,下面通过一个广播报文示例进行说明:
0x代表这是一个十六进制表示的字符串。每个十六进制数对代表一个字节。由于十六进制数的最大值为FF(即),而Java中byte类型的取值范围是-到,因此两个十六进制数可以准确表示一个字节。
广播数据单元的第一个字节表示该单元的数据长度,接下来的数据则根据不同的类型进行解释。例如,类型0x表示设备的全名。
在设置广播数据时,开发者可以通过 AdvertiseData 类来封装数据。区块链源码git例如,可以通过 AdvertiseData.Builder#setIncludeDeviceName() 设置是否在广播包中包含设备名称,或者通过 AdvertiseData.Builder#addServiceData() 添加特定UUID及其对应的数据。
广播的配置通过 AdvertiseSettings 类进行管理,例如设置广播模式、发射功率、持续时间和连接性。广播的名称可以通过 BluetoothAdapter#setName() 方法进行设置。
广播的实现通过 BluetoothLeAdvertiser#startAdvertising() 方法启动。在启动广播前,需要检查 BluetoothAdapter 是否支持广播,并确保 BluetoothLeAdvertiser 对象不为空。网游账号中心源码广播的停止则通过 BluetoothLeAdvertiser.stopAdvertising() 方法实现。
尽管广播可以告知外部设备存在某些服务,但手机端并不一定需要初始化对应的Gatt服务。因此,当外部设备尝试连接并查询服务时,可能无法找到对应的服务和数据。
在Gatt服务中,服务类型分为两个级别,创建 BluetoothGattService 时需要指定UUID和服务类型。Gatt服务中的最小通信单元是 Characteristic,它支持读写操作。Characteristic 具有不同的权限属性,用于定义其功能。
在实现广播功能后,可以通过蓝牙管理器获取 Gatt Server,并添加 Gatt Service。添加完 Gatt Service 后,外部设备连接手机时,将能够发现对应的 GATT Service 并读取数据。
定义 Gatt Server 回调有助于处理设备连接、特征值修改、读取特征值等事件。广播启动后,外部设备如nRF连接至手机外设时,可以看到特征值信息。
本文是蓝牙BLE系列文章的第三部分,涵盖了广播的相关内容,并提供了实现细节和示例,有助于开发者理解和实现蓝牙广播功能。
如何读取一次,我连接的多个设备的 rssi 值
我在开发一个应用程序,它需要连接到 Android 4.3 设备上的蓝牙设备。我能够通过 BluetoothGatt.readRemoteRssi() 方法从设备中读取 RSSI 值。我现在想要同时读取多个已连接设备的 RSSI 值,但是我每次只能读取到最后连接的设备的 RSSI 值。
例如,假设有两个 BLE 设备 A 和 B。我首先连接到设备 A 并读取其 RSSI 值。然后,我连接到设备 B,并且能够从设备 B 读取 RSSI 值。但是,我无法读取设备 A 的 RSSI 值,而是只能读取设备 B 的 RSSI 值。
在 Main.java 文件中,我列出了所有已连接设备的位置。当我在列表中点击一个设备时,会将设备的名称和地址传递到 DeviceControl.java 文件。
```java
final Intent qintent = new Intent(this, DeviceControl.class);
HashMap select = (HashMap) devicelist.getItemAtPosition(arg2);
String name = (String) select.get("name");
String address = (String) select.get("address");
qintent.putExtra(DeviceControl.EXTRAS_DEVICE_NAME, name);
qintent.putExtra(DeviceControl.EXTRAS_DEVICE_ADDRESS, address);
startActivity(qintent);
```
DeviceControl.java 文件将调用 BluetoothLeService.java 文件并连接到设备。
```java
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
// TODO Auto-generated method stub
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
mBluetoothLeService.connect(mDeviceAddress);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
// TODO Auto-generated method stub
mBluetoothLeService = null;
}
};
```
BluetoothLeService.java 文件负责连接到设备。
```java
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect");
return false;
}
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Try to create a new connection");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
```
连接到设备后,我可以使用 readRemoteRssi() 方法从设备中读取 RSSI 值。
```java
public void readRemoteRssi() {
mBluetoothGatt.readRemoteRssi();
}
```
然而,我注意到每次只能读取到最后连接的设备的 RSSI 值。当我查看日志时,我发现它总是发送 onCharacteristicWrite 和 readRemoteRssi() 调用到我最后连接的设备。
为了解决这个问题,我考虑了以下几种方法:
1. 创建多个 BluetoothGatt 对象来分别连接多个设备,并逐一调用 readRemoteRssi() 方法。
```java
BluetoothGatt mBluetoothGatt1 = device1.connectGatt(this, false, mGattCallback);
BluetoothGatt mBluetoothGatt2 = device2.connectGatt(this, false, mGattCallback);
```
这种方法的缺点是它比较麻烦,并且需要管理多个 BluetoothGatt 对象。
另一种解决方案是重新连接到第一个设备,然后再尝试读取或写入 CharacteristicWrite 值的设备。这样可以确保我能够读取所有已连接设备的 RSSI 值。
Win IoT物联网预览版更新内容和已知修复问题汇总
Win IoT物联网预览版更新内容和已知修复问题汇总
除了小娜驾到,还包括装置入口UI界面改进,为DragonBoard和BluetoothLE堆栈开发的UEFI文件系统卷的GUID Bug修复等内容。
更新内容:
为DragonBoard和BluetoothLE堆栈开发的UEFI文件系统卷的GUID Bug修复
解决IoT版Cortana听力报错
Windows装置入口(WDP/Web管理)UI界面改进
Cortana功能启用
FFU中的Dragonboard BSP更新为高通版
Windows装置入口(WDP/Web管理)为IoT实例扩展增加快速运行入口
修复硬件通知(hwnclx)和USB功能(usbfnclx)包的类扩展(Class Extensions),使得这些功能可以包含在默认IoT核心图像中
让IoT Shell可以等待PPKG提供的包来完成安装
让GPIO中断缓冲API
在Applyupdate.exe增加blockrebooton/blockrebootoff标志
修复电源状态API确定唤醒计时器被取消从连接准备状态退出
通用写过滤(UWF)增加进入Windows映像和Configuration Designer(ICD)的选项
BluetoothLE堆栈更新解决在NanoRDP连接引发GattDeviceService.GetCharacteristics问题
使用物联网版Win的用户需要注意,版同样拥有各种问题,相关用户需谨慎对待。
更多知识请关注windows教程 栏目
2024-11-19 08:39
2024-11-19 07:36
2024-11-19 07:07
2024-11-19 07:00
2024-11-19 06:54