From cba3c3004741787311e7a513346afde9b3b631c9 Mon Sep 17 00:00:00 2001 From: Juha Vuolle Date: Wed, 21 Aug 2024 15:11:27 +0300 Subject: [PATCH] Prioritize Android permissions of the application manifest This is a manual cherry-pick from 2c1506b1bd551249852d43250d7919f5e3ac7ac1 With minor documentation modification (6.8.1 instead of 6.9). Users may use their own AndroidManifest.xml and define permissions. However in case the manifest defines a permission that a Qt module also sets when the template replacement is done, an error will occur during the application build (duplicate permission definition). This patch prioritizes such manual permissions and removes any previous ones a Qt module might have set. Task-number: QTBUG-129944 Change-Id: If94c218928aa5672686dd468a8d66995508d591f Reviewed-by: Assam Boudjelthia (cherry picked from commit 2c1506b1bd551249852d43250d7919f5e3ac7ac1) --- .../android-manifest-file-configuration.qdoc | 11 +++++++++++ src/corelib/kernel/qpermissions.cpp | 2 ++ src/tools/androiddeployqt/main.cpp | 17 +++++++++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/android/templates/doc/src/android-manifest-file-configuration.qdoc b/src/android/templates/doc/src/android-manifest-file-configuration.qdoc index 407a10c8920..d899e4675f0 100644 --- a/src/android/templates/doc/src/android-manifest-file-configuration.qdoc +++ b/src/android/templates/doc/src/android-manifest-file-configuration.qdoc @@ -246,6 +246,17 @@ the actual values: able to include the correct permissions. So some functionalities might not work properly. +\section3 Customizing Permissions + +Since Qt 6.8.1, it is possible to override the default permissions set +by Qt modules. This is useful if you need to define the same permissions +as used by a Qt module, but with additional or different attributes. + +To achieve this, you can manually define these permissions in the Android +manifest file, along with the \c {} placeholder. +Manually defined permissions take precedence over the same permissions added +by Qt modules, avoiding duplication. + \section2 Style Extraction Qt uses different methods to determine how Qt Widgets and Qt Quick Controls diff --git a/src/corelib/kernel/qpermissions.cpp b/src/corelib/kernel/qpermissions.cpp index 6d295970550..bfe8087d969 100644 --- a/src/corelib/kernel/qpermissions.cpp +++ b/src/corelib/kernel/qpermissions.cpp @@ -382,6 +382,8 @@ QT_PERMISSION_IMPL_COMMON(QMicrophonePermission) \l {QLocationPermission::Precise}{precise location}) and ensure that \c {BLUETOOTH_SCAN} permission doesn't have the \c {android:usesPermissionFlags="neverForLocation"} attribute set. + For setting and customizing permissions in the application manifest, + \l {Qt Permissions and Features}{see this guide}. \include permissions.qdocinc permission-metadata */ diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp index 6567b0dac0d..08bd4ccdf3f 100644 --- a/src/tools/androiddeployqt/main.cpp +++ b/src/tools/androiddeployqt/main.cpp @@ -1855,6 +1855,21 @@ bool updateAndroidManifest(Options &options) replacements[QStringLiteral("-- %%INSERT_VERSION_CODE%% --")] = options.versionCode; replacements[QStringLiteral("package=\"org.qtproject.example\"")] = "package=\"%1\""_L1.arg(options.packageName); + const QString androidManifestPath = options.outputDirectory + "/AndroidManifest.xml"_L1; + QFile androidManifestXml(androidManifestPath); + // User may have manually defined permissions in the AndroidManifest.xml + // Read these permissions in order to remove any duplicates, as otherwise the + // application build would fail. + if (androidManifestXml.exists() && androidManifestXml.open(QIODevice::ReadOnly)) { + QXmlStreamReader reader(&androidManifestXml); + while (!reader.atEnd()) { + reader.readNext(); + if (reader.isStartElement() && reader.name() == "uses-permission"_L1) + options.permissions.remove(QString(reader.attributes().value("android:name"_L1))); + } + androidManifestXml.close(); + } + QString permissions; for (auto [name, extras] : options.permissions.asKeyValueRange()) permissions += " \n"_L1.arg(name).arg(extras); @@ -1868,13 +1883,11 @@ bool updateAndroidManifest(Options &options) replacements[QStringLiteral("")] = features.trimmed(); - QString androidManifestPath = options.outputDirectory + "/AndroidManifest.xml"_L1; if (!updateFile(androidManifestPath, replacements)) return false; // read the package, min & target sdk API levels from manifest file. bool checkOldAndroidLabelString = false; - QFile androidManifestXml(androidManifestPath); if (androidManifestXml.exists()) { if (!androidManifestXml.open(QIODevice::ReadOnly)) { fprintf(stderr, "Cannot open %s for reading.\n", qPrintable(androidManifestPath));