diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java | 82 | ||||
-rw-r--r-- | src/android/templates/AndroidManifest.xml | 101 | ||||
-rw-r--r-- | src/android/templates/res/values/libs.xml | 6 | ||||
-rw-r--r-- | src/tools/androiddeployqt/main.cpp | 23 |
4 files changed, 113 insertions, 99 deletions
diff --git a/src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java b/src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java index 7a122f658a..ef53e91bab 100644 --- a/src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java +++ b/src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java @@ -1,4 +1,5 @@ /* + Copyright (C) 2021 The Qt Company Ltd. Copyright (c) 2019, BogDan Vatra <bogdan@kde.org> Contact: http://www.qt.io/licensing/ @@ -42,6 +43,7 @@ import android.content.ContextWrapper; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ComponentInfo; +import android.content.res.Resources; import android.os.Build; import android.os.Bundle; import android.util.Log; @@ -170,28 +172,29 @@ public abstract class QtLoader { // this function is used to load and start the loader private void loadApplication(Bundle loaderParams) { + final Resources resources = m_context.getResources(); + final String packageName = m_context.getPackageName(); try { final int errorCode = loaderParams.getInt(ERROR_CODE_KEY); if (errorCode != 0) { // fatal error, show the error and quit AlertDialog errorDialog = new AlertDialog.Builder(m_context).create(); errorDialog.setMessage(loaderParams.getString(ERROR_MESSAGE_KEY)); - errorDialog.setButton(m_context.getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - finish(); - } - }); + errorDialog.setButton(resources.getString(android.R.string.ok), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); errorDialog.show(); return; } // add all bundled Qt libs to loader params - ArrayList<String> libs = new ArrayList<String>(); - if (m_contextInfo.metaData.containsKey("android.app.bundled_libs_resource_id")) { - int resourceId = m_contextInfo.metaData.getInt("android.app.bundled_libs_resource_id"); - libs.addAll(prefferedAbiLibs(m_context.getResources().getStringArray(resourceId))); - } + int id = resources.getIdentifier("bundled_libs", "array", packageName); + final String[] bundledLibs = resources.getStringArray(id); + ArrayList<String> libs = new ArrayList<>(prefferedAbiLibs(bundledLibs)); String libName = null; if (m_contextInfo.metaData.containsKey("android.app.lib_name")) { @@ -225,17 +228,16 @@ public abstract class QtLoader { } catch (Exception e) { e.printStackTrace(); AlertDialog errorDialog = new AlertDialog.Builder(m_context).create(); - if (m_contextInfo.metaData.containsKey("android.app.fatal_error_msg")) - errorDialog.setMessage(m_contextInfo.metaData.getString("android.app.fatal_error_msg")); - else - errorDialog.setMessage("Fatal error, your application can't be started."); - - errorDialog.setButton(m_context.getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - finish(); - } - }); + int id = resources.getIdentifier("fatal_error_msg", "string", + packageName); + errorDialog.setMessage(resources.getString(id)); + errorDialog.setButton(resources.getString(android.R.string.ok), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); errorDialog.show(); } } @@ -243,14 +245,16 @@ public abstract class QtLoader { public void startApp(final boolean firstStart) { try { - if (m_contextInfo.metaData.containsKey("android.app.qt_libs_resource_id")) { - int resourceId = m_contextInfo.metaData.getInt("android.app.qt_libs_resource_id"); - m_qtLibs = prefferedAbiLibs(m_context.getResources().getStringArray(resourceId)); - } + final Resources resources = m_context.getResources(); + final String packageName = m_context.getPackageName(); + int id = resources.getIdentifier("qt_libs", "array", packageName); + m_qtLibs = prefferedAbiLibs(resources.getStringArray(id)); - if (m_contextInfo.metaData.containsKey("android.app.use_local_qt_libs") - && m_contextInfo.metaData.getInt("android.app.use_local_qt_libs") == 1) { - ArrayList<String> libraryList = new ArrayList<String>(); + id = resources.getIdentifier("use_local_qt_libs", "string", packageName); + final int useLocalLibs = Integer.parseInt(resources.getString(id)); + + if (useLocalLibs == 1) { + ArrayList<String> libraryList = new ArrayList<>(); boolean apkDeployFromSystem = false; String apkPath = m_context.getApplicationInfo().publicSourceDir; @@ -293,10 +297,13 @@ public abstract class QtLoader { libraryList.add(libPrefix + lib + ".so"); } - if (m_contextInfo.metaData.containsKey("android.app.bundle_local_qt_libs") - && m_contextInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) { - int resourceId = m_contextInfo.metaData.getInt("android.app.load_local_libs_resource_id"); - for (String libs : prefferedAbiLibs(m_context.getResources().getStringArray(resourceId))) { + id = resources.getIdentifier("bundle_local_qt_libs", "string", packageName); + final int bundleLocalLibs = Integer.parseInt(resources.getString(id)); + + if (bundleLocalLibs == 1) { + id = resources.getIdentifier("load_local_libs", "array", packageName); + ArrayList<String> localLibs = prefferedAbiLibs(resources.getStringArray(id)); + for (String libs : localLibs) { for (String lib : libs.split(":")) { if (!lib.isEmpty()) libraryList.add(libsDir + lib); @@ -310,10 +317,11 @@ public abstract class QtLoader { loaderParams.putInt(ERROR_CODE_KEY, 0); loaderParams.putString(DEX_PATH_KEY, new String()); loaderParams.putString(LOADER_CLASS_NAME_KEY, loaderClassName()); - if (m_contextInfo.metaData.containsKey("android.app.static_init_classes")) { - loaderParams.putStringArray(STATIC_INIT_CLASSES_KEY, - m_contextInfo.metaData.getString("android.app.static_init_classes").split(":")); - } + + id = resources.getIdentifier("static_init_classes", "string", packageName); + loaderParams.putStringArray(STATIC_INIT_CLASSES_KEY, resources.getString(id) + .split(":")); + loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList); diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml index fa520d0345..d352209339 100644 --- a/src/android/templates/AndroidManifest.xml +++ b/src/android/templates/AndroidManifest.xml @@ -1,75 +1,82 @@ <?xml version="1.0"?> -<manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="-- %%INSERT_VERSION_CODE%% --" android:installLocation="auto"> - <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application. - Remove the comment if you do not require these default permissions. --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.qtproject.example" + android:installLocation="auto" + android:versionCode="-- %%INSERT_VERSION_CODE%% --" + android:versionName="-- %%INSERT_VERSION_NAME%% --"> + <!-- The comment below will be replaced with dependencies permissions upon deployment. + Remove the comment if you do not require these default permissions. --> <!-- %%INSERT_PERMISSIONS --> - <!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application. - Remove the comment if you do not require these default features. --> + <!-- The comment below will be replaced with dependencies permissions upon deployment. + Remove the comment if you do not require these default features. --> <!-- %%INSERT_FEATURES --> - <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> - <application android:hardwareAccelerated="true" android:name="org.qtproject.qt.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:extractNativeLibs="true" android:requestLegacyExternalStorage="true"> - <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="org.qtproject.qt.android.bindings.QtActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="unspecified" android:launchMode="singleTop"> + <supports-screens + android:anyDensity="true" + android:largeScreens="true" + android:normalScreens="true" + android:smallScreens="true" /> + <application + android:name="org.qtproject.qt.android.bindings.QtApplication" + android:extractNativeLibs="true" + android:hardwareAccelerated="true" + android:label="-- %%INSERT_APP_NAME%% --" + android:requestLegacyExternalStorage="true"> + <activity + android:name="org.qtproject.qt.android.bindings.QtActivity" + android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" + android:label="-- %%INSERT_APP_NAME%% --" + android:launchMode="singleTop" + android:screenOrientation="unspecified"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> - - <!-- Application arguments --> - <meta-data android:name="android.app.arguments" android:value="-- %%INSERT_APP_ARGUMENTS%% --"/> <!-- Application arguments --> - <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/> - <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/> - <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/> - <!-- Deploy Qt libs as part of package --> - <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/> + <meta-data + android:name="android.app.arguments" + android:value="-- %%INSERT_APP_ARGUMENTS%% --" /> + <!-- Application arguments --> + <meta-data + android:name="android.app.lib_name" + android:value="-- %%INSERT_APP_LIB_NAME%% --" /> - <!-- Run with local libs --> - <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/> - <meta-data android:name="android.app.load_local_libs_resource_id" android:resource="@array/load_local_libs"/> - <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/> - <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/> <!-- Used to specify custom system library path to run with local system libs --> - <!-- <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/> --> - <!-- Messages maps --> - <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/> - <meta-data android:value="@string/unsupported_android_version" android:name="android.app.unsupported_android_version"/> - <!-- Messages maps --> - +<!-- <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/>--> <!-- Splash screen --> - <!-- Orientation-specific (portrait/landscape) data is checked first. If not available for current orientation, - then android.app.splash_screen_drawable. For best results, use together with splash_screen_sticky and - use hideSplashScreen() with a fade-out animation from Qt Android Extras to hide the splash screen when you - are done populating your window with content. --> - <!-- meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/logo_portrait" / --> - <!-- meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/logo_landscape" / --> - <!-- meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/ --> - <!-- meta-data android:name="android.app.splash_screen_sticky" android:value="true"/ --> + <!-- Orientation-specific (portrait/landscape) data is checked first. If not available + for current orientation, then android.app.splash_screen_drawable. For best + results, use together with splash_screen_sticky and use hideSplashScreen() with + a fade-out animation to hide the splash screen when you are done populating + your window with content. --> +<!-- <meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/logo_portrait" />--> +<!-- <meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/logo_landscape" />--> +<!-- <meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/>--> +<!-- <meta-data android:name="android.app.splash_screen_sticky" android:value="true"/>--> <!-- Splash screen --> <!-- Background running --> <!-- Warning: changing this value to true may cause unexpected crashes if the application still try to draw after - "applicationStateChanged(Qt::ApplicationSuspended)" - signal is sent! --> - <meta-data android:name="android.app.background_running" android:value="false"/> + "applicationStateChanged(Qt::ApplicationSuspended)" signal is sent! --> + <meta-data + android:name="android.app.background_running" + android:value="false" /> <!-- Background running --> <!-- extract android style --> <!-- available android:values : - * default - In most cases this will be the same as "full", but it can also be something else if needed, e.g., for compatibility reasons + * default - In most cases this will be the same as "full", but it can also be + * something else if needed, e.g., for compatibility reasons * full - useful QWidget & Quick Controls 1 apps * minimal - useful for Quick Controls 2 apps, it is much faster than "full" - * none - useful for apps that don't use any of the above Qt modules - --> - <meta-data android:name="android.app.extract_android_style" android:value="default"/> + * none - useful for apps that don't use any of the above Qt modules --> + <meta-data + android:name="android.app.extract_android_style" + android:value="default" /> <!-- extract android style --> - </activity> - - <!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices --> - + </activity> </application> - </manifest> diff --git a/src/android/templates/res/values/libs.xml b/src/android/templates/res/values/libs.xml index 280c03c686..beb15ca1d8 100644 --- a/src/android/templates/res/values/libs.xml +++ b/src/android/templates/res/values/libs.xml @@ -1,7 +1,6 @@ <?xml version='1.0' encoding='utf-8'?> <resources> - <!-- The following is handled automatically by the deployment tool. It should - not be edited manually. --> + <!-- DO NOT EDIT THIS: This file is populated automatically by the deployment tool. --> <array name="bundled_libs"> <!-- %%INSERT_EXTRA_LIBS%% --> @@ -15,4 +14,7 @@ <!-- %%INSERT_LOCAL_LIBS%% --> </array> + <string name="static_init_classes"><!-- %%INSERT_INIT_CLASSES%% --></string> + <string name="use_local_qt_libs"><!-- %%USE_LOCAL_QT_LIBS%% --></string> + <string name="bundle_local_qt_libs"><!-- %%BUNDLE_LOCAL_QT_LIBS%% --></string> </resources> diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp index 406acaf54d..7993a0cfb8 100644 --- a/src/tools/androiddeployqt/main.cpp +++ b/src/tools/androiddeployqt/main.cpp @@ -235,7 +235,6 @@ struct Options bool usesOpenGL = false; // Per package collected information - QStringList localJars; QStringList initClasses; QStringList permissions; QStringList features; @@ -1411,10 +1410,20 @@ bool updateLibsXml(Options *options) allLocalLibs += QLatin1String(" <item>%1;%2</item>\n").arg(it.key(), localLibs.join(QLatin1Char(':'))); } + options->initClasses.removeDuplicates(); + QHash<QString, QString> replacements; replacements[QStringLiteral("<!-- %%INSERT_QT_LIBS%% -->")] += qtLibs.trimmed(); replacements[QStringLiteral("<!-- %%INSERT_LOCAL_LIBS%% -->")] = allLocalLibs.trimmed(); replacements[QStringLiteral("<!-- %%INSERT_EXTRA_LIBS%% -->")] = extraLibs.trimmed(); + const QString initClasses = options->initClasses.join(QLatin1Char(':')); + replacements[QStringLiteral("<!-- %%INSERT_INIT_CLASSES%% -->")] = initClasses; + + // Bundle and use libs from the apk because currently we don't have a way avoid + // duplicating them. + replacements[QStringLiteral("<!-- %%BUNDLE_LOCAL_QT_LIBS%% -->")] = QLatin1String("1"); + replacements[QStringLiteral("<!-- %%USE_LOCAL_QT_LIBS%% -->")] = QLatin1String("1"); + if (!updateFile(fileName, replacements)) return false; @@ -1456,22 +1465,13 @@ bool updateAndroidManifest(Options &options) if (options.verbose) fprintf(stdout, " -- AndroidManifest.xml \n"); - options.localJars.removeDuplicates(); - options.initClasses.removeDuplicates(); - QHash<QString, QString> replacements; replacements[QStringLiteral("-- %%INSERT_APP_NAME%% --")] = options.applicationBinary; replacements[QStringLiteral("-- %%INSERT_APP_ARGUMENTS%% --")] = options.applicationArguments; replacements[QStringLiteral("-- %%INSERT_APP_LIB_NAME%% --")] = options.applicationBinary; - replacements[QStringLiteral("-- %%INSERT_LOCAL_JARS%% --")] = options.localJars.join(QLatin1Char(':')); - replacements[QStringLiteral("-- %%INSERT_INIT_CLASSES%% --")] = options.initClasses.join(QLatin1Char(':')); replacements[QStringLiteral("-- %%INSERT_VERSION_NAME%% --")] = options.versionName; replacements[QStringLiteral("-- %%INSERT_VERSION_CODE%% --")] = options.versionCode; replacements[QStringLiteral("package=\"org.qtproject.example\"")] = QLatin1String("package=\"%1\"").arg(options.packageName); - replacements[QStringLiteral("-- %%BUNDLE_LOCAL_QT_LIBS%% --")] - = (options.deploymentMechanism == Options::Bundled) ? QLatin1String("1") : QLatin1String("0"); - // use libs from the apk - replacements[QStringLiteral("-- %%USE_LOCAL_QT_LIBS%% --")] = QLatin1String("1"); QString permissions; for (const QString &permission : qAsConst(options.permissions)) @@ -1664,9 +1664,6 @@ bool readAndroidDependencyXml(Options *options, } } - if (!fileName.isEmpty()) - options->localJars.append(fileName); - if (reader.attributes().hasAttribute(QLatin1String("initClass"))) { options->initClasses.append(reader.attributes().value(QLatin1String("initClass")).toString()); } |