From 092b3a0ff9c24edd0fc60dc436aaefcca2b1939c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tinja=20Paavosepp=C3=A4?= Date: Wed, 24 Apr 2024 09:14:05 +0300 Subject: [PATCH] Android: Make QtLoader subclasses singletons When embedding QML to non-Qt Android apps, it is possible that the QtView will be recreated, after e.g. an orientation change. This will lead to a new QtLoader being created and trying to load the Qt libraries again, even though they have already been loaded. Also, once adding support for having more than one QtView, it doesn't make sense to try and load the libraries again. Having the loaders be singletons and checking whether the libraries have already been loaded avoids this. Task-number: QTBUG-124114 Pick-to: 6.8 Change-Id: I2273fc58a8f1268f03d3348b782e74d83759f351 Reviewed-by: Assam Boudjelthia --- .../src/org/qtproject/qt/android/QtActivityBase.java | 2 +- .../src/org/qtproject/qt/android/QtActivityLoader.java | 8 +++++++- .../src/org/qtproject/qt/android/QtEmbeddedLoader.java | 10 +++++++++- .../jar/src/org/qtproject/qt/android/QtLoader.java | 9 ++++++++- .../src/org/qtproject/qt/android/QtServiceBase.java | 2 +- .../src/org/qtproject/qt/android/QtServiceLoader.java | 6 ++++++ .../jar/src/org/qtproject/qt/android/QtView.java | 2 +- 7 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java index e2dae9eb2f0..0999b440463 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java @@ -107,7 +107,7 @@ public class QtActivityBase extends Activity implements QtNative.AppStateDetails addReferrer(getIntent()); try { - QtActivityLoader loader = new QtActivityLoader(this); + QtActivityLoader loader = QtActivityLoader.getActivityLoader(this); loader.appendApplicationParameters(m_applicationParams); if (loader.loadQtLibraries()) { diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityLoader.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityLoader.java index 46fe95543b8..0efefc17efc 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityLoader.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityLoader.java @@ -24,7 +24,7 @@ import java.nio.charset.StandardCharsets; class QtActivityLoader extends QtLoader { private final Activity m_activity; - QtActivityLoader(Activity activity) throws IllegalArgumentException + private QtActivityLoader(Activity activity) throws IllegalArgumentException { super(new ContextWrapper(activity)); m_activity = activity; @@ -32,6 +32,12 @@ class QtActivityLoader extends QtLoader { extractContextMetaData(m_activity); } + static QtActivityLoader getActivityLoader(Activity activity) throws IllegalArgumentException { + if (m_instance == null) + m_instance = new QtActivityLoader(activity); + return (QtActivityLoader) m_instance; + } + private String getDecodedUtfString(String str) { byte[] decodedExtraEnvVars = Base64.decode(str, Base64.DEFAULT); diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java index 5606da665bf..72750dc5461 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedLoader.java @@ -6,10 +6,12 @@ package org.qtproject.qt.android; import android.content.Context; import android.content.ContextWrapper; +import android.util.Log; + class QtEmbeddedLoader extends QtLoader { private static final String TAG = "QtEmbeddedLoader"; - QtEmbeddedLoader(Context context) throws IllegalArgumentException { + private QtEmbeddedLoader(Context context) throws IllegalArgumentException { super(new ContextWrapper(context)); // TODO Service context handling QTBUG-118874 int displayDensity = context.getResources().getDisplayMetrics().densityDpi; @@ -18,4 +20,10 @@ class QtEmbeddedLoader extends QtLoader { setEnvironmentVariable("ANDROID_STYLE_PATH", stylePath); setEnvironmentVariable("QT_ANDROID_NO_EXIT_CALL", String.valueOf(true)); } + + static QtEmbeddedLoader getEmbeddedLoader(Context context) throws IllegalArgumentException { + if (m_instance == null) + m_instance = new QtEmbeddedLoader(context); + return (QtEmbeddedLoader) m_instance; + } } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtLoader.java b/src/android/jar/src/org/qtproject/qt/android/QtLoader.java index 7747e16b023..f0d5d09eee3 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtLoader.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtLoader.java @@ -49,6 +49,9 @@ abstract class QtLoader { protected int m_debuggerSleepMs = 0; + protected static QtLoader m_instance = null; + protected boolean m_librariesLoaded; + /** * Sets and initialize the basic pieces. * Initializes the class loader since it doesn't rely on anything @@ -57,7 +60,7 @@ abstract class QtLoader { * @throws IllegalArgumentException if the given Context is not either an Activity or Service, * or no ComponentInfo could be found for it **/ - public QtLoader(ContextWrapper context) throws IllegalArgumentException { + QtLoader(ContextWrapper context) throws IllegalArgumentException { m_resources = context.getResources(); m_packageName = context.getPackageName(); final Context baseContext = context.getBaseContext(); @@ -414,6 +417,9 @@ abstract class QtLoader { * Loads all Qt native bundled libraries and main library. **/ public boolean loadQtLibraries() { + if (m_librariesLoaded) + return true; + if (!useLocalQtLibs()) { Log.w(QtTAG, "Use local Qt libs is false"); return false; @@ -460,6 +466,7 @@ abstract class QtLoader { Log.e(QtTAG, "Loading main library failed"); return false; } + m_librariesLoaded = true; return true; } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtServiceBase.java b/src/android/jar/src/org/qtproject/qt/android/QtServiceBase.java index 395b19931b7..81cc4e59652 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtServiceBase.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtServiceBase.java @@ -28,7 +28,7 @@ public class QtServiceBase extends Service { QtNative.setService(this); try { - QtServiceLoader loader = new QtServiceLoader(this); + QtServiceLoader loader = QtServiceLoader.getServiceLoader(this); if (loader.loadQtLibraries()) { QtNative.startApplication(loader.getApplicationParameters(), loader.getMainLibraryPath()); diff --git a/src/android/jar/src/org/qtproject/qt/android/QtServiceLoader.java b/src/android/jar/src/org/qtproject/qt/android/QtServiceLoader.java index 23c7b3fa264..816ad566c83 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtServiceLoader.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtServiceLoader.java @@ -14,4 +14,10 @@ class QtServiceLoader extends QtLoader { super(new ContextWrapper(service)); extractContextMetaData(service); } + + static QtServiceLoader getServiceLoader(Service service) throws IllegalArgumentException { + if (m_instance == null) + m_instance = new QtServiceLoader(service); + return (QtServiceLoader) m_instance; + } } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtView.java b/src/android/jar/src/org/qtproject/qt/android/QtView.java index 91756b47532..706d66eccf2 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtView.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtView.java @@ -145,7 +145,7 @@ abstract class QtView extends ViewGroup { void loadQtLibraries(String appLibName) { QtEmbeddedLoader loader = null; try { - loader = new QtEmbeddedLoader(getContext()); + loader = QtEmbeddedLoader.getEmbeddedLoader(getContext()); } catch (IllegalArgumentException e) { Log.e(TAG, e.getMessage()); QtEmbeddedViewInterfaceFactory.remove(getContext());