Why isMultipleAdvertisementSupported() returns false, when getBluetoothLeAdvertiser returns an object?
Asked Answered
I

1

5

I am trying to play with BLE transmission on my device.

Here is the code I use and the output:

// check BLE support
Log.i(TAG, "BLE supported: " + getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)); // true

// check BLE transmission support
final BluetoothManager bluetoothManager =
        (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();

Log.i(TAG, "isMultipleAdvertisementSupported: " + mBluetoothAdapter.isMultipleAdvertisementSupported()); // false
Log.i(TAG, "isOffloadedFilteringSupported: " + mBluetoothAdapter.isOffloadedFilteringSupported()); // false
Log.i(TAG, "isOffloadedScanBatchingSupported: " + mBluetoothAdapter.isOffloadedScanBatchingSupported()); // false

BluetoothLeAdvertiser mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
Log.i(TAG, mBluetoothLeAdvertiser.toString()); //android.bluetooth.le.BluetoothLeAdvertiser@1c51f789

// check BLE transmission support
// android-beacon-library, https://github.com/AltBeacon/android-beacon-library
int result = BeaconTransmitter.checkTransmissionSupported(getApplicationContext());
Log.i(TAG, "ABL checkTransmissionSupported: " + result); // 0

I can not understand why mBluetoothLeAdvertiser is not null, since mBluetoothLeAdvertiser verifies that it is not false:

package android.bluetooth;
// ...

public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
    if (getState() != STATE_ON) {
        return null;
    }
    if (!isMultipleAdvertisementSupported()) {
        return null;
    }
    synchronized(mLock) {
        if (sBluetoothLeAdvertiser == null) {
            sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
        }
    }
    return sBluetoothLeAdvertiser;
}

// ...

public boolean isMultipleAdvertisementSupported() {
    if (getState() != STATE_ON) return false;
    try {
        return mService.isMultiAdvertisementSupported();
    } catch (RemoteException e) {
        Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
    }
    return false;
}
Intoxicating answered 19/8, 2015 at 10:27 Comment(0)
F
16

Welcome to the world of Android, which is both open source and closed source at the same time! Your analysis of the open source BluetoothLeAdvertiser code above is correct. If that code is running on your mobile device, you would not see the output that your test in the top code snippet shows. Conclusion: the code shown in the second snippet must not be what is on the device.

Android device OEMs are free to fork the source code and modify it to make it work with their hardware. In this case, I know that Motorola did the same thing in this code for their Moto X and Moto G devices. These devices return a BluetoothLeAdvertiser despite the fact that isMultipleAdvertisementSupported() returns false. A Motorola engineer explained to me that they changed this because they wanted to support Advertising despite using a BLE chip that could support only one Advertisement at a time. Indeed, I have verified that Motorola devices can advertise, but if you try to get two advertisements going simultaneously, it fails.

Fabianfabianism answered 19/8, 2015 at 13:1 Comment(9)
Thanks. I test it on Sony Z3 Compact. Since multiple advertisements are not supported, does it mean that I can not use my device in BLE peripheral mode? Or still I can? I need to emulate translation of one ~ iBeacon at the same time.Intoxicating
David, do you have any sample code you used on Motorola devices to advertise? Looks like your Android Beacon Library can advertise only when multiple advertisement is supported.Intoxicating
The BeaconTransmitter class in the Android Beacon Library is what I have used for Motorola. The only change I made to get it to work is to change the method that validates transmit capability to try and construct an advertiser instance rather than relying on isMultipleAdvertisementSupported(). If an instance can be constructed, transmit capability is assumed. github.com/AltBeacon/android-beacon-library/commit/…Fabianfabianism
Thank you. I use Android Studio and gradle, how could I modify the source of Android Beacon Library in this case? Or, should I define some other version? org.altbeacon:android-beacon-library:2.2-beta2 doesn't work.Intoxicating
That change is that the latest version of the library, so there is no reason to rebuild it. I suspect there is simply an issue with the Sony Z3 Compact such that it allows you to get an Advertiser instance but does not successfully start advertising. You may have no recourse but to open a bug report with Sony.Fabianfabianism
Why do I get Advertisement start failed, code: 2? Does Error 2 code mean NOT_SUPPORTED_BLE (altbeacon.github.io/android-beacon-library/javadoc/org/…)?Intoxicating
No, it means ADVERTISE_FAILED_TOO_MANY_ADVERTISERS, per android.googlesource.com/platform/frameworks/base/+/…Fabianfabianism
I've referenced this answer in a bug report because I think the documentation is incorrect: issuetracker.google.com/issues/115560698Lawyer
Could it actually be that another app is advertising?Fabianfabianism

© 2022 - 2024 — McMap. All rights reserved.