Browse Source

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)
```
master
Sander van Grieken 2 years ago
parent
commit
450b9a03ce
No known key found for this signature in database
GPG Key ID: 9BCF8209EA402EBA
  1. 2
      electrum/gui/qml/components/main.qml
  2. 48
      electrum/gui/qml/qeqrscanner.py

2
electrum/gui/qml/components/main.qml

@ -413,7 +413,7 @@ ApplicationWindow
Component {
id: _scanDialog
QRScanner {
//onClosed: destroy()
onFinished: destroy()
}
}
Component {

48
electrum/gui/qml/qeqrscanner.py

@ -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

Loading…
Cancel
Save