From fe9c7dcae03e6056e8074897a5d57df8a8a85c3f Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Sat, 7 Sep 2024 13:40:28 +0300 Subject: [PATCH] CMake:Android: add property QT_ANDROID_APP_ICON to set app icon This allows users to set an app icon directly from CMake without needing to manage a custom AndroidManifest.xml file. Fixes: QTBUG-92013 Change-Id: Ic2f44978697d0f4833bde7f66630943d3032e982 Reviewed-by: Alexey Edelev --- src/android/templates/AndroidManifest.xml | 1 + .../android-manifest-file-configuration.qdoc | 7 ++- src/corelib/Qt6AndroidMacros.cmake | 4 ++ .../doc/src/cmake/cmake-properties.qdoc | 45 +++++++++++++++++++ ..._android_generate_deployment_settings.qdoc | 1 + src/tools/androiddeployqt/main.cpp | 16 +++++++ 6 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml index 21ceaacc2e4..a55a80f94ef 100644 --- a/src/android/templates/AndroidManifest.xml +++ b/src/android/templates/AndroidManifest.xml @@ -15,6 +15,7 @@ android:name="org.qtproject.qt.android.bindings.QtApplication" android:hardwareAccelerated="true" android:label="-- %%INSERT_APP_NAME%% --" + android:icon="-- %%INSERT_APP_ICON%% --" android:requestLegacyExternalStorage="true" android:allowBackup="true" android:fullBackupOnly="false"> 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 a70ab1d0baf..4cf03564ee2 100644 --- a/src/android/templates/doc/src/android-manifest-file-configuration.qdoc +++ b/src/android/templates/doc/src/android-manifest-file-configuration.qdoc @@ -70,7 +70,7 @@ Qt sets the following manifest configuration by default: default values are \c anyDensity, \c largeScreens, \c normalScreens, and \c smallScreens. \row - \li {1, 6} \l {Android: App Manifest }{} + \li {1, 7} \l {Android: App Manifest }{} \li android:name \li The application class name. Default value is \c {org.qtproject.qt.android.bindings.QtApplication}. @@ -78,6 +78,11 @@ Qt sets the following manifest configuration by default: \li android:label \li The application name label. Default value is the Qt project's target name. This can be set using \l {QT_ANDROID_APP_NAME}. +\row + \li android:icon + \li The application icon as a reference to a drawable or mipmap resource. This + tag is not used unless set using \l {QT_ANDROID_APP_ICON} or set manually + in the \c {AndroidManifest.xml}. \row \li android:hardwareAccelerated \li Sets hardware acceleration preference. The default value is \c true. diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake index 8fd64858354..c5896adfcc4 100644 --- a/src/corelib/Qt6AndroidMacros.cmake +++ b/src/corelib/Qt6AndroidMacros.cmake @@ -225,6 +225,10 @@ function(qt6_android_generate_deployment_settings target) _qt_internal_add_android_deployment_property(file_contents "android-app-name" ${target} "QT_ANDROID_APP_NAME") + # app icon + _qt_internal_add_android_deployment_property(file_contents "android-app-icon" + ${target} "QT_ANDROID_APP_ICON") + # version code _qt_internal_add_android_deployment_property(file_contents "android-version-code" ${target} "QT_ANDROID_VERSION_CODE") diff --git a/src/corelib/doc/src/cmake/cmake-properties.qdoc b/src/corelib/doc/src/cmake/cmake-properties.qdoc index 4ca6a8448ce..661c14bdce3 100644 --- a/src/corelib/doc/src/cmake/cmake-properties.qdoc +++ b/src/corelib/doc/src/cmake/cmake-properties.qdoc @@ -328,6 +328,51 @@ set_target_properties(${target} PROPERTIES \sa {QT_ANDROID_PACKAGE_NAME} */ +/*! +\page cmake-target-property-qt-android-app-icon.html +\ingroup cmake-properties-qtcore +\ingroup cmake-target-properties-qtcore + +\title QT_ANDROID_APP_ICON +\target cmake-target-property-QT_ANDROID_APP_ICON +\ingroup cmake-android-manifest-properties + +\summary {The Android app's icon resource name.} + +\cmakepropertysince 6.9 +\cmakepropertyandroidonly + +Specifies the app's icon name as an Android drawable or mipmap reference. +This only works if the \c {AndroidManifest.xml} file contains the placeholder +or when the \c {AndroidManifest.xml} is managed by Qt. + +\badcode + +\endcode + +You can use this property as follows: + +\badcode +set_target_properties(${target} PROPERTIES + QT_ANDROID_APP_ICON "@mipmap/ic_launcher" +) +\endcode + +Or using drawables: + +\badcode +set_target_properties(${target} PROPERTIES + QT_ANDROID_APP_ICON "@drawable/ic_launcher" +) +\endcode + +\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()} +*/ + /*! \page cmake-target-property-qt-android-version-code.html \ingroup cmake-properties-qtcore diff --git a/src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc b/src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc index 6781e5e0934..b873ec0f9d7 100644 --- a/src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc +++ b/src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc @@ -65,6 +65,7 @@ how to accomplish this. \li \l{cmake-target-property-QT_ANDROID_TARGET_SDK_VERSION}{QT_ANDROID_TARGET_SDK_VERSION} \li \l{cmake-target-property-QT_ANDROID_PACKAGE_NAME}{QT_ANDROID_PACKAGE_NAME} \li \l{cmake-target-property-QT_ANDROID_APP_NAME}{QT_ANDROID_APP_NAME} +\li \l{cmake-target-property-QT_ANDROID_APP_ICON}{QT_ANDROID_APP_ICON} \li \l{cmake-target-property-QT_ANDROID_VERSION_NAME}{QT_ANDROID_VERSION_NAME} \li \l{cmake-target-property-QT_ANDROID_VERSION_CODE}{QT_ANDROID_VERSION_CODE} \li \l{cmake-target-property-QT_QML_IMPORT_PATH}{QT_QML_IMPORT_PATH} diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp index c851ec27502..6e3a174ef38 100644 --- a/src/tools/androiddeployqt/main.cpp +++ b/src/tools/androiddeployqt/main.cpp @@ -192,6 +192,7 @@ struct Options QString systemLibsPath; QString packageName; QString appName; + QString appIcon; QStringList extraLibs; QHash archExtraLibs; QStringList extraPlugins; @@ -1380,6 +1381,12 @@ bool readInputFile(Options *options) options->appName = options->applicationBinary; } + { + const QJsonValue androidAppIcon = jsonObject.value("android-app-icon"_L1); + if (!androidAppIcon.isUndefined()) + options->appIcon = androidAppIcon.toString(); + } + { using ItFlag = QDirListing::IteratorFlag; const QJsonValue deploymentDependencies = jsonObject.value("deployment-dependencies"_L1); @@ -1701,6 +1708,11 @@ bool updateFile(const QString &fileName, const QHash &replacem return false; } + // Remove leftover empty lines after replacements, for example, + // in case of setting the app icon. + QRegularExpression emptyLinesRegex("\\n\\s+\\n"_L1); + contents = QString::fromUtf8(contents).replace(emptyLinesRegex, "\n"_L1).toUtf8(); + inputFile.write(contents); } @@ -1859,6 +1871,10 @@ 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 iconAttribute = "android:icon=\"%1\""_L1; + replacements[iconAttribute.arg("-- %%INSERT_APP_ICON%% --"_L1)] = options.appIcon.isEmpty() ? + ""_L1 : iconAttribute.arg(options.appIcon); + const QString androidManifestPath = options.outputDirectory + "/AndroidManifest.xml"_L1; QFile androidManifestXml(androidManifestPath); // User may have manually defined permissions in the AndroidManifest.xml