hbldh / bleak

A cross platform Bluetooth Low Energy Client for Python using asyncio
MIT License
1.83k stars 302 forks source link

Android permissions #1621

Open vascolp opened 4 months ago

vascolp commented 4 months ago

Hello again!

Description

I have an android app that works very well with bleak (good start :-)) The app does not require location data. It only uses BLE to scan and connect to LEGO Hubs. But bleak forces permissions ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, ACCESS_BACKGROUND_LOCATION.

Location permitions are a problem if you intend to do an android app that can be used by children. Android offers the ability to "strongly assert that my app does not use location" (check point 5 here). According to the same page, I am also convinced that in some situations ACCESS_BACKGROUND_LOCATION is also not needed. My case in particular.

Testing

I tried all this by making a copy of bleak and just commenting the call to the request_permissions() (and following await) and using these buildozer permissions (check the special case for BLUETOOTH_SCAN):

android.permissions = android.permission.INTERNET,android.permission.BLUETOOTH_ADMIN,(name=android.permission.BLUETOOTH_SCAN;usesPermissionFlags=neverForLocation),android.permission.BLUETOOTH_CONNECT

And everything works fine!!

Is there a chance that you could find a way to omit the call to request_permissions() if the user wants that? Some parameter valid only for android, or something like that?

I would appreciate it very much!

Thanks in advance! VascoLP

vascolp commented 4 months ago

Ok, here are some notes about android permission versions, that might be of interest to someone.

  1. Did not investigate versions prior to android 10, but probably it works like android 10.

  2. On android versions 10 and 11, (APIs 29 and 30) bleak will need ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION. In some cases (when there is a background service) you might also need ACCESS_BACKGROUND_LOCATION.

  3. On android 12 and above (API 31 and above), if your app does not use locations, you can use the ability to "strongly assert that my app does not use location" (check it here), so the *LOCATION permissions are not needed.

  4. If you want to give support for android 10 to 14 in a kivy application, and avoid location permissions where possible, you have to give some permissions based on API levels. With the following example, an APP will ask for location permissions in android up to 11, but not on android 12 or above. Here is a configuration example. Notice that this example will only work if the issue above is fixed. Otherwise, bleak 0.22.2 requests permissions hardcoded.

  5. buildozer.spec:

    # Permissions for APIs 29 to 34. Some of them only for APIs up to 30
    android.permissions = android.permission.INTERNET,android.permission.BLUETOOTH_ADMIN,android.permission.BLUETOOTH_CONNECT,android.permission.BLUETOOTH,(name=android.permission.BLUETOOTH_SCAN;usesPermissionFlags=neverForLocation),(name=android.permission.ACCESS_FINE_LOCATION;maxSdkVersion=30),(name=android.permission.ACCESS_COARSE_LOCATION;maxSdkVersion=30)
    android.api = 34
    android.minapi = 29
  6. Python code to request permissions. You can do it at startup or somewhere where needed with this sample code:

        if platform != 'android': 
            return # or whatever suits you....
        from android import api_version
        from android.permissions import request_permissions, Permission, check_permission
        permissions_list=[
            #Permission.INTERNET,
            Permission.BLUETOOTH_ADMIN,
            Permission.BLUETOOTH_SCAN,
            Permission.BLUETOOTH_CONNECT,
        ]
        if api_version < 31:
            permissions_list.append(Permission.ACCESS_COARSE_LOCATION)
            permissions_list.append(Permission.ACCESS_FINE_LOCATION)
            permissions_list.append(Permission.ACCESS_BACKGROUND_LOCATION) # If needed
    
        request_permissions(permissions_list)
dlech commented 4 months ago

I agree that Bleak should not be dealing with Android permissions. It should be up to the individual application to deal with that.

So I would be happy to take a pull request that removes permission stuff from the android backend code and moves it to the example app.

vascolp commented 2 months ago

Maybe you could just put the android permissions code inside an if, something like this:

if 'BLEAK_ANDROID_NO_PERMISSIONS' not in globals():
   # get permissions

Then I just would have to define that variable before importing bleak?

dlech commented 2 months ago

I would rather that it be an explicit function rather than something that happens magically at import.

vascolp commented 2 months ago

Well, it would not really be in the import, the if should be inside the BleakScannerP4Android.start() method, and the test would happen in run time. Well, I would rather have no direct permission handling at all in bleak... but I understand that that might mess with existing apps.

dlech commented 2 months ago

Given that things are kind of broken anyway on newer android versions, I think it would be OK to make a breaking change in this case.