-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
Checklist
- [x ] the issue is indeed a bug and not a support request
- [ x] issue doesn't already exist: https://github.com/kivy/python-for-android/issues
- [ x] I have a short, runnable example that reproduces the issue
- [ x] I reproduced the problem with the latest development version (
p4a.branch = develop
) - [ x] I used the grave accent (aka backticks) to format code or logs when appropriated
Versions
- Python: 3.8
- OS: Android 10
- Kivy: 1.11.1
- Cython: 29
- OpenJDK: 8
Description
BroadcastReveiver hangs with "JVM exception occurred: Java.lang.IllegalThreadStateException" during on_resume().
This on_resume() call is the second call to BroadcastReveiver().start() after a stop() in on_pause()
I believe the issue is in pythonforandroid/recipes/android/src/android/broadcast.py
In line 49, where self.handlertheread is instantiated in __init__() and it should be instantiated in start(), because it is destroyed by .quit() in stop()
To replicate, start the app, wait till the screen shows the result of at least one scan, then pause the app. Resume the app, screen should show "scanning......" but actually shows the screen at pause state - this is never updated as the app has hung.
The issue has presumably been exposed by the changes in garbage collection in Python 3.8
test case:
#############################################
# WiFi Scanner
#############################################
from kivy.app import App
from kivy.uix.label import Label
from android import mActivity
from android.broadcast import BroadcastReceiver
from android.permissions import request_permissions,check_permission,Permission
from android.runnable import run_on_ui_thread
from jnius import autoclass, cast
############## References #################
# https://developer.android.com/guide/topics/connectivity/wifi-scan#java
# Android documentation error? It appears ACCESS_WIFI_STATE is also required.
#
# BUT this API is depreciated in API 28 :(
# https://developer.android.com/reference/android/net/wifi/WifiManager#startScan()
#
# Pattern for this app:
# https://python-for-android.readthedocs.io/en/stable/old_toolchain/android/#module-android.broadcast
#
# Use default buildozer.spec except:
# android.permissions = ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE, CHANGE_WIFI_STATE
#
# Tested with SDK 27, NDK 19c, Android 10
###########################################
Context = autoclass('android.content.Context')
WifiManager = autoclass('android.net.wifi.WifiManager')
class MyApp(App):
def build(self):
self.paused = False
action = WifiManager.SCAN_RESULTS_AVAILABLE_ACTION
self.wm = cast('android.net.wifi.WifiManager',
mActivity.getSystemService(Context.WIFI_SERVICE))
self.br = BroadcastReceiver(self.on_broadcast,actions=[action])
self.label = Label(text='None')
return self.label
@run_on_ui_thread
def update_label(self,text):
self.label.text = text
def on_broadcast(self, context, intent):
extras = intent.getExtras()
if extras.get(WifiManager.EXTRA_RESULTS_UPDATED):
text = 'Look what I found (Scan #'+str(self.scan)+'):\n\n'
self.scan += 1
for result in self.wm.getScanResults().toArray():
if result.SSID:
text += result.SSID + '\n'
else:
text += 'A WiFi with no SSID\n'
self.update_label(text)
def on_start(self):
request_permissions([Permission.ACCESS_FINE_LOCATION,
Permission.ACCESS_WIFI_STATE,
Permission.CHANGE_WIFI_STATE],
self.callback)
def callback(self,permissions,grants):
self.granted = all(grants)
self.start_scan()
def start_scan(self):
self.scan = 0
if self.granted:
self.br.start()
if self.wm.startScan():
self.label.text = 'Scanning.........'
else:
self.label.text = 'Start Scan Failed'
else:
self.label.text = 'Not Authorized to Scan'
def on_pause(self):
if self.granted:
# Cause of issue is "self.handlerthread.quit()" inside the next line.
self.br.stop()
# Unrelated to this issue report:
# Handle race condition with callback() on first on_pause()
self.paused = True
return True
def on_resume(self):
if self.paused:
self.granted =\
check_permission(Permission.ACCESS_FINE_LOCATION) and\
check_permission(Permission.ACCESS_WIFI_STATE) and\
check_permission(Permission.CHANGE_WIFI_STATE)
# Issue, on_resume():
# JVM exception occurred: java.lang.IllegalThreadStateException
# occurs in start_scan() then self.br.start() at self.handlerthread.start()
self.start_scan()
MyApp().run()
buildozer.spec
Command:
buildozer android debug
Spec file:
Default buildozer.spec, except:
android.permissions = ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE, CHANGE_WIFI_STATE
Logs
09-04 18:27:08.011 3778 3778 I python : Traceback (most recent call last):
09-04 18:27:08.011 3778 3778 I python : File "/home/bobf/ex/wifi/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/myapp/kivy/core/window/window_sdl2.py", line 251, in _event_filter
09-04 18:27:08.011 3778 3778 I python : File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
09-04 18:27:08.011 3778 3778 I python : File "/home/bobf/ex/wifi/.buildozer/android/app/main.py", line 97, in on_resume
09-04 18:27:08.012 3778 3778 I python : File "/home/bobf/ex/wifi/.buildozer/android/app/main.py", line 72, in start_scan
09-04 18:27:08.012 3778 3778 I python : File "/home/bobf/ex/wifi/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/myapp/android/broadcast.py", line 75, in start
09-04 18:27:08.012 3778 3778 I python : File "jnius/jnius_export_class.pxi", line 857, in jnius.jnius.JavaMethod.__call__
09-04 18:27:08.012 3778 3778 I python : File "jnius/jnius_export_class.pxi", line 954, in jnius.jnius.JavaMethod.call_method
09-04 18:27:08.012 3778 3778 I python : File "jnius/jnius_utils.pxi", line 91, in jnius.jnius.check_exception
09-04 18:27:08.012 3778 3778 I python : jnius.jnius.JavaException: JVM exception occurred: java.lang.IllegalThreadStateException
09-04 18:27:08.013 3778 3778 I python : Exception ignored in: 'kivy.core.window._window_sdl2._WindowSDL2Storage.cb_event_filter'