Java Android:蓝牙低能扫描仪接收空数据

Java Android:蓝牙低能扫描仪接收空数据,java,android,bluetooth,bluetooth-lowenergy,btle,Java,Android,Bluetooth,Bluetooth Lowenergy,Btle,这是广告客户(注意数据作为广告客户数据类型传递) 它成功地开始了 这是扫描仪 private void discover() { ScanSettings settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_BALANCED) .build(); mBluetoothLeScanner.startScan(null, settings,

这是广告客户(注意
数据
作为
广告客户数据
类型传递)

它成功地开始了

这是扫描仪

 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);
    }
};
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]}
我想收到正确的广告数据,我做错了什么吗

编辑:清单具有蓝牙、bt管理和位置权限。第三个在Android 6中运行时启动请求

编辑:通过打印整个扫描记录,您可以获得此输出

 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]
ScanRecord[mAdvertiseFlags=-1, mServiceUuids=[cf2c82b6-6a06-403d-b7e6-13934e602664], MManufacturersSpecificATA={}, mServiceData={000082b6-0000-1000-8000-00805f9b34fb=[49,50,51,52, 53,54]},mTxPowerLevel=-2147483648,mDeviceName=null]

基本上,您不能使用广告客户决定的uuid,它位于mServiceUuids数组中,因为与mServiceData关联的键是另一个键。因此,我以这种方式更改了代码,以导航数据映射并获取值(请参见两个if块)

返回false,因为数据映射未使用广告客户的uuid

我必须在地图上导航以找到值(第二个if块),但我没有任何方法知道这是否是我感兴趣的值。无论哪种方式,如果系统在receiver应用程序上运行扫描仪代码时放置了另一个我不知道的密钥,我都无法获取该值


如何在接收器上处理此问题?我想使用数据字段,但获取它们的字符串键事先未知,由系统决定。

我发现了错误。更改此行:

.addServiceData(pUuid, "123456".getBytes(Charset.forName("UTF-8")))
致:

就这样。我使用了与您相同的示例代码

在这里找到一个更好的例子:

尝试添加扫描过滤器并检索结果

 private void discover() 
{
    List<ScanFilter> filters = new ArrayList<ScanFilter>();

    ScanFilter filter = new ScanFilter.Builder()
            .setServiceUuid( new ParcelUuid(UUID.fromString( 
   getString(R.string.ble_uuid ) ) ) )
            .build();
    filters.add( filter );
private void discover()
{
列表过滤器=新的ArrayList();
ScanFilter filter=new ScanFilter.Builder()
.setServiceUuid(新的PARCELUID(UUID.fromString(
getString(R.string.ble_uuid)))
.build();
过滤器。添加(过滤器);

源代码链接:

我知道这是一个旧线程,但由于我有同样的问题并找到了解决方案

与广告客户中的
.addServiceUuid()
.addServiceData()
一起使用的UUID是不同的对象。 第一个标识服务,是一个128位的UUID。第二个标识服务中的serviceData,预计是一个16位的UUID

这就是扫描器接收数据的原因

0000**82b6**-0000-1000-8000-00805f9b34fb
请注意,16位
0x82b6
与传递给的UUID共用。addServiceData:

cf2c**82b6**-6a06-403d-b7e6-13934e602664
16位UUID通过左移96位并添加蓝牙常量UUID转换为128位

解决方案就是使用这种形式的UUID[
0000xxxx-0000-1000-8000-00805f9b34fb

]在广告客户和扫描器中标识服务数据。您可以保留原始128位UUID来标识服务。

@guiv在这里给出了正确答案

让我用更简洁的方式补充一下

addServiceData需要16位UUID,而AddServiceUUID可以接受16位或128位。 addServiceData不会引发异常,而是自动将128位UUID调整为16位,因此addServiceData的输入参数(在广告客户中)和getServiceData()的返回值(在扫描仪中)的键之间存在差异


解决方案-确保在广告客户中使用16位UUID这应该是公认的答案。这是一个很小的细节,我认为它很容易被忽略(并且没有验证或错误)。此外,我注意到将错误的128位UUID设置为服务数据UUID,会完全破坏广告数据。
.addServiceData(pUuid, "123456".getBytes()
 private void discover() 
{
    List<ScanFilter> filters = new ArrayList<ScanFilter>();

    ScanFilter filter = new ScanFilter.Builder()
            .setServiceUuid( new ParcelUuid(UUID.fromString( 
   getString(R.string.ble_uuid ) ) ) )
            .build();
    filters.add( filter );
0000**82b6**-0000-1000-8000-00805f9b34fb
cf2c**82b6**-6a06-403d-b7e6-13934e602664