Android: Simplify reading manifest files

Change-Id: I8be86a26fd1f37ce59af7e5cdbdaf12519937da0
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Jarek Kobus
2024-05-17 12:33:19 +02:00
parent 3380c3f968
commit 7b0a3aa0dc

View File

@@ -34,6 +34,7 @@
#include <QVersionNumber>
using namespace Android::Internal;
using namespace Core;
using namespace ProjectExplorer;
using namespace Utils;
@@ -60,9 +61,32 @@ public:
using LibrariesMap = QMap<QString, Library>;
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<QDomElement> 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));
}
}