Android: Make the manifest less to scary to read and edit

Remove unnecessary elements from the manifest file, making it
easier to manage and read. Mostly, the removed elements are
more internal data that is populated by the build system
and the user shouldn't have to worry or confront that.

Also, use the same formatting used by Android Studio.

[ChangeLog][Android] Remove some elements from the manifest
file that are internal, to make it easier to deal with the
manifest.

Pick-to: 6.2
Change-Id: I6a1f275b579370972c0bf022502a8fbfe7d0bfd1
Reviewed-by: BogDan Vatra <bogdan@kdab.com>
This commit is contained in:
Assam Boudjelthia 2021-06-22 19:34:12 +03:00
parent af6bc5a21b
commit 963a31c0f4
4 changed files with 113 additions and 99 deletions

View File

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

View File

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

View File

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

View File

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