Java Android AdvertiseData Builder-在执行回调时添加多个服务

Java Android AdvertiseData Builder-在执行回调时添加多个服务,java,android,callback,bluetooth-lowenergy,Java,Android,Callback,Bluetooth Lowenergy,我正在尝试为我的Android外围设备(化石手表)构建多个BLE服务,但发现在创建AdvertiseData时,不能一个接一个地添加多个服务,必须等待回调: 如果Android中的所有BLE外设都是这样(而不是特定于上面链接的实际用途),我如何利用AdvertiseData.Builder()和.addServiceUuid()在BluetoothGattServerCallback>onServiceAdded中添加我的第二个和第三个服务 换句话说,我如何等待回调执行并继续添加服务?如何重构

我正在尝试为我的Android外围设备(化石手表)构建多个BLE服务,但发现在创建AdvertiseData时,不能一个接一个地添加多个服务,必须等待回调:

如果Android中的所有BLE外设都是这样(而不是特定于上面链接的实际用途),我如何利用AdvertiseData.Builder()和.addServiceUuid()在BluetoothGattServerCallback>onServiceAdded中添加我的第二个和第三个服务

换句话说,我如何等待回调执行并继续添加服务?如何重构代码以适应这种情况

我尝试重写回调,并检查回调中通过的服务是否是第一个,然后添加第二个,等等。我现在收到一个错误(如下所示),因此我不太确定是否在其已包含的方法(包括在下面的代码中)之外处理AdvertiseData.Builder()部分:

无法解析方法“addServiceUuid(android.os.parceluid)”

我浏览了谷歌等网站,没有发现任何类似的问题

回拨:

    private BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() {
        @Override
        public void onServiceAdded(int status, BluetoothGattService service){
            if (service == commandsService){ // if the service added is the first one, add the second
                advData.addServiceUuid(new ParcelUuid(CONFIRMS_SERVICE_UUID));
            } else if (service == confirmsService){ // if the service is the second, add the third
                advData.addServiceUuid(new ParcelUuid(ALERTS_SERVICE_UUID));
            } else {
                // All three should be added, success!
            }
        }
广告已开始,如果包含以下注释,则会显示一个错误(如下所示):

private void startAdvertising() {
        BluetoothAdapter bluetoothAdapter = mBluetoothManager.getAdapter();
        mBluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
        if (mBluetoothLeAdvertiser == null) {
            Log.w(TAG, "Failed to create advertiser");
            return;
        }

        AdvertiseSettings settings = new AdvertiseSettings.Builder()
                .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
                .setConnectable(true)
                .setTimeout(1000)
                .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
                .build();

        advData = new AdvertiseData.Builder()
                .setIncludeDeviceName(false)
                .setIncludeTxPowerLevel(false)
                .addServiceUuid(new ParcelUuid(COMMANDS_SERVICE_UUID))
//                .addServiceUuid(new ParcelUuid(CONFIRMS_SERVICE_UUID))
//                .addServiceUuid(new ParcelUuid(ALERTS_SERVICE_UUID))
                .build();

        mBluetoothLeAdvertiser
                .startAdvertising(settings, advData, mAdvertiseCallback);
    }
如果这两行未注释,则会发生以下错误:

W/GattServer: LE Advertise Failed: 1
W/Binder: Caught a RuntimeException from the binder stub implementation.
    java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
        at java.util.ArrayList.get(ArrayList.java:437)
        at android.bluetooth.BluetoothGattServer$1.onServiceAdded(BluetoothGattServer.java:129)
        at android.bluetooth.IBluetoothGattServerCallback$Stub.onTransact(IBluetoothGattServerCallback.java:85)
        at android.os.Binder.execTransact(Binder.java:697)
我希望了解如何利用AdvertiseData.Builder并添加多个服务,使用回调一次添加一个。我不明白如何将回调和构建器一起使用,以及等待回调添加下一个服务的正确方法是什么


资源-我用这个项目作为开始的例子:

在我偶然发现这个问题之前,我一直面临着同样的问题。
T Linkin的评论让我想到了这个问题

事实证明,您不能同时添加所有的
BluetoothGattService
s。
通过按顺序添加它们,可以防止该问题

您可以将所有服务保留在
队列中

fun advertise() {
    val gattServices: List<BluetoothGattService> = createServices()
    this.addServiceQueue = LinkedList(gattServices)
        
    if(addServiceQueue.isEmpty()) {
        startAdvertisement()
    } else {
        val firstItem = addServiceQueue.poll()
        gattServer?.addService(firstItem)
    }
}

看一看这张照片。看起来你的广告包太大了。添加两个完整的128位服务UUID对于广告来说太多了。您必须使用更小的UUID并制作自己的定制广告包

看起来像是另一个用户@alextk做的,但没有说明如何:
override fun onServiceAdded(status: Int, service: BluetoothGattService?) {
    Log.d(TAG, "onServiceAdded: status $status")
    if (status == BluetoothGatt.GATT_SUCCESS) {
        Log.d(TAG, "onServiceAdded: success")

        val nextItem = addServiceQueue.poll()
        if(nextItem == null) {
            startAdvertisement()
        } else {
            gattServer?.addService(nextItem)
        }
    }
}