Android 如何像在 iOS 中一样广播 BLE 本地名称?

Posted

技术标签:

【中文标题】Android 如何像在 iOS 中一样广播 BLE 本地名称?【英文标题】:How can Android broadcast BLE local name like in iOS? 【发布时间】:2015-05-04 18:32:15 【问题描述】:

我有一个带有服务 uuid 和本地名称的 android 应用程序广告 ble 广播数据。问题是这个“本地名称”(又名蓝牙设备名称)被限制为 8 个字符,每个字符都是 16 位 unicode 表示,因此每个字符 2 个字节。每当我尝试将设备名称更改为 9 个字符长时,由于错误 1(即

)而无法启动 ble 广播
  public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1;

我知道 GAP 配置文件广播数据包的长度为 27 个字节,其中 7 个用于标头,因此应该保留 20 个免费使用,而不仅仅是 16 个?

这是真正让我发痒的泡菜:

ios 广播 ble 广告标头时,我会获取设备的完整本地名称作为 ScanRecord 的一部分,而不仅限于 16 个字节。只是广播的一部分,我这里不建立 GATT 连接。

iOS 是如何做到这一点的?例如,在我的 Android 上,我能够从 iOS 广告广播中检索 14 个字符、28 个字节长的唯一 ID。 28 字节长于蓝牙 4.0 标准规定的 27 字节限制。 Android 为何能够接收超过 27 个字节的完整广播?为什么我的“本地名称”或设备名称最多只能有 8 个字符或 16 个字节,否则无法开始广播?

这是我的代码:

         final BluetoothLeAdvertiser advertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();

        //advertise settings
        final AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
        settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY);
        settingsBuilder.setConnectable(true);
        settingsBuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);

        //advertise data
        AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
        ParcelUuid uuid = new ParcelUuid(UUID.fromString("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"));
        dataBuilder.addServiceUuid(uuid);

        mBluetoothAdapter.setName("12345678"); //8 characters works, 9+ fails
        dataBuilder.setIncludeDeviceName(true);

     if (advertiser!=null) 
         advertiser.startAdvertising(settingsBuilder.build(), dataBuilder.build(), mAdvertiseCallback);
      

     mAdvertiseCallback = new AdvertiseCallback() 
         @Override
         public void onStartSuccess(AdvertiseSettings settingsInEffect) 
             super.onStartSuccess(settingsInEffect);
             Log.d(LOGN, "BLE STARTED ADVERTISING BROADCAST "+settingsInEffect);

         

         @Override
         public void onStartFailure(int errorCode) 
                 super.onStartFailure(errorCode);
                 Log.d(LOGN, "BLE ADVERTISING FAILED TO START: "+errorCode);
         
    ;

Android 有没有办法像 iOS 一样在广播中包含完整的本地名称?

谢谢!

【问题讨论】:

有什么新东西吗?你最终找到什么了吗? Sorry nothing yet :( 据我所知,iOS 符合标准,将其广播数据包按顺序分成 20 字节的集合。如果这是真的,那么 Android 可以把多个广播标头重新组合在一起意味着硬件堆栈也应该能够拆分自己的广播标头,如果它们的长度超过 20 个字节... 你不是叫这个:“dataBuilder.addServiceUuid”,它也会尝试将服务数据放入广告包中吗? @LanceNanek 哪里说的? developer.android.com/intl/ru/reference/android/bluetooth/le/… 【参考方案1】:

如果您查看StartAdvertising 的重载,您可以看到扫描响应有一个附加参数。您可以将本地名称放在扫描响应数据中。请记住从数据构建器中删除 setIncludeDeviceName

AdvertiseData.Builder scanResponseBuilder = new AdvertiseData.Builder();
mBluetoothAdapter.setName("123456789")
scanResponseBuilder.setIncludeDeviceName(true);

//...

if (advertiser!=null) 
     advertiser.startAdvertising(settingsBuilder.build(), dataBuilder.build(), scanResponseBuilder.SetIncludeDeviceName.build(), mAdvertiseCallback);
  

【讨论】:

以上是关于Android 如何像在 iOS 中一样广播 BLE 本地名称?的主要内容,如果未能解决你的问题,请参考以下文章

如何像在 iOS 中为 iMessage 一样为 Android 创建贴纸包?

Swift3 如何像在 android 中一样在 iOS 中实现底部工作表

Android:像在 iOS 中一样逐步获取 HTTP 响应

我如何在 Intellij Idea 中找到构建变体,就像在 Android Studio 中一样?

如何在 Android 中像在 Google 地图中一样获得持续的位置更新?

在 Android 中,如何像在谷歌地图中一样显示带有方角的警报对话框?