don/cordova-plugin-ble-central

ACCESS_FINE_LOCATION not requested in API level 34

Closed this issue · 7 comments

The app was running great until API 34.

Even using only in the manifest, in Android 14, the App only ask for course location access, and the BLE can't scan. Meanwhile, the same App in an Android 13 (API 33) is working perfectly and asking for both FINE and COARSE location.

It's a problem of the plugin?
Can someone give me a solution?

ACCESS_FINE_LOCATION is not needed for a general scan in API v34 if you're not using the scan results to derive a physical location.

See information here: https://developer.android.com/develop/connectivity/bluetooth/bt-permissions#declare

By default, this plugin assumes neverForLocation. If this doesn't match your usecase, you might want to switch to the slim variant of this plugin which leaves the exact requested android permissions in your direct control. See https://github.com/don/cordova-plugin-ble-central?tab=readme-ov-file#android-permission-conflicts for information about this.

The only caveat to pay attention to is that some BLE beacons are filtered out if you specify neverForLocation: https://developer.android.com/develop/connectivity/bluetooth/bt-permissions

If what you're scanning for fits this category, definitely the slim variant and your own custom permissions set is the right way to go there.

@joseitor just to double-check, are you using the latest version of the plugin by the way?

II tried leting only the premisions of the pluging, using plugin-ble-central@slim with my own permisions, with and without android:maxSdkVersion="34", using and avoidind ACCESS_FINE_LOCATION, neverForLocation... and always get the same problems. In Android 14 only ask for Coarse Location, and after accepting it, I cannot scan because is missing the location permision.
WhatsApp Image 2024-03-15 at 08 14 00_199596e6
WhatsApp Image 2024-03-15 at 08 14 00_1b131a93
And yes, I'm using the lasted version (all dependencies are updated)

I'm using Gradle 7.6.4, can be that a problem with target APi 34?

You'll need to manually request the ACCESS_FINE_LOCATION permissions yourself at runtime using the native android interfaces (or via another plugin such as https://github.com/dpa99c/cordova-diagnostic-plugin)

See the logic here:

List<String> missingPermissions = new ArrayList<String>();
if (COMPILE_SDK_VERSION >= 31 && Build.VERSION.SDK_INT >= 31) { // (API 31) Build.VERSION_CODE.S
if (!PermissionHelper.hasPermission(this, BLUETOOTH_SCAN)) {
missingPermissions.add(BLUETOOTH_SCAN);
}
if (!PermissionHelper.hasPermission(this, BLUETOOTH_CONNECT)) {
missingPermissions.add(BLUETOOTH_CONNECT);
}
} else if (COMPILE_SDK_VERSION >= 30 && Build.VERSION.SDK_INT >= 30) { // (API 30) Build.VERSION_CODES.R
// Android 11 specifically requires FINE location access to be granted first before
// the app is allowed to ask for ACCESS_BACKGROUND_LOCATION
// Source: https://developer.android.com/about/versions/11/privacy/location
if (!PermissionHelper.hasPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
missingPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
} else {
String accessBackgroundLocation = this.preferences.getString("accessBackgroundLocation", "false");
if (accessBackgroundLocation == "true" && !PermissionHelper.hasPermission(this, ACCESS_BACKGROUND_LOCATION)) {
LOG.w(TAG, "ACCESS_BACKGROUND_LOCATION is being requested");
missingPermissions.add(ACCESS_BACKGROUND_LOCATION);
}
}
} else if (COMPILE_SDK_VERSION >= 29 && Build.VERSION.SDK_INT >= 29) { // (API 29) Build.VERSION_CODES.Q
if (!PermissionHelper.hasPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
missingPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
String accessBackgroundLocation = this.preferences.getString("accessBackgroundLocation", "false");
if (accessBackgroundLocation == "true" && !PermissionHelper.hasPermission(this, ACCESS_BACKGROUND_LOCATION)) {
LOG.w(TAG, "ACCESS_BACKGROUND_LOCATION is being requested");
missingPermissions.add(ACCESS_BACKGROUND_LOCATION);
}
} else {
if(!PermissionHelper.hasPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
missingPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
}

Thanks! It worked! Apparently, in Android 14 ask for ACCESS_FINE_LOCATION just after start the app is not right and is ignored. I solved it asking again for permision on the runtime, when needed just before start scaning BLE devices.

This is the code I used in case might be useful for someone.

  this.permissions.checkPermission
    (this.permissions.PERMISSION.ACCESS_FINE_LOCATION).then((result) => {
      if (!result.hasPermission) {
        this.permissions.requestPermission
          (this.permissions.PERMISSION.ACCESS_FINE_LOCATION);
      }
    }, (err) => {
      this.permissions.requestPermission
        (this.permissions.PERMISSION.ACCESS_FINE_LOCATION);
    })

Thanks for sharing your solution @joseitor . Great job investigating this.

I'm still a bit puzzled how the plugin's default permission sets here weren't sufficient, but at least you have a solution!

According from what I experienced, it looks like Android 14 don't ask for high sensitive permisions as fine_location if they are asked just after starting the app. According Google, apps should ask for permissions just before when it is actually needed, so I guess not Android got more stricted about it, although I haven't read any about a change about it in API 34 (but I did't check it all and I'm really new on this).