- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
这是广告商(注意 data
作为 AdvertiseData
类型传递)
private void advertise() {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothLeAdvertiser advertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
.setConnectable(false)
.build();
ParcelUuid pUuid = new ParcelUuid(UUID.fromString("cf2c82b6-6a06-403d-b7e6-13934e602664"));
AdvertiseData data = new AdvertiseData.Builder()
//.setIncludeDeviceName(true)
.addServiceUuid(pUuid)
.addServiceData(pUuid, "123456".getBytes(Charset.forName("UTF-8")))
.build();
AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
Log.i(tag, "Advertising onStartSuccess");
super.onStartSuccess(settingsInEffect);
}
@Override
public void onStartFailure(int errorCode) {
Log.e(tag, "Advertising onStartFailure: " + errorCode);
super.onStartFailure(errorCode);
}
};
advertiser.startAdvertising(settings, data, advertiseCallback);
}
启动成功
这是扫描仪
private void discover() {
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
.build();
mBluetoothLeScanner.startScan(null, settings, mScanCallback);
}
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
Log.i(tag, "Discovery onScanResult");
if (result == null) {
Log.i(tag, "no result");
return;
}
ScanRecord scanRecord = result.getScanRecord();
List<ParcelUuid> list = scanRecord != null ? scanRecord.getServiceUuids() : null;
if (list != null) {
Log.i(tag, scanRecord.toString());
for (ParcelUuid uuid : list) {
byte[] data = scanRecord.getServiceData(uuid);
}
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
Log.i(tag, "Discovery onBatchScanResults");
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.e(tag, "Discovery onScanFailed: " + errorCode);
}
};
在回调 onScarnResult
中,我记录了生成此输出的扫描记录 toString()
ScanRecord [mAdvertiseFlags=2,
mServiceUuids=[cf2c82b6-6a06-403d-b7e6-13934e602664],
mManufacturerSpecificData={},
mServiceData={000082b6-0000-1000-8000-00805f9b34fb=[49, 50, 51, 52, 53, 54]},
mTxPowerLevel=-2147483648, mDeviceName=null]
uuid匹配,不幸的是
的结果 byte[] data = scanRecord.getServiceData(uuid)
是 null
。我注意到 toString
输出具有广告数据字符“123456”的 ASCII 代码,即 49,50,51,52,53,54
mServiceData={000082b6-0000-1000-8000-00805f9b34fb=[49, 50, 51, 52, 53, 54]}
我想收到正确的广告数据,我做错了什么吗?
编辑: list 具有蓝牙、bt 管理和位置权限。第三个在 Android 6 中在运行时发起请求
编辑:通过打印整个 scanRecord 你得到这个输出
ScanRecord [mAdvertiseFlags=-1, mServiceUuids=[cf2c82b6-6a06-403d-b7e6-13934e602664], mManufacturerSpecificData={}, mServiceData={000082b6-0000-1000-8000-00805f9b34fb=[49, 50, 51, 52, 53, 54]}, mTxPowerLevel=-2147483648, mDeviceName=null]
基本上你不能使用广告商决定的uuid,它在mServiceUuids数组中,因为关联到mServiceData的键是另一个。所以我以这种方式更改了代码,以导航数据映射并获取值(请参阅两个 if block )
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
for (ScanResult result : results) {
ScanRecord scanRecord = result.getScanRecord();
List<ParcelUuid> uuids = scanRecord.getServiceUuids();
Map<ParcelUuid, byte[]> map = scanRecord.getServiceData();
if (uuids != null) {
for (ParcelUuid uuid : uuids) {
byte[] data = scanRecord.getServiceData(uuid);
Log.i(tag, uuid + " -> " + data + " contain " + map.containsKey(uuid));
}
}
if (map != null) {
Set<Map.Entry<ParcelUuid, byte[]>> set = map.entrySet();
Iterator<Map.Entry<ParcelUuid, byte[]>> iterator = set.iterator();
while (iterator.hasNext()) {
Log.i(tag, new String(iterator.next().getValue()));
}
}
}
}
其实行
map.containsKey(uuid)
返回false,因为广告商的uuid没有被数据映射使用。
我必须在 map 上导航才能找到该值(第二个 if block ),但我没有任何方法可以知道这是否是我感兴趣的值。无论哪种方式,我都无法获得该值 if在接收器应用程序上运行扫描仪代码时,系统放置了另一个我不知道的 key 。
我该如何处理接收器上的这个问题?我想使用数据字段,但获取它们的字符串键不是先验的,是由系统决定的。
最佳答案
我知道这是一个旧线程,但由于我遇到了同样的问题并找到了解决方案...
与广告商中的 .addServiceUuid()
和 .addServiceData()
一起使用的 UUID 是不同的对象。第一个标识服务,是一个 128 位的 UUID。第二个标识该服务中的 serviceData,预计为 16 位 UUID。
这就是扫描器接收的原因
0000**82b6**-0000-1000-8000-00805f9b34fb
请注意,16 位 0x82b6
与传递给 .addServiceData 的 UUID 相同:
cf2c**82b6**-6a06-403d-b7e6-13934e602664
通过左移 96 位并添加蓝牙常量 UUID,将 16 位 UUID 转换为 128 位。
解决方案就是使用这种形式的 UUID [0000xxxx-0000-1000-8000-00805f9b34fb
] 来识别广告商和扫描仪中的服务数据。您可以保留您原来的 128 位 UUID 来标识该服务。
关于java - Android:低功耗蓝牙扫描器接收到空数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38241691/
具体的软硬件实现点击 http://mcu-ai.com/ MCU-AI技术网页_MCU-AI人工智能 卷积神经网络(CNN)通过从原始数据中自动学习层次特征表示,在图像识别任务中取得了巨大成功。虽然
具体的软硬件实现点击 http://mcu-ai.com/ MCU-AI技术网页_MCU-AI人工智能 血压的测量和预测是心脏病患者和有心脏问题的人的一个重要条件,应该保持持续的控制。在这项研究中,基
具体的软硬件实现点击 http://mcu-ai.com/ MCU-AI技术网页_MCU-AI人工智能 心血管疾病是最严重的死亡原因之一,每年在全世界造成严重的生命损失。持续监测血压似乎是最可行的选择
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是 恩智浦MCX系列MCU的新品MCXN947 。 自 2015 年恩智浦和飞思卡尔合并成新恩智浦之后,关于它们各
我正在开发一个应用程序,该应用程序接受语音输入,并将该输入与 list 中的已知项目进行匹配。 list 中的每个项目都有一个别名列表,以便长标题的项目可以与较短的名称相匹配。 例如: class P
两个双模蓝牙设备连接时,必须使用EDR,不能并联使用LE。然后必须通过 EDR 链路传输 BT 低功耗 GATT 配置文件。这是我从规范中读到的内容。 但是 iOS EDR 堆栈(在没有 MFi 许可
我正在尝试为 S3 开发蓝牙 4.0 应用程序。问题是,手机的行为就像它甚至没有蓝牙 4.0。它不会发现 4.0 设备,并且无法通过 4.0 设备发现。我在手机设置和应用程序中都尝试过,使用 Broa
我正在寻找一种与 Adafruit bluefruit LE(nRF8001 芯片组)板进行交互的方法,在 Windows 桌面应用程序中使用 c#(据我所知,我无法使用 Windows.Device
我是一名优秀的程序员,十分优秀!