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 <!-- %%INSERT_PERMISSIONS --> 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 <assam.boudjelthia@qt.io>
(cherry picked from commit 2c1506b1bd551249852d43250d7919f5e3ac7ac1)
This commit is contained in:
Juha Vuolle 2024-08-21 15:11:27 +03:00
parent 0df76339f0
commit cba3c30047
3 changed files with 28 additions and 2 deletions

View File

@ -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 {<!-- %%INSERT_PERMISSIONS -->} 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

View File

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

View File

@ -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 += " <uses-permission android:name=\"%1\" %2 />\n"_L1.arg(name).arg(extras);
@ -1868,13 +1883,11 @@ bool updateAndroidManifest(Options &options)
replacements[QStringLiteral("<!-- %%INSERT_FEATURES -->")] = 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));