Skip to content

BroadcastReceiver hangs on_resume() #2308

@RobertFlatt

Description

@RobertFlatt

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'

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy