summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAssam Boudjelthia <[email protected]>2024-05-10 14:45:50 +0300
committerAssam Boudjelthia <[email protected]>2024-05-16 16:40:55 +0300
commitfbb35cdb0b2c302e5963900bf59bc91a7c21765a (patch)
treec99a1c62611cccdabe03e9d4c34d6476678a3f7a
parentc9ddc4b8e17fac10d2f25fe21c09bdd734513ac6 (diff)
Android:CMake: Add QT_ANDROID_PACKAGE_NAME property
Allow setting the package name directly from CMake properties. If the package name is not set manually under AndroidManifest.xml nor build.gradle, then the value set by this property is used. The value is passed to build.gradle as "namespace" which is the way to set the package name after AGP 7.4 instead of AndroidManifest.xml "package" attribute. Task-number: QTBUG-106907 Change-Id: I94bd73c294d751eabfd96c0a10a6b3ff270d8137 Reviewed-by: Tinja Paavoseppä <[email protected]>
-rw-r--r--doc/global/externalsites/external-resources.qdoc4
-rw-r--r--src/corelib/Qt6AndroidMacros.cmake4
-rw-r--r--src/corelib/doc/src/cmake/cmake-properties.qdoc49
-rw-r--r--src/corelib/doc/src/cmake/qt_android_generate_deployment_settings.qdoc1
-rw-r--r--src/tools/androiddeployqt/main.cpp63
-rw-r--r--tests/auto/other/android_deployment_settings/CMakeLists.txt2
-rw-r--r--tests/auto/other/android_deployment_settings/tst_android_deployment_settings.cpp2
7 files changed, 109 insertions, 16 deletions
diff --git a/doc/global/externalsites/external-resources.qdoc b/doc/global/externalsites/external-resources.qdoc
index 272c73b3b01..0dcea08a53a 100644
--- a/doc/global/externalsites/external-resources.qdoc
+++ b/doc/global/externalsites/external-resources.qdoc
@@ -33,6 +33,10 @@
\title Android: Tagged Pointers
*/
/*!
+ \externalpage https://developer.android.com/build/configure-app-module
+ \title Android: Configure the app module
+*/
+/*!
\externalpage https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl
\title iOS: canOpenURL:
*/
diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake
index 96b24ee680e..3e96130b85a 100644
--- a/src/corelib/Qt6AndroidMacros.cmake
+++ b/src/corelib/Qt6AndroidMacros.cmake
@@ -217,6 +217,10 @@ function(qt6_android_generate_deployment_settings target)
${target} "_qt_android_native_package_source_dir")
# version code
+ _qt_internal_add_android_deployment_property(file_contents "android-package-name"
+ ${target} "QT_ANDROID_PACKAGE_NAME")
+
+ # 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 8fe2b0e88fd..3740b29612a 100644
--- a/src/corelib/doc/src/cmake/cmake-properties.qdoc
+++ b/src/corelib/doc/src/cmake/cmake-properties.qdoc
@@ -245,6 +245,55 @@ CMake will attempt to use the latest installed version.
*/
/*!
+\page cmake-target-property-qt-android-package-name.html
+\ingroup cmake-properties-qtcore
+\ingroup cmake-target-properties-qtcore
+
+\title QT_ANDROID_PACKAGE_NAME
+\target cmake-target-property-QT_ANDROID_PACKAGE_NAME
+
+\summary {The app's package name.}
+
+\cmakepropertysince 6.8
+\preliminarycmakeproperty
+\cmakepropertyandroidonly
+
+Specifies the app's package name. This is usually a unique dot separated
+name for the app, that will be used to identify the app on devices or in
+the Play Store. For example, "org.qtproject.example.gallery".
+
+The package name set by this property is passed to the \c build.gradle file
+as a \c namespace property, instead of \c AndroidManifest.xml, since the
+latter is deprecated since Android Gradle Plugin 7.4.
+
+The package name considers some words or characters as illegal and the build
+will clean such names if any is encountered. An underscore (\c _) either replaces
+illegal characters or is appended to illegal words.
+
+\list
+ \li Allowed characters: alphanumeric, an underscore or a dot [a-zA-Z0-9_.].
+ \li Illegal words: abstract, continue, for, new, switch, assert, default,
+ if, package, synchronized, boolean, do, goto, private, this, break,
+ double, implements, protected, throw, byte, else, import, public,
+ throws, case, enum, instanceof, return, transient, catch, extends,
+ int, short, try, char, final, interface, static, void, class, finally,
+ long, strictfp, volatile, const, float, native, super, while.
+\endlist
+
+The default package name for Qt for Android apps is \c org.qtproject.example.<target_name>.
+
+\note Setting the package name manually in \c build.gradle (via
+\c namespace property) takes precedence over \c AndroidManifest.xml
+(via \c package attribute), and the latter also takes precedence over
+this property.
+
+For more information, see Android's
+\l{Android: Configure the app module}{configure the app module}.
+
+\sa{qt6_android_generate_deployment_settings}{qt_android_generate_deployment_settings()}
+*/
+
+/*!
\page cmake-target-property-qt-android-version-code.html
\ingroup cmake-properties-qtcore
\ingroup cmake-target-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 5a7bbdc33f5..daa3680070a 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
@@ -63,6 +63,7 @@ how to accomplish this.
\li \l{cmake-target-property-QT_ANDROID_MIN_SDK_VERSION}{QT_ANDROID_MIN_SDK_VERSION}
\li \l{cmake-target-property-QT_ANDROID_PACKAGE_SOURCE_DIR}{QT_ANDROID_PACKAGE_SOURCE_DIR}
\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_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 4ff57373810..da5c2c8c775 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -802,18 +802,25 @@ GradleBuildConfigs gradleBuildConfigs(const QString &path)
return configs;
}
-QString cleanPackageName(QString packageName)
+QString cleanPackageName(QString packageName, bool *cleaned = nullptr)
{
auto isLegalChar = [] (QChar c) -> bool {
ushort ch = c.unicode();
return (ch >= '0' && ch <= '9') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= 'a' && ch <= 'z') ||
- ch == '.';
+ ch == '.' || ch == '_';
};
+
+ if (cleaned)
+ *cleaned = false;
+
for (QChar &c : packageName) {
- if (!isLegalChar(c))
+ if (!isLegalChar(c)) {
c = u'_';
+ if (cleaned)
+ *cleaned = true;
+ }
}
static QStringList keywords;
@@ -848,12 +855,16 @@ QString cleanPackageName(QString packageName)
QChar c = word[0];
if ((c >= u'0' && c <= u'9') || c == u'_') {
packageName.insert(index + 1, u'a');
+ if (cleaned)
+ *cleaned = true;
index = next + 1;
continue;
}
}
if (keywords.contains(word)) {
packageName.insert(next, "_"_L1);
+ if (cleaned)
+ *cleaned = true;
index = next + 1;
} else {
index = next;
@@ -885,26 +896,29 @@ QString detectLatestAndroidPlatform(const QString &sdkPath)
QString extractPackageName(Options *options)
{
- QString packageName;
+ {
+ const QString gradleBuildFile = options->androidSourceDirectory + "/build.gradle"_L1;
+ QString packageName = gradleBuildConfigs(gradleBuildFile).appNamespace;
+
+ if (!packageName.isEmpty() && packageName != "androidPackageName"_L1)
+ return packageName;
+ }
+
QFile androidManifestXml(options->androidSourceDirectory + "/AndroidManifest.xml"_L1);
if (androidManifestXml.open(QIODevice::ReadOnly)) {
QXmlStreamReader reader(&androidManifestXml);
while (!reader.atEnd()) {
reader.readNext();
- if (reader.isStartElement() && reader.name() == "manifest"_L1)
- packageName = reader.attributes().value("package"_L1).toString();
+ if (reader.isStartElement() && reader.name() == "manifest"_L1) {
+ QString packageName = reader.attributes().value("package"_L1).toString();
+ if (!packageName.isEmpty() && packageName != "org.qtproject.example"_L1)
+ return packageName;
+ break;
+ }
}
}
- if (packageName.isEmpty()) {
- const QString gradleBuildFile = options->androidSourceDirectory + "/build.gradle"_L1;
- packageName = gradleBuildConfigs(gradleBuildFile).appNamespace;
- }
-
- if (packageName.isEmpty() || packageName == "androidPackageName"_L1)
- packageName = "org.qtproject.example.%1"_L1.arg(options->applicationBinary);
-
- return cleanPackageName(packageName);
+ return QString();
}
bool parseCmakeBoolean(const QJsonValue &value)
@@ -1302,6 +1316,24 @@ bool readInputFile(Options *options)
}
{
+ const QJsonValue androidPackageName = jsonObject.value("android-package-name"_L1);
+ const QString extractedPackageName = extractPackageName(options);
+ if (!extractedPackageName.isEmpty())
+ options->packageName = extractedPackageName;
+ else if (!androidPackageName.isUndefined())
+ options->packageName = androidPackageName.toString();
+ else
+ options->packageName = "org.qtproject.example.%1"_L1.arg(options->applicationBinary);
+
+ bool cleaned;
+ options->packageName = cleanPackageName(options->packageName, &cleaned);
+ if (cleaned) {
+ fprintf(stderr, "Warning: Package name contained illegal characters and was cleaned "
+ "to \"%s\"\n", qPrintable(options->packageName));
+ }
+ }
+
+ {
using ItFlag = QDirListing::IteratorFlag;
const QJsonValue deploymentDependencies = jsonObject.value("deployment-dependencies"_L1);
if (!deploymentDependencies.isUndefined()) {
@@ -1358,7 +1390,6 @@ bool readInputFile(Options *options)
options->isZstdCompressionEnabled = zstdCompressionFlag.toBool();
}
}
- options->packageName = extractPackageName(options);
return true;
}
diff --git a/tests/auto/other/android_deployment_settings/CMakeLists.txt b/tests/auto/other/android_deployment_settings/CMakeLists.txt
index f2ba1353282..9ef457189a6 100644
--- a/tests/auto/other/android_deployment_settings/CMakeLists.txt
+++ b/tests/auto/other/android_deployment_settings/CMakeLists.txt
@@ -30,6 +30,7 @@ set_target_properties(${target} PROPERTIES
QT_ANDROID_SDK_BUILD_TOOLS_REVISION "23.0.2"
QT_ANDROID_MIN_SDK_VERSION "1"
QT_ANDROID_TARGET_SDK_VERSION "2"
+ QT_ANDROID_PACKAGE_NAME "org.qtproject.android_deployment_settings_test"
QT_ANDROID_DEPLOYMENT_DEPENDENCIES "dep1.so;dep2.so;dep3.so"
QT_ANDROID_DEPLOYMENT_SETTINGS_FILE "attempt_to_rewrite.json"
QT_ANDROID_EXTRA_LIBS
@@ -53,6 +54,7 @@ set_target_properties(${target} PROPERTIES
QT_ANDROID_SDK_BUILD_TOOLS_REVISION "23.0.2"
QT_ANDROID_MIN_SDK_VERSION "1"
QT_ANDROID_TARGET_SDK_VERSION "2"
+ QT_ANDROID_PACKAGE_NAME "org.qtproject.android_deployment_settings_test"
QT_ANDROID_DEPLOYMENT_DEPENDENCIES "dep1.so;dep2.so;dep3.so"
QT_ANDROID_EXTRA_LIBS
"some/path/to/lib1.so;some/path\\to/lib2.so;some\\path\\to\\lib3.so;some/path/to/lib4.so"
diff --git a/tests/auto/other/android_deployment_settings/tst_android_deployment_settings.cpp b/tests/auto/other/android_deployment_settings/tst_android_deployment_settings.cpp
index d68d08b58eb..f8428aaf43c 100644
--- a/tests/auto/other/android_deployment_settings/tst_android_deployment_settings.cpp
+++ b/tests/auto/other/android_deployment_settings/tst_android_deployment_settings.cpp
@@ -76,6 +76,8 @@ void tst_android_deployment_settings::DeploymentSettings_data()
<< "1";
QTest::newRow("android-target-sdk-version") << "android-target-sdk-version"
<< "2";
+ QTest::newRow("android-package-name") << "android-package-name"
+ << "org.qtproject.android_deployment_settings_test";
}
void tst_android_deployment_settings::DeploymentSettings()