google / uribeacon

The Web Uri Open Beacon for the Internet of Things
Apache License 2.0
409 stars 108 forks source link

LBluetoothLeScannerCompat fails to work when using ScanSettings.CALLBACK_TYPE_FIRST_MATCH | ScanSettings.CALLBACK_TYPE_MATCH_LOST #214

Open saiimons opened 9 years ago

saiimons commented 9 years ago

I am running the code on a Nexus 9, with Android 5.0.1. Scan fails to start with the following message :

java.lang.SecurityException: Need BLUETOOTH_PRIVILEGED permission: Neither user 10119 nor current process has android.permission.BLUETOOTH_PRIVILEGED. at android.os.Parcel.readException(Parcel.java:1540) at android.os.Parcel.readException(Parcel.java:1493) at android.bluetooth.IBluetoothGatt$Stub$Proxy.startScan(IBluetoothGatt.java:747) at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper.onClientRegistered(BluetoothLeScanner.java:299) at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:56) at android.os.Binder.execTransact(Binder.java:446)

I found out that the parameters are handled using reflection.

The only compatible setting is the CALLBACK_TYPE_ALL_MATCHES.

In my opinion we could fix the issue by :

I am working on a fix, and will probably post a reply about it.

g-ortuno commented 9 years ago

Do you have the correct permissions in the manifest?

On Sat, Mar 7, 2015, 2:17 PM Simon GUEROUT notifications@github.com wrote:

I am running the code on a Nexus 9, with Android 5.0.1. Scan fails to start with the following message :

java.lang.SecurityException: Need BLUETOOTH_PRIVILEGED permission: Neither user 10119 nor current process has android.permission.BLUETOOTH_PRIVILEGED. at android.os.Parcel.readException(Parcel.java:1540) at android.os.Parcel.readException(Parcel.java:1493) at android.bluetooth.IBluetoothGatt$Stub$Proxy.startScan(IBluetoothGatt.java:747) at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper.onClientRegistered(BluetoothLeScanner.java:299) at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:56) at android.os.Binder.execTransact(Binder.java:446)

I found out that the parameters are handled using reflection.

The only compatible setting is the CALLBACK_TYPE_ALL_MATCHES.

In my opinion we could fix the issue by :

  • Not using reflection
  • Changing the ScanCallback in order to handle these parameters.

I am working on a fix, and will probably post a reply about it.

— Reply to this email directly or view it on GitHub https://github.com/google/uribeacon/issues/214.

saiimons commented 9 years ago

Well, I have BLUETOOTH and BLUETOOTH_ADMIN, but as BLUETOOTH_PRIVILEGED is not supposed to be used, I did not include it at first.

public static final String BLUETOOTH_PRIVILEGED Allows applications to pair bluetooth devices without user interaction, and to allow or disallow phonebook access or message access. This is not available to third party applications.

Constant Value: "android.permission.BLUETOOTH_PRIVILEGED"

Even including it does not change anything.

Here is the code I am using

scanner = BluetoothLeScannerCompatProvider.getBluetoothLeScannerCompat(mContext);
// THIS FAILS
scanner.startScan(
  Arrays.asList(new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("7265656c-7941-6374-6976-652055554944")).build()),
  new ScanSettings.Builder() //
      .setCallbackType(ScanSettings.CALLBACK_TYPE_FIRST_MATCH | ScanSettings.CALLBACK_TYPE_MATCH_LOST) //
      .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER) //
      .setScanResultType(ScanSettings.SCAN_RESULT_TYPE_FULL) //
      .build(),
  scanCallback
);

// THIS WORKS
scanner.startScan(
  Arrays.asList(new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("7265656c-7941-6374-6976-652055554944")).build()),
  new ScanSettings.Builder() //
      .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) //
      .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER) //
      .setScanResultType(ScanSettings.SCAN_RESULT_TYPE_FULL) //
      .build(),
  scanCallback
);
g-ortuno commented 9 years ago

Take a look at this. It seems there is one extra permission needed for the library. https://github.com/google/uribeacon/blob/master/android-uribeacon/uribeacon-sample/src/main/AndroidManifest.xml Also if you look at the BLE API in lollipop it says only the all matches is supported.

On Sat, Mar 7, 2015, 2:51 PM Simon GUEROUT notifications@github.com wrote:

Well, I have BLUETOOTH and BLUETOOTH_ADMIN, but as BLUETOOTH_PRIVILEGED is not supposed to be used, I did not include it at first.

public static final String BLUETOOTH_PRIVILEGED Allows applications to pair bluetooth devices without user interaction, and to allow or disallow phonebook access or message access. This is not available to third party applications.

Constant Value: "android.permission.BLUETOOTH_PRIVILEGED"

Even including it does not change anything.

Here is the code I am using

scanner = BluetoothLeScannerCompatProvider.getBluetoothLeScannerCompat(mContext);// THIS FAILS scanner.startScan( Arrays.asList(new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("7265656c-7941-6374-6976-652055554944")).build()), new ScanSettings.Builder() // .setCallbackType(ScanSettings.CALLBACK_TYPE_FIRST_MATCH | ScanSettings.CALLBACK_TYPE_MATCH_LOST) // .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER) // .setScanResultType(ScanSettings.SCAN_RESULT_TYPE_FULL) // .build(), scanCallback ); // THIS WORKS scanner.startScan( Arrays.asList(new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("7265656c-7941-6374-6976-652055554944")).build()), new ScanSettings.Builder() // .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) // .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER) // .setScanResultType(ScanSettings.SCAN_RESULT_TYPE_FULL) // .build(), scanCallback );

— Reply to this email directly or view it on GitHub https://github.com/google/uribeacon/issues/214#issuecomment-77714976.

saiimons commented 9 years ago

The extra permission is not used in Lollipop, but it is in my Manifest. As for the ALL_MATCHES vs the FIRST_MATCH|MATCH_LOST, it is handled for the older versions in JbBluetoothLeScannerCompat. I'll try to code a similar function so that the feature is supported in Lollipop.

saiimons commented 9 years ago

I am working on a project based on parts of this library : https://github.com/reelyactive/ble-android-sdk I'll fix my project and port the changes in this one (I'll submit a pull request)

g-ortuno commented 9 years ago

The compat library uses the ble lollipop library if available (where only all matches is supported) . If you're on a nexus 9 then it's probably not using the jellybean library.

On Sat, Mar 7, 2015, 3:19 PM Simon GUEROUT notifications@github.com wrote:

I am working on a project based on parts of this library : https://github.com/reelyactive/ble-android-sdk I'll fix my project and port the changes in this one (I'll submit a pull request)

— Reply to this email directly or view it on GitHub https://github.com/google/uribeacon/issues/214#issuecomment-77715910.

saiimons commented 9 years ago

I tried using both versions of the API on hte Nexus 9 and using FIRST_MATCH|MATCH_LOST fails with the newest :

// GO LOLLIPOP
scanner = BluetoothLeScannerCompatProvider.getBluetoothLeScannerCompat(mContext);
// GO JELLYBEAN
scanner = BluetoothLeScannerCompatProvider.getBluetoothLeScannerCompat(mContext, false);
g-ortuno commented 9 years ago

So the first one doesn't work but the second one does?

On Sat, Mar 7, 2015, 3:28 PM Simon GUEROUT notifications@github.com wrote:

I tried using both versions of the API on hte Nexus 9 and using FIRST_MATCH|MATCH_LOST fails with the newest :

// GO LOLLIPOP scanner = BluetoothLeScannerCompatProvider.getBluetoothLeScannerCompat(mContext);// GO JELLYBEAN scanner = BluetoothLeScannerCompatProvider.getBluetoothLeScannerCompat(mContext, false);

— Reply to this email directly or view it on GitHub https://github.com/google/uribeacon/issues/214#issuecomment-77716205.

saiimons commented 9 years ago

So I tried 4 cases:

In the JbBluetoothLeScannerCompat the adresses seen during the scan are kept in memory, in order to track events when using _FIRST_MATCH|MATCHLOST, in LBluetoothLeScannerCompat there is a call to

if (method.toString().contains(".setCallbackType(")) {
    method.invoke(builder, settings.getCallbackType());
    callbackTypeSet = true;
}

which leads to the error. Looking at the Android source code shows that these are not public (yet). (https://android.googlesource.com/platform/frameworks/base/+/android-5.0.2_r1/core/java/android/bluetooth/le/ScanSettings.java)

In order to support _FIRST_MATCH|MATCHLOST, the same code as in JbBluetoothLeScannerCompat#callbackLeScanClients should be used for new matches (+ an alarm to check for lost matches ?).

Peter767 commented 4 years ago

I am running the code on a Nexus 9, with Android 5.0.1. Scan fails to start with the following message :

java.lang.SecurityException: Need BLUETOOTH_PRIVILEGED permission: Neither user 10119 nor current process has android.permission.BLUETOOTH_PRIVILEGED. at android.os.Parcel.readException(Parcel.java:1540) at android.os.Parcel.readException(Parcel.java:1493) at android.bluetooth.IBluetoothGatt$Stub$Proxy.startScan(IBluetoothGatt.java:747) at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper.onClientRegistered(BluetoothLeScanner.java:299) at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:56) at android.os.Binder.execTransact(Binder.java:446)

I found out that the parameters are handled using reflection.

The only compatible setting is the CALLBACK_TYPE_ALL_MATCHES.

In my opinion we could fix the issue by :

  • Not using reflection
  • Changing the ScanCallback in order to handle these parameters.

I am working on a fix, and will probably post a reply about it.

I am working on it. I will fix it within 10 days. I got the real issue I will fix it. for more information click scanner.