Does BluetoothLeAdvertiser work on a Nexus 5 with

2019-01-13 14:23发布

问题:

After flashing my Nexus 5 to the Android 5.0 preview release hammerhead-lpx13d, the OS reports that it no longer supports Bluetooth LE advertising. If you call:

((BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE))
    .getAdapter().getBluetoothLeAdvertiser()

always returns null. In addition, the new method:

((BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE))
    .getAdapter().isMultipleAdvertisementSupported()

always returns false

The first method used to return a valid object on the first Android L preview release for the Nexus 5 back in June. It no longer does, after flashing the latest update.

Does anybody see otherwise?

EDIT: This has been reproduced by at least one person, who opened an issue with Google here: https://code.google.com/p/android-developer-preview/issues/detail?id=1570

回答1:

Unfortunately, the official answer from Google is no, the Nexus 5 no longer supports advertising.

We introduced BLE peripheral mode in Android 5.0 Lollipop. Nexus 6 and Nexus 9 are the first two production Nexus devices that support BLE peripheral mode. Due to hardware chipset dependency, older Nexus devices (4/5/7) will not have access to the feature on Lollipop.

See Comment #52 on issue 1570 by danielho...@google.com: BLE advertise mode not working https://code.google.com/p/android-developer-preview/issues/detail?id=1570

That said, I have confirmed that advertising is supported by the Nexus 9 tablet. See here for details: http://developer.radiusnetworks.com/2014/11/18/beacon-transmission-with-android-5.html



回答2:

This is not full a solution, but a proposed work-around posted by mattprec on Google Code. It allows you to get a BluetoothLeAdvertiser instance by calling the private constructor rather than using the public API. Unfortunately, reports of testing on a Nexus 5 and a Nexus 7 2013 edition say that even after you get an instance you can't use the object to make advertisements come out. Also, be warned that even if you can get it to work, it might break on any minor code release of Android because it is using a non-public API.

For the record, here's the code snippet copied from that page:

private static BluetoothLeAdvertiser getAdvertiserHack(BluetoothAdapter adapter) {
  try {
    Class<? extends BluetoothAdapter> adapterClass = adapter.getClass();
    Field advertiserField = adapterClass.getDeclaredField("sBluetoothLeAdvertiser");
    advertiserField.setAccessible(true);
    Object advertiser = advertiserField.get(adapter);
    if (advertiser == null) {
      Field bluetoothManagerServiceField = adapterClass.getDeclaredField("mManagerService");
      bluetoothManagerServiceField.setAccessible(true);
      Object bluetoothManagerService = bluetoothManagerServiceField.get(adapter);

      Constructor<?> constructor = BluetoothLeAdvertiser.class.getDeclaredConstructor(
          bluetoothManagerServiceField.getType());
      constructor.setAccessible(true);
      advertiser = constructor.newInstance(bluetoothManagerService);

      advertiserField.set(adapter, advertiser);
    }
    return (BluetoothLeAdvertiser) advertiser;
  } catch (Exception e) {
    return null;
  }
}


回答3:

That said, I have confirmed that advertising is supported by the Nexus 9 tablet. See here for details: http://developer.radiusnetworks.com/2014/11/18/beacon-transmission-with-android-5.html

QuickBeacon app is working fine on Nexus 9. In app there is a Beacon Format option.@davidgyoung Could you give exact String for BeaconParser to make this library transmit in iBeacon format?



回答4:

UPDATE: Related question up to android-beacon-library/BLE Android SDK. Is there possibility - without calling startAdvertising method - to check if there is advertising service running in background?

UPDATE:

Recording to this : https://code.google.com/p/android-developer-preview/issues/detail?id=1570#c52

Now only Nexus 6 and Nexus 9 supports BLE Peripheal Mode in Android 5.0

UPDATE: I work on Nexus 5 Android 5.0 build number LPX13D

according to this https://stackoverflow.com/a/26611779/1906420

After implementig your workaround bluetoothAdvertiser is not null. Calling startAdvertising from bluetoothAdvertiser

bluetoothAdvertiser.startAdvertising(settingsBuilder.build(), dataBuilder.build(), advertiseCallback);

where

private AdvertiseCallback advertiseCallback = new AdvertiseCallback() {

        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffec) {

        }

        @Override
        public void onStartFailure(int result) {
            if (result == ADVERTISE_FAILED_DATA_TOO_LARGE) {
                Log.d(TAG, "Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes.");
            }
            else if(result == ADVERTISE_FAILED_TOO_MANY_ADVERTISERS){
                Log.d(TAG, "Failed to start advertising because no advertising instance is available.");
            }
            else if(result == ADVERTISE_FAILED_ALREADY_STARTED){
                 Log.d(TAG, "Failed to start advertising as the advertising is already started.");
            }
            else if(result == ADVERTISE_FAILED_INTERNAL_ERROR){
                Log.d(TAG, "Operation failed due to an internal error.");
            }
            else if(result == ADVERTISE_FAILED_FEATURE_UNSUPPORTED){
                Log.d(TAG, "This feature is not supported on this platform.");
            }
            else {
                Log.d(TAG, "There was unknown error.");
            }

        }

    };

always give callback onStartFailure with error code 5 ( ADVERTISE_FAILED_FEATURE_UNSUPPORTED )