From 7b0a3aa0dc45b0cae504343ec8b59bd19713419d Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 17 May 2024 12:33:19 +0200 Subject: [PATCH] Android: Simplify reading manifest files Change-Id: I8be86a26fd1f37ce59af7e5cdbdaf12519937da0 Reviewed-by: Alessandro Portale --- src/plugins/android/androidmanager.cpp | 115 +++++++++++-------------- 1 file changed, 50 insertions(+), 65 deletions(-) diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index 3d32654cee7..227b77f224e 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -34,6 +34,7 @@ #include using namespace Android::Internal; +using namespace Core; using namespace ProjectExplorer; using namespace Utils; @@ -60,9 +61,32 @@ public: using LibrariesMap = QMap; -static bool openXmlFile(QDomDocument &doc, const FilePath &fileName); -static bool openManifest(const Target *target, QDomDocument &doc); -static int parseMinSdk(const QDomElement &manifestElem); +static std::optional documentElement(const FilePath &fileName) +{ + QFile file(fileName.toString()); + if (!file.open(QIODevice::ReadOnly)) { + MessageManager::writeDisrupting(Tr::tr("Cannot open: %1").arg(fileName.toUserOutput())); + return {}; + } + QDomDocument doc; + if (!doc.setContent(file.readAll())) { + MessageManager::writeDisrupting(Tr::tr("Cannot parse: %1").arg(fileName.toUserOutput())); + return {}; + } + return doc.documentElement(); +} + +static int parseMinSdk(const QDomElement &manifestElem) +{ + const QDomElement usesSdk = manifestElem.firstChildElement("uses-sdk"); + if (!usesSdk.isNull() && usesSdk.hasAttribute("android:minSdkVersion")) { + bool ok; + int tmp = usesSdk.attribute("android:minSdkVersion").toInt(&ok); + if (ok) + return tmp; + } + return 0; +} static const ProjectNode *currentProjectNode(const Target *target) { @@ -71,30 +95,27 @@ static const ProjectNode *currentProjectNode(const Target *target) QString packageName(const Target *target) { - QDomDocument doc; - if (!openManifest(target, doc)) + const auto element = documentElement(AndroidManager::manifestPath(target)); + if (!element) return {}; - QDomElement manifestElem = doc.documentElement(); - return manifestElem.attribute(QLatin1String("package")); + return element->attribute("package"); } QString packageName(const FilePath &manifestFile) { - QDomDocument doc; - if (!openXmlFile(doc, manifestFile)) + const auto element = documentElement(manifestFile); + if (!element) return {}; - QDomElement manifestElem = doc.documentElement(); - return manifestElem.attribute(QLatin1String("package")); + return element->attribute("package"); } QString activityName(const Target *target) { - QDomDocument doc; - if (!openManifest(target, doc)) + const auto element = documentElement(AndroidManager::manifestPath(target)); + if (!element) return {}; - QDomElement activityElem = doc.documentElement().firstChildElement( - QLatin1String("application")).firstChildElement(QLatin1String("activity")); - return activityElem.attribute(QLatin1String("android:name")); + return element->firstChildElement("application").firstChildElement("activity") + .attribute("android:name"); } static FilePath manifestSourcePath(const Target *target) @@ -118,10 +139,11 @@ static FilePath manifestSourcePath(const Target *target) */ int minimumSDK(const Target *target) { - QDomDocument doc; - if (!openXmlFile(doc, manifestSourcePath(target))) + const auto element = documentElement(manifestSourcePath(target)); + if (!element) return minimumSDK(target->kit()); - const int minSdkVersion = parseMinSdk(doc.documentElement()); + + const int minSdkVersion = parseMinSdk(*element); if (minSdkVersion == 0) return AndroidManager::defaultMinimumSDK(QtSupport::QtKitAspect::qtVersion(target->kit())); return minSdkVersion; @@ -136,12 +158,12 @@ int minimumSDK(const Kit *kit) int minSdkVersion = -1; QtSupport::QtVersion *version = QtSupport::QtKitAspect::qtVersion(kit); if (version && version->targetDeviceTypes().contains(Constants::ANDROID_DEVICE_TYPE)) { - FilePath stockManifestFilePath = FilePath::fromUserInput( + const FilePath stockManifestFilePath = FilePath::fromUserInput( version->prefix().toString() + "/src/android/templates/AndroidManifest.xml"); - QDomDocument doc; - if (openXmlFile(doc, stockManifestFilePath)) { - minSdkVersion = parseMinSdk(doc.documentElement()); - } + + const auto element = documentElement(stockManifestFilePath); + if (element) + minSdkVersion = parseMinSdk(*element); } if (minSdkVersion == 0) return AndroidManager::defaultMinimumSDK(version); @@ -240,7 +262,7 @@ bool isQt5CmakeProject(const ProjectExplorer::Target *target) { const QtSupport::QtVersion *qt = QtSupport::QtKitAspect::qtVersion(target->kit()); const bool isQt5 = qt && qt->qtVersion() < QVersionNumber(6, 0, 0); - const Core::Context cmakeCtx = Core::Context(CMakeProjectManager::Constants::CMAKE_PROJECT_ID); + const Context cmakeCtx(CMakeProjectManager::Constants::CMAKE_PROJECT_ID); const bool isCmakeProject = (target->project()->projectContext() == cmakeCtx); return isQt5 && isCmakeProject; } @@ -371,7 +393,7 @@ bool skipInstallationAndPackageSteps(const Target *target) const Project *p = target->project(); - const Core::Context cmakeCtx = Core::Context(CMakeProjectManager::Constants::CMAKE_PROJECT_ID); + const Context cmakeCtx(CMakeProjectManager::Constants::CMAKE_PROJECT_ID); const bool isCmakeProject = p->projectContext() == cmakeCtx; if (isCmakeProject) return false; // CMake reports ProductType::Other for Android Apps @@ -538,43 +560,6 @@ QString androidNameForApiLevel(int x) } } -static void raiseError(const QString &reason) -{ - QMessageBox::critical(nullptr, Tr::tr("Error creating Android templates."), reason); -} - -static bool openXmlFile(QDomDocument &doc, const FilePath &fileName) -{ - QFile f(fileName.toString()); - if (!f.open(QIODevice::ReadOnly)) - return false; - - if (!doc.setContent(f.readAll())) { - raiseError(Tr::tr("Cannot parse \"%1\".").arg(fileName.toUserOutput())); - return false; - } - return true; -} - -static bool openManifest(const Target *target, QDomDocument &doc) -{ - return openXmlFile(doc, AndroidManager::manifestPath(target)); -} - -static int parseMinSdk(const QDomElement &manifestElem) -{ - QDomElement usesSdk = manifestElem.firstChildElement(QLatin1String("uses-sdk")); - if (usesSdk.isNull()) - return 0; - if (usesSdk.hasAttribute(QLatin1String("android:minSdkVersion"))) { - bool ok; - int tmp = usesSdk.attribute(QLatin1String("android:minSdkVersion")).toInt(&ok); - if (ok) - return tmp; - } - return 0; -} - void installQASIPackage(Target *target, const FilePath &packagePath) { const QStringList appAbis = AndroidManager::applicationAbis(target); @@ -589,7 +574,7 @@ void installQASIPackage(Target *target, const FilePath &packagePath) if (info.type == IDevice::Emulator) { deviceSerialNumber = AndroidAvdManager::startAvd(info.avdName); if (deviceSerialNumber.isEmpty()) - Core::MessageManager::writeDisrupting(Tr::tr("Starting Android virtual device failed.")); + MessageManager::writeDisrupting(Tr::tr("Starting Android virtual device failed.")); } QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber); @@ -600,7 +585,7 @@ void installQASIPackage(Target *target, const FilePath &packagePath) // TODO: Potential leak when the process is still running on Creator shutdown. QObject::connect(process, &Process::done, process, &QObject::deleteLater); } else { - Core::MessageManager::writeDisrupting( + MessageManager::writeDisrupting( Tr::tr("Android package installation failed.\n%1").arg(error)); } }