python-for-android
python-for-android copied to clipboard
Error when calling broadcastrecivercallback in kivy when build apk in buildozer
2021-11-26 13:54:12.888 28011-28050/com.alfamart.pos I/python: File "./common/func/broadcastreceiver.py", line 56, in init 2021-11-26 13:54:12.889 28011-28050/com.alfamart.pos I/python: self.listener = BroadcastReceiver.Callback(self.callback) 2021-11-26 13:54:12.889 28011-28050/com.alfamart.pos I/python: File "./common/func/broadcastreceiver.py", line 20, in init 2021-11-26 13:54:12.890 28011-28050/com.alfamart.pos I/python: super(PythonJavaClass ,self).init(*args,**kwargs) 2021-11-26 13:54:12.891 28011-28050/com.alfamart.pos I/python: File "jnius/jnius_proxy.pxi", line 28, in jnius.jnius.PythonJavaClass.init 2021-11-26 13:54:12.891 28011-28050/com.alfamart.pos I/python: File "jnius/jnius_proxy.pxi", line 34, in jnius.jnius.PythonJavaClass._init_j_self_ptr 2021-11-26 13:54:12.891 28011-28050/com.alfamart.pos I/python: File "jnius/jnius_proxy.pxi", line 182, in jnius.jnius.create_proxy_instance 2021-11-26 13:54:12.892 28011-28050/com.alfamart.pos I/python: File "jnius/jnius_export_class.pxi", line 768, in jnius.jnius.JavaMethod.call 2021-11-26 13:54:12.892 28011-28050/com.alfamart.pos I/python: File "jnius/jnius_export_class.pxi", line 934, in jnius.jnius.JavaMethod.call_staticmethod 2021-11-26 13:54:12.893 28011-28050/com.alfamart.pos I/python: File "jnius/jnius_utils.pxi", line 91, in jnius.jnius.check_exception 2021-11-26 13:54:12.893 28011-28050/com.alfamart.pos I/python: jnius.jnius.JavaException: JVM exception occurred: interface org.kivy.android.GenericBroadcastReceiverCallback is not visible from class loader 2021-11-26 13:54:12.893 28011-28050/com.alfamart.pos I/python: Python for android ended.
Code:
-------------------------------------------------------------------
Broadcast receiver bridge
from jnius import autoclass, PythonJavaClass, java_method
JNI_NAMESPACE = u'org/kivy/android' JAVA_NAMESPACE = u'org.kivy.android' ACTIVITY_CLASS_NAME = 'org.kivy.android.PythonActivity' SERVICE_CLASS_NAME = 'org.kivy.android.PythonService'
class BroadcastReceiver(object):
class Callback(PythonJavaClass):
__javainterfaces__ = [JNI_NAMESPACE + '/GenericBroadcastReceiverCallback']
__javacontext__ = 'app'
def __init__(self, callback, *args, **kwargs):
self.callback = callback
super(PythonJavaClass ,self).__init__(*args,**kwargs)
@java_method('(Landroid/content/Context;Landroid/content/Intent;)V')
def onReceive(self, context, intent):
self.callback(context, intent)
def __init__(self, callback, actions=None, categories=None):
super().__init__()
self.callback = callback
if not actions and not categories:
raise Exception('You need to define at least actions or categories')
def _expand_partial_name(partial_name):
if '.' in partial_name:
return partial_name # Its actually a full dotted name
else:
name = 'ACTION_{}'.format(partial_name.upper())
if not hasattr(Intent, name):
raise Exception('The intent {} doesnt exist'.format(name))
return getattr(Intent, name)
# resolve actions/categories first
Intent = autoclass('android.content.Intent')
resolved_actions = [_expand_partial_name(x) for x in actions or []]
resolved_categories = [_expand_partial_name(x) for x in categories or []]
# resolve android API
GenericBroadcastReceiver = autoclass(JAVA_NAMESPACE + '.GenericBroadcastReceiver')
IntentFilter = autoclass('android.content.IntentFilter')
HandlerThread = autoclass('android.os.HandlerThread')
# create a thread for handling events from the receiver
self.handlerthread = HandlerThread('handlerthread')
# create a listener
self.listener = BroadcastReceiver.Callback(self.callback)
self.receiver = GenericBroadcastReceiver(self.listener)
self.receiver_filter = IntentFilter()
for x in resolved_actions:
self.receiver_filter.addAction(x)
for x in resolved_categories:
self.receiver_filter.addCategory(x)
def start(self):
Handler = autoclass('android.os.Handler')
self.handlerthread.start()
self.handler = Handler(self.handlerthread.getLooper())
self.context.registerReceiver(
self.receiver, self.receiver_filter, None, self.handler)
def stop(self):
self.context.unregisterReceiver(self.receiver)
self.handlerthread.quit()
@property
def context(self):
from os import environ
if 'PYTHON_SERVICE_ARGUMENT' in environ:
PythonService = autoclass(SERVICE_CLASS_NAME)
return PythonService.mService
PythonActivity = autoclass(ACTIVITY_CLASS_NAME)
return PythonActivity.mActivity
some reference on the cause of the issue https://stackoverflow.com/questions/13263340/findclass-from-any-thread-in-android-jni
@akshayaurora Does this mean p4a should be modified to take care of this, or are you saying it is the app developer's job? [Basically, can I close this?]