diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9c360d48..3a8658e2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -18,6 +18,7 @@ Changed * Don't change ctypes' global state ``bleak.backends.winrt.util``. * Improved performance of BlueZ backend when there are many adapters. * Added support for Python 3.13. +* **BREAKING CHANGE** Android backend do not request permissions in background. ``request_permissions()`` has to be called explicitly. `0.22.2`_ (2024-06-01) ====================== diff --git a/bleak/backends/p4android/defs.py b/bleak/backends/p4android/defs.py index 832f92bc..c1d894d0 100644 --- a/bleak/backends/p4android/defs.py +++ b/bleak/backends/p4android/defs.py @@ -36,6 +36,7 @@ BLEAK_JNI_NAMESPACE + ".PythonBluetoothGattCallback" ) +VERSION = autoclass('android.os.Build$VERSION') class ScanFailed(enum.IntEnum): ALREADY_STARTED = ScanCallback.SCAN_FAILED_ALREADY_STARTED diff --git a/bleak/backends/p4android/scanner.py b/bleak/backends/p4android/scanner.py index fb3be74b..711c86d4 100644 --- a/bleak/backends/p4android/scanner.py +++ b/bleak/backends/p4android/scanner.py @@ -12,7 +12,6 @@ from asyncio import timeout as async_timeout from android.broadcast import BroadcastReceiver -from android.permissions import Permission, request_permissions from jnius import cast, java_method from ...exc import BleakError @@ -73,30 +72,6 @@ async def start(self) -> None: if self.__callback is None: self.__callback = _PythonScanCallback(self, loop) - permission_acknowledged = loop.create_future() - - def handle_permissions(permissions, grantResults): - if any(grantResults): - loop.call_soon_threadsafe( - permission_acknowledged.set_result, grantResults - ) - else: - loop.call_soon_threadsafe( - permission_acknowledged.set_exception( - BleakError("User denied access to " + str(permissions)) - ) - ) - - request_permissions( - [ - Permission.ACCESS_FINE_LOCATION, - Permission.ACCESS_COARSE_LOCATION, - "android.permission.ACCESS_BACKGROUND_LOCATION", - ], - handle_permissions, - ) - await permission_acknowledged - self.__adapter = defs.BluetoothAdapter.getDefaultAdapter() if self.__adapter is None: raise BleakError("Bluetooth is not supported on this hardware platform") diff --git a/bleak/backends/p4android/utils.py b/bleak/backends/p4android/utils.py index a4fafda3..0bcd09b3 100644 --- a/bleak/backends/p4android/utils.py +++ b/bleak/backends/p4android/utils.py @@ -3,10 +3,14 @@ import asyncio import logging import warnings +from typing import List, Optional +from android.permissions import Permission +from android.permissions import request_permissions as request_android_permissions from jnius import PythonJavaClass from ...exc import BleakError +from . import defs logger = logging.getLogger(__name__) @@ -92,3 +96,34 @@ def _result_state_unthreadsafe(self, failure_str, source, data): else: # send it on the event thread raise exception + +async def request_permissions(permissions: Optional[List[str]] = None) -> None: + loop = asyncio.get_running_loop() + permission_acknowledged = loop.create_future() + def handle_permissions(permissions, grantResults): + if any(grantResults): + loop.call_soon_threadsafe( + permission_acknowledged.set_result, grantResults + ) + else: + loop.call_soon_threadsafe( + permission_acknowledged.set_exception( + BleakError("User denied access to " + str(permissions)) + ) + ) + if permissions is None: + permissions = [ + Permission.ACCESS_FINE_LOCATION, + Permission.ACCESS_COARSE_LOCATION, + Permission.ACCESS_BACKGROUND_LOCATION, + ] + if defs.VERSION.SDK_INT >= 31: + permissions.extend([ + Permission.BLUETOOTH_SCAN, + Permission.BLUETOOTH_CONNECT, + ]) + request_android_permissions( + permissions, + handle_permissions, + ) + await permission_acknowledged diff --git a/examples/kivy/main.py b/examples/kivy/main.py index dd965d3b..b0fd349e 100644 --- a/examples/kivy/main.py +++ b/examples/kivy/main.py @@ -1,4 +1,5 @@ import asyncio +import os import bleak from kivy.app import App @@ -38,6 +39,9 @@ def on_stop(self): self.running = False async def example(self): + if os.environ.get("P4A_BOOTSTRAP") is not None: + from bleak.backends.p4android.utils import request_permissions + await request_permissions() while self.running: try: self.line("scanning")