diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp index a8ae7d14403..6485b93990d 100644 --- a/src/plugins/android/androidbuildapkstep.cpp +++ b/src/plugins/android/androidbuildapkstep.cpp @@ -71,6 +71,7 @@ static Q_LOGGING_CATEGORY(buildapkstepLog, "qtc.android.build.androidbuildapkste const char KeystoreLocationKey[] = "KeystoreLocation"; const char BuildTargetSdkKey[] = "BuildTargetSdk"; +const char BuildToolsVersionKey[] = "BuildToolsVersion"; const char VerboseOutputKey[] = "VerboseOutput"; class PasswordInputDialog : public QDialog @@ -167,8 +168,29 @@ QWidget *AndroidBuildApkWidget::createApplicationGroup() const QString sdk = targetSDKComboBox->itemText(idx); m_step->setBuildTargetSdk(sdk); }); + targetSDKComboBox->setCurrentIndex(targets.indexOf(m_step->buildTargetSdk())); + + const QList buildToolsVersions = Utils::transform( + AndroidConfigurations::sdkManager()->filteredBuildTools(minApiSupported), + [](const BuildTools *pkg) { + return pkg->revision(); + }); + + auto buildToolsSdkComboBox = new QComboBox(); + for (const QVersionNumber &version : buildToolsVersions) + buildToolsSdkComboBox->addItem(version.toString(), QVariant::fromValue(version)); + connect(buildToolsSdkComboBox, &QComboBox::activated, this, + [this, buildToolsSdkComboBox](int idx) { + m_step->setBuildToolsVersion(buildToolsSdkComboBox->itemData(idx).value()); + }); + + const int initIdx = (m_step->buildToolsVersion().majorVersion() < 1) + ? buildToolsVersions.indexOf(buildToolsVersions.last()) + : buildToolsVersions.indexOf(m_step->buildToolsVersion()); + buildToolsSdkComboBox->setCurrentIndex(initIdx); auto formLayout = new QFormLayout(group); + formLayout->addRow(Tr::tr("Android build-tools version:"), buildToolsSdkComboBox); formLayout->addRow(Tr::tr("Android build platform SDK:"), targetSDKComboBox); auto createAndroidTemplatesButton = new QPushButton(Tr::tr("Create Templates")); @@ -540,6 +562,8 @@ bool AndroidBuildApkStep::init() return false; } + updateBuildToolsVersionInJsonFile(); + QStringList arguments = {"--input", m_inputFile.toString(), "--output", outputDir.toString(), "--android-platform", m_buildTargetSdk, @@ -841,11 +865,28 @@ void AndroidBuildApkStep::reportWarningOrError(const QString &message, Task::Tas TaskHub::addTask(BuildSystemTask(type, message)); } +void AndroidBuildApkStep::updateBuildToolsVersionInJsonFile() +{ + expected_str contents = m_inputFile.fileContents(); + if (!contents) + return; + + QRegularExpression regex(QLatin1String("\"sdkBuildToolsRevision\":.\"[0-9.]+\"")); + QRegularExpressionMatch match = regex.match(QString::fromUtf8(contents.value())); + const QString version = buildToolsVersion().toString(); + if (match.hasMatch() && !version.isEmpty()) { + const auto newStr = QLatin1String("\"sdkBuildToolsRevision\": \"%1\"").arg(version).toUtf8(); + contents->replace(match.captured(0).toUtf8(), newStr); + m_inputFile.writeFileContents(contents.value()); + } +} + bool AndroidBuildApkStep::fromMap(const QVariantMap &map) { m_keystorePath = FilePath::fromSettings(map.value(KeystoreLocationKey)); m_signPackage = false; // don't restore this m_buildTargetSdk = map.value(BuildTargetSdkKey).toString(); + m_buildToolsVersion = QVersionNumber::fromString(map.value(BuildToolsVersionKey).toString()); if (m_buildTargetSdk.isEmpty()) { m_buildTargetSdk = AndroidConfig::apiLevelNameFor(AndroidConfigurations:: sdkManager()->latestAndroidSdkPlatform()); @@ -859,6 +900,7 @@ QVariantMap AndroidBuildApkStep::toMap() const QVariantMap map = ProjectExplorer::AbstractProcessStep::toMap(); map.insert(KeystoreLocationKey, m_keystorePath.toSettings()); map.insert(BuildTargetSdkKey, m_buildTargetSdk); + map.insert(BuildToolsVersionKey, m_buildToolsVersion.toString()); map.insert(VerboseOutputKey, m_verbose); return map; } @@ -878,6 +920,16 @@ void AndroidBuildApkStep::setBuildTargetSdk(const QString &sdk) m_buildTargetSdk = sdk; } +QVersionNumber AndroidBuildApkStep::buildToolsVersion() const +{ + return m_buildToolsVersion; +} + +void AndroidBuildApkStep::setBuildToolsVersion(const QVersionNumber &version) +{ + m_buildToolsVersion = version; +} + void AndroidBuildApkStep::stdError(const QString &output) { QString newOutput = output; diff --git a/src/plugins/android/androidbuildapkstep.h b/src/plugins/android/androidbuildapkstep.h index 944a7e1e7c0..89ddd208a54 100644 --- a/src/plugins/android/androidbuildapkstep.h +++ b/src/plugins/android/androidbuildapkstep.h @@ -4,11 +4,11 @@ #pragma once -#include "android_global.h" - #include #include +#include + QT_BEGIN_NAMESPACE class QAbstractItemModel; QT_END_NAMESPACE @@ -52,6 +52,9 @@ public: QString buildTargetSdk() const; void setBuildTargetSdk(const QString &sdk); + QVersionNumber buildToolsVersion() const; + void setBuildToolsVersion(const QVersionNumber &version); + QVariant data(Utils::Id id) const override; private: @@ -68,6 +71,7 @@ private: void stdError(const QString &output); void reportWarningOrError(const QString &message, ProjectExplorer::Task::TaskType type); + void updateBuildToolsVersionInJsonFile(); bool m_buildAAB = false; bool m_signPackage = false; @@ -76,6 +80,7 @@ private: bool m_openPackageLocationForRun = false; bool m_addDebugger = true; QString m_buildTargetSdk; + QVersionNumber m_buildToolsVersion; Utils::FilePath m_keystorePath; QString m_keystorePasswd; diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp index 6a05ff1752a..486acf59848 100644 --- a/src/plugins/android/androidsdkmanager.cpp +++ b/src/plugins/android/androidsdkmanager.cpp @@ -376,6 +376,20 @@ SdkPlatformList AndroidSdkManager::filteredSdkPlatforms(int minApiLevel, return result; } +BuildToolsList AndroidSdkManager::filteredBuildTools(int minApiLevel, + AndroidSdkPackage::PackageState state) +{ + const AndroidSdkPackageList list = m_d->filteredPackages(state, + AndroidSdkPackage::BuildToolsPackage); + BuildToolsList result; + for (AndroidSdkPackage *p : list) { + auto platform = dynamic_cast(p); + if (platform && platform->revision().majorVersion() >= minApiLevel) + result << platform; + } + return result; +} + void AndroidSdkManager::reloadPackages(bool forceReload) { m_d->refreshSdkPackages(forceReload); diff --git a/src/plugins/android/androidsdkmanager.h b/src/plugins/android/androidsdkmanager.h index b56dcec8779..7fdbee362f6 100644 --- a/src/plugins/android/androidsdkmanager.h +++ b/src/plugins/android/androidsdkmanager.h @@ -54,6 +54,9 @@ public: SdkPlatformList filteredSdkPlatforms(int minApiLevel, AndroidSdkPackage::PackageState state = AndroidSdkPackage::Installed); + BuildToolsList filteredBuildTools(int minApiLevel, + AndroidSdkPackage::PackageState state + = AndroidSdkPackage::Installed); void reloadPackages(bool forceReload = false); bool isBusy() const; diff --git a/src/plugins/android/androidsdkpackage.h b/src/plugins/android/androidsdkpackage.h index eb8eca08bea..f2926962d25 100644 --- a/src/plugins/android/androidsdkpackage.h +++ b/src/plugins/android/androidsdkpackage.h @@ -145,6 +145,7 @@ public: bool isValid() const override; PackageType type() const override; }; +using BuildToolsList = QList; class PlatformTools : public AndroidSdkPackage {