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 <assam.boudjelthia@qt.io>
This commit is contained in:
Tinja Paavoseppä 2024-04-24 09:14:05 +03:00
parent 9e259de282
commit 092b3a0ff9
7 changed files with 33 additions and 6 deletions

View File

@ -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()) {

View File

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

View File

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

View File

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

View File

@ -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());

View File

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

View File

@ -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());