Didn't find class "com.github.hbldh.bleak.PythonScanCallback$Interface"
- bleak version: 0.21.1
- Python version: 3.10
- Operating System: android
Description
python-for-andorid+flask
What I Did
this is my flask code
import asyncio
import bleak
async def main():
return [{'name': d.name, 'addr': d.address} for d in await bleak.BleakScanner.discover() if d.name]
print(asyncio.run(main()))
def scan():
return asyncio.run(main())
i user python-for-android create a flask apk,i want scan lbe.
Logs
I successfully scanned the device when the program started
11-26 13:38:57.239 10024 10096 I python : [{'name': 'Mesh Mi Switch 1', 'addr': '74:A3:4A:E2:83:9D'}, {'name': 'Qingping Motion & Light', 'addr': '58:2D:34:60:A7:9A'}, {'name': 'AIMA-06B4D0', 'addr': 'F1:22:33:06:B4:D0'}, {'name': '客厅 电视', 'addr': '78:F2:35:2F:10:D6'}, {'name': 'Mesh Mi Switch 1', 'addr': '74:A3:4A:E2:83:3E'}, {'name': 'yeelink.light.light3', 'addr': '28:D1:27:31:2C:38'}, {'name': 'yeelink.light.light3', 'addr': '28:D1:27:2B:43:49'}, {'name': 'yeelink.light.light3', 'addr': '28:D1:27:2D:68:6A'}, {'name': 'LYWSD03MMC', 'addr': 'A4:C1:38:D4:7A:1D'}, {'name': 'LYWSD03MMC', 'addr': 'A4:C1:38:DA:BB:05'}]
When I call the ‘scan’ api, the program reports an error
11-26 13:39:17.282 10024 10332 I python : [2023-11-26 13:39:17,279] ERROR in app: Exception on /api/config/scan [POST]
11-26 13:39:17.282 10024 10332 I python : Traceback (most recent call last):
11-26 13:39:17.282 10024 10332 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/flask/app.py", line 2073, in wsgi_app
11-26 13:39:17.282 10024 10332 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/flask/app.py", line 1518, in full_dispatch_request
11-26 13:39:17.282 10024 10332 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/flask/app.py", line 1516, in full_dispatch_request
11-26 13:39:17.282 10024 10332 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/flask/app.py", line 1502, in dispatch_request
11-26 13:39:17.282 10024 10332 I python : File "/tda/tda-android/main.py", line 32, in api
11-26 13:39:17.282 10024 10332 I python : File "/tda/tda-android/model/config.py", line 14, in scan
11-26 13:39:17.282 10024 10332 I python : File "/root/.local/share/python-for-android/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/Lib/asyncio/runners.py", line 44, in run
11-26 13:39:17.282 10024 10332 I python : File "/root/.local/share/python-for-android/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/Lib/asyncio/base_events.py", line 641, in run_until_complete
11-26 13:39:17.282 10024 10332 I python : File "/tda/tda-android/model/config.py", line 7, in main
11-26 13:39:17.282 10024 10332 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/bleak/__init__.py", line 317, in discover
11-26 13:39:17.282 10024 10332 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/bleak/__init__.py", line 158, in __aenter__
11-26 13:39:17.282 10024 10332 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/bleak/backends/p4android/scanner.py", line 74, in start
11-26 13:39:17.282 10024 10332 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/bleak/backends/p4android/scanner.py", line 278, in __init__
11-26 13:39:17.282 10024 10332 I python : File "jnius/jnius_export_class.pxi", line 269, in jnius.jnius.JavaClass.__init__
11-26 13:39:17.282 10024 10332 I python : File "jnius/jnius_export_class.pxi", line 362, in jnius.jnius.JavaClass.call_constructor
11-26 13:39:17.282 10024 10332 I python : File "jnius/jnius_conversion.pxi", line 99, in jnius.jnius.populate_args
11-26 13:39:17.282 10024 10332 I python : File "jnius/jnius_proxy.pxi", line 34, in jnius.jnius.PythonJavaClass._init_j_self_ptr
11-26 13:39:17.282 10024 10332 I python : File "jnius/jnius_proxy.pxi", line 166, in jnius.jnius.create_proxy_instance
11-26 13:39:17.282 10024 10332 I python : File "jnius/jnius_export_func.pxi", line 22, in jnius.jnius.find_javaclass
11-26 13:39:17.282 10024 10332 I python : File "jnius/jnius_utils.pxi", line 79, in jnius.jnius.check_exception
11-26 13:39:17.282 10024 10332 I python : jnius.jnius.JavaException: JVM exception occurred: Didn't find class "com.github.hbldh.bleak.PythonScanCallback$Interface" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib64, /system/system_ext/lib64, /system/product/lib64, /system/lib64, /system/system_ext/lib64, /system/product/lib64]] java.lang.ClassNotFoundException
11-26 13:39:17.285 10024 10332 I python : 127.0.0.1 - - [26/Nov/2023 13:39:17] "POST /api/config/scan HTTP/1.1" 500 -
I used bleak recipe on python-for-Android,i can use bleak in android flask,but only use flask "threaded=False" you know,bluetooth operation takes time,i want threaded=True help me
from jnius import autoclass
autoclass('org.jnius.NativeInvocationHandler')
autoclass('com.github.hbldh.bleak.PythonScanCallback')
autoclass('com.github.hbldh.bleak.PythonBluetoothGattCallback')
autoclass('com.github.hbldh.bleak.PythonScanCallback$Interface')
autoclass java in main.py, At the beginning, it was Didn't find class org.jnius.NativeInvocationHandler then com.github.hbldh.bleak.PythonScanCallback after com.github.hbldh.bleak.PythonBluetoothGattCallback last i user autoclass import com.github.hbldh.bleak.PythonScanCallback$Interface. But he is ineffective
01-25 17:00:39.820 31179 8229 I python : File "/tda/tda-android/model/ble.py", line 20, in scan
01-25 17:00:39.820 31179 8229 I python : File "/root/.local/share/python-for-android/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/Lib/asyncio/runners.py", line 44, in run
01-25 17:00:39.820 31179 8229 I python : File "/root/.local/share/python-for-android/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/Lib/asyncio/base_events.py", line 641, in run_until_complete
01-25 17:00:39.820 31179 8229 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/bleak/__init__.py", line 317, in discover
01-25 17:00:39.820 31179 8229 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/bleak/__init__.py", line 158, in __aenter__
01-25 17:00:39.820 31179 8229 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/bleak/backends/p4android/scanner.py", line 74, in start
01-25 17:00:39.820 31179 8229 I python : File "/root/.local/share/python-for-android/build/python-installs/tda/arm64-v8a/bleak/backends/p4android/scanner.py", line 278, in __init__
jnius.jnius.JavaException: JVM exception occurred: Didn't find class "com.github.hbldh.bleak.PythonScanCallback$Interface" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib64, /system_ext/lib64, /system/lib64, /system_ext/lib64]] java.lang.ClassNotFoundException
Hey man did you find a solution?
Actually I found some complex if you want deal with it from python. but I ended up editing the bleak module locally and did these steps:
-
I had to call
autoclass("PACKAGE")in main thread for all packages (com.github.hbldh.bleak.PythonScanCallback, org.jnius.NativeInvocationHandler ... ) needed. -
In my case even after that this interface "com.github.hbldh.bleak.PythonBluetoothGattCallback$Interface" wasn't recognized in the other threads so I had to initialize all the clients in main thread but even with that this line in backends/p4android/client
self.__callbacks = _PythonBluetoothGattCallback(self, loop)caused problems because it's the one loading com.github.hbldh.bleak.PythonBluetoothGattCallback$Interface . So I moved all
self.__adapter = defs.BluetoothAdapter.getDefaultAdapter()
if self.__adapter is None:
raise BleakError("Bluetooth is not supported on this hardware platform")
if self.__adapter.getState() != defs.BluetoothAdapter.STATE_ON:
raise BleakError("Bluetooth is not turned on")
self.__device = self.__adapter.getRemoteDevice(self.address)
self.__callbacks = _PythonBluetoothGattCallback(self, loop)
self._subscriptions = {}
from connect to __init__ and made it able to take a loop as a parameter
def __init__(
self,
address_or_ble_device: Union[BLEDevice, str],
services: Optional[Set[uuid.UUID]],
loop,
**kwargs,
)
in the main thread:
loop = asyncio.new_event_loop()
speed_client = bleak.BleakClient(speed_address, loop = loop)
cadence_client = bleak.BleakClient(cadence_address, loop = loop)
my function that connect each device:
async def connect_device(client, callback):
try:
await client.connect()
await client.start_notify(CSC_SERVICE, callback)
....
in my function that connect the devices
async def connect_devices(info):
asyncio.set_event_loop(loop)
...
cadence_connect = connect_device(cadence_client, cadence_callback)
speed_connect = connect_device(speed_client, speed_callback)
await asyncio.gather(cadence_connect, speed_connect)
Hope this helps
Actually I found some complex if you want deal with it from python. but I ended up editing the bleak module locally and did these steps:
- I had to call
autoclass("PACKAGE")in main thread for all packages (com.github.hbldh.bleak.PythonScanCallback, org.jnius.NativeInvocationHandler ... ) needed.- In my case even after that this interface "com.github.hbldh.bleak.PythonBluetoothGattCallback$Interface" wasn't recognized in the other threads so I had to initialize all the clients in main thread but even with that this line in backends/p4android/client
self.__callbacks = _PythonBluetoothGattCallback(self, loop)caused problems because it's the one loading com.github.hbldh.bleak.PythonBluetoothGattCallback$Interface . So I moved allself.__adapter = defs.BluetoothAdapter.getDefaultAdapter() if self.__adapter is None: raise BleakError("Bluetooth is not supported on this hardware platform") if self.__adapter.getState() != defs.BluetoothAdapter.STATE_ON: raise BleakError("Bluetooth is not turned on") self.__device = self.__adapter.getRemoteDevice(self.address) self.__callbacks = _PythonBluetoothGattCallback(self, loop) self._subscriptions = {}from
connectto__init__and made it able to take a loop as a parameterdef __init__( self, address_or_ble_device: Union[BLEDevice, str], services: Optional[Set[uuid.UUID]], loop, **kwargs, )in the main thread:
loop = asyncio.new_event_loop() speed_client = bleak.BleakClient(speed_address, loop = loop) cadence_client = bleak.BleakClient(cadence_address, loop = loop)my function that connect each device:
async def connect_device(client, callback): try: await client.connect() await client.start_notify(CSC_SERVICE, callback) ....in my function that connect the devices
async def connect_devices(info): asyncio.set_event_loop(loop) ... cadence_connect = connect_device(cadence_client, cadence_callback) speed_connect = connect_device(speed_client, speed_callback) await asyncio.gather(cadence_connect, speed_connect)Hope this helps
Why have to call autoclass("PACKAGE") in main thread for all packages needed and how to do this?
How to solve it? I didn't understand either