qml: don't unbind/unregister the ActivityResultListener from within the ActivityResultListener handler func.
instead, schedule a queued finished signal to unregister the listener after the handler has finished. See PythonActivity.java in P4A for why this probably causes the most often occurring crash we see on the Play Store: ``` Exception java.lang.RuntimeException: at android.app.ActivityThread.deliverResults (ActivityThread.java:5164) at android.app.ActivityThread.handleSendResult (ActivityThread.java:5205) at android.app.servertransaction.ActivityResultItem.execute (ActivityResultItem.java:51) at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2136) at android.os.Handler.dispatchMessage (Handler.java:106) at android.os.Looper.loop (Looper.java:236) at android.app.ActivityThread.main (ActivityThread.java:8061) at java.lang.reflect.Method.invoke at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:656) at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:967) Caused by java.util.ConcurrentModificationException: at java.util.ArrayList$Itr.next (ArrayList.java:860) at org.kivy.android.PythonActivity.onActivityResult (PythonActivity.java:218) at android.app.Activity.dispatchActivityResult (Activity.java:8501) at android.app.ActivityThread.deliverResults (ActivityThread.java:5157) ```
This commit is contained in:
@@ -413,7 +413,7 @@ ApplicationWindow
|
||||
Component {
|
||||
id: _scanDialog
|
||||
QRScanner {
|
||||
//onClosed: destroy()
|
||||
onFinished: destroy()
|
||||
}
|
||||
}
|
||||
Component {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, Qt
|
||||
from PyQt6.QtGui import QGuiApplication
|
||||
|
||||
from electrum.util import send_exception_to_crash_reporter, UserFacingException
|
||||
@@ -10,7 +10,7 @@ from electrum.i18n import _
|
||||
|
||||
|
||||
if 'ANDROID_DATA' in os.environ:
|
||||
from jnius import autoclass, cast
|
||||
from jnius import autoclass
|
||||
from android import activity
|
||||
|
||||
jpythonActivity = autoclass('org.kivy.android.PythonActivity').mActivity
|
||||
@@ -23,10 +23,18 @@ class QEQRScanner(QObject):
|
||||
|
||||
found = pyqtSignal()
|
||||
|
||||
finished = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._hint = _("Scan a QR code.")
|
||||
self._scan_data = "" # decoded qr code result
|
||||
self.finished.connect(self._unbind, Qt.ConnectionType.QueuedConnection)
|
||||
|
||||
self.destroyed.connect(lambda: self.on_destroy())
|
||||
|
||||
def on_destroy(self):
|
||||
self._unbind()
|
||||
|
||||
@pyqtProperty(str)
|
||||
def hint(self):
|
||||
@@ -49,34 +57,34 @@ class QEQRScanner(QObject):
|
||||
if 'ANDROID_DATA' not in os.environ:
|
||||
self._scan_qr_non_android()
|
||||
return
|
||||
SimpleScannerActivity = autoclass("org.electrum.qr.SimpleScannerActivity")
|
||||
intent = jIntent(jpythonActivity, SimpleScannerActivity)
|
||||
jSimpleScannerActivity = autoclass("org.electrum.qr.SimpleScannerActivity")
|
||||
intent = jIntent(jpythonActivity, jSimpleScannerActivity)
|
||||
intent.putExtra(jIntent.EXTRA_TEXT, jString(self._hint))
|
||||
|
||||
def on_qr_result(requestCode, resultCode, intent):
|
||||
try:
|
||||
if resultCode == -1: # RESULT_OK:
|
||||
# this doesn't work due to some bug in jnius:
|
||||
# contents = intent.getStringExtra("text")
|
||||
contents = intent.getStringExtra(jString("text"))
|
||||
#self._logger.info(f"on_qr_result. {contents=!r}")
|
||||
self.scanData = contents
|
||||
self.found.emit()
|
||||
except Exception as e: # exc would otherwise get lost
|
||||
send_exception_to_crash_reporter(e)
|
||||
finally:
|
||||
activity.unbind(on_activity_result=on_qr_result)
|
||||
activity.bind(on_activity_result=on_qr_result)
|
||||
activity.bind(on_activity_result=self.on_qr_activity_result)
|
||||
jpythonActivity.startActivityForResult(intent, 0)
|
||||
|
||||
def on_qr_activity_result(self, requestCode, resultCode, intent):
|
||||
try:
|
||||
if resultCode == -1: # RESULT_OK:
|
||||
contents = intent.getStringExtra(jString("text"))
|
||||
self.scanData = contents
|
||||
self.found.emit()
|
||||
except Exception as e: # exc would otherwise get lost
|
||||
send_exception_to_crash_reporter(e)
|
||||
finally:
|
||||
self.finished.emit()
|
||||
|
||||
@pyqtSlot()
|
||||
def close(self):
|
||||
pass
|
||||
def _unbind(self):
|
||||
if 'ANDROID_DATA' in os.environ:
|
||||
activity.unbind(on_activity_result=self.on_qr_activity_result)
|
||||
|
||||
def _scan_qr_non_android(self):
|
||||
data = QGuiApplication.clipboard().text()
|
||||
self.scanData = data
|
||||
self.found.emit()
|
||||
self.finished.emit()
|
||||
return
|
||||
# from electrum import qrscanner
|
||||
# from .qeapp import ElectrumQmlApplication
|
||||
|
||||
Reference in New Issue
Block a user