aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAssam Boudjelthia <[email protected]>2020-11-28 15:44:37 +0200
committerAssam Boudjelthia <[email protected]>2022-03-17 20:45:07 +0000
commit5454dda2492f388f17e842f50e7c0731772c647f (patch)
tree034d62bdb5033db604cb2241ca2a4773f24e07ca
parent188544052c17879cf711d1d2e20a3ae59d4f714f (diff)
Android: keep up with sdk tools changing folder structure
The cmdline-tools package used to have the folder structure "tools/bin". However, latest packages are using the structure "cmdline-tools/bin". And since subsequent updates we are installing "cmdline-tools;latest" package, it will be put in "cmdline-tools/latest" folder, so we cannot extract to that path, or otherwise sdkmanager will complain that the path is in use. Currently we extract it and put it under the SDK path, then use it to install the essential packages, then it won't be used at all. This patch changes that by extracting the downloaded package into a temporary location, and use sdkmanager from there directly. Also, this patch updates the links to the cmdline-tools along the way. Fixes: QTCREATORBUG-27174 Change-Id: I1f5d0e38f5a026631e8a3852821d85a69d543c32 Reviewed-by: Alessandro Portale <[email protected]>
-rw-r--r--share/qtcreator/android/sdk_definitions.json12
-rw-r--r--src/plugins/android/androidbuildapkstep.cpp2
-rw-r--r--src/plugins/android/androidconfigurations.cpp92
-rw-r--r--src/plugins/android/androidconfigurations.h6
-rw-r--r--src/plugins/android/androidconstants.h3
-rw-r--r--src/plugins/android/androidsdkdownloader.cpp20
-rw-r--r--src/plugins/android/androidsdkdownloader.h4
-rw-r--r--src/plugins/android/androidsdkmanager.cpp24
-rw-r--r--src/plugins/android/androidsettingswidget.cpp9
9 files changed, 116 insertions, 56 deletions
diff --git a/share/qtcreator/android/sdk_definitions.json b/share/qtcreator/android/sdk_definitions.json
index 56ac6b4f47d..76e67c9fced 100644
--- a/share/qtcreator/android/sdk_definitions.json
+++ b/share/qtcreator/android/sdk_definitions.json
@@ -1,12 +1,12 @@
{
"common": {
"sdk_tools_url": {
- "linux": "https://dl.google.com/android/repository/commandlinetools-linux-6609375_latest.zip",
- "linux_sha256": "89f308315e041c93a37a79e0627c47f21d5c5edbe5e80ea8dc0aac8a649e0e92",
- "windows": "https://dl.google.com/android/repository/commandlinetools-win-6609375_latest.zip",
- "windows_sha256": "40bba20275180194bebf89bb58c74d712bb93cc401f36bd2f8f32383acf9826c",
- "mac": "https://dl.google.com/android/repository/commandlinetools-mac-6609375_latest.zip",
- "mac_sha256": "2c3822db1c916655223e5ee8ce0fbf6b73d0b99012045c9dc8eaa6a5736c0c55"
+ "linux": "https://dl.google.com/android/repository/commandlinetools-linux-8092744_latest.zip",
+ "linux_sha256": "d71f75333d79c9c6ef5c39d3456c6c58c613de30e6a751ea0dbd433e8f8b9cbf",
+ "windows": "https://dl.google.com/android/repository/commandlinetools-win-8092744_latest.zip",
+ "windows_sha256": "5de99ed67cb2e30fe443baf8b282d1b0b6247d0c25c6d888a7e8657b3b35c281",
+ "mac": "https://dl.google.com/android/repository/commandlinetools-mac-8092744_latest.zip",
+ "mac_sha256": "1de25523d595198d29666f9976eed65d99bbc5e4a3e8e48e5d6c98bb7e9030cc"
},
"sdk_essential_packages": {
"default": ["platform-tools", "platforms;android-31", "cmdline-tools;latest"],
diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp
index 5464c09c83e..b53cf3b6f7a 100644
--- a/src/plugins/android/androidbuildapkstep.cpp
+++ b/src/plugins/android/androidbuildapkstep.cpp
@@ -535,7 +535,7 @@ bool AndroidBuildApkStep::init()
const QVersionNumber sdkToolsVersion = AndroidConfigurations::currentConfig().sdkToolsVersion();
if (sdkToolsVersion >= QVersionNumber(25, 3, 0)
- || AndroidConfigurations::currentConfig().isCmdlineSdkToolsInstalled()) {
+ && AndroidConfigurations::currentConfig().preCmdlineSdkToolsInstalled()) {
if (!version->sourcePath().pathAppended("src/3rdparty/gradle").exists()) {
const QString error
= tr("The installed SDK tools version (%1) does not include Gradle "
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index 15f525a5592..c3702fa2763 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -474,9 +474,12 @@ QString AndroidConfig::apiLevelNameFor(const SdkPlatform *platform)
QString("android-%1").arg(platform->apiLevel()) : "";
}
-bool AndroidConfig::isCmdlineSdkToolsInstalled() const
+// This is checking for the SDK tools [*] that were deprecated in favor of
+// the command-line tools.
+// See https://developer.android.com/studio/releases/sdk-tools
+bool AndroidConfig::preCmdlineSdkToolsInstalled() const
{
- QString toolPath("cmdline-tools/latest/bin/sdkmanager");
+ QString toolPath("tools/bin/sdkmanager");
if (HostOsInfo::isWindowsHost())
toolPath += ANDROID_BAT_SUFFIX;
@@ -491,38 +494,51 @@ FilePath AndroidConfig::adbToolPath() const
FilePath AndroidConfig::emulatorToolPath() const
{
QString relativePath = "emulator/emulator";
- if (sdkToolsVersion() < QVersionNumber(25, 3, 0) && !isCmdlineSdkToolsInstalled())
+ if (sdkToolsVersion() < QVersionNumber(25, 3, 0) && preCmdlineSdkToolsInstalled())
relativePath = "tools/emulator";
return m_sdkLocation / (relativePath + QTC_HOST_EXE_SUFFIX);
}
FilePath AndroidConfig::sdkManagerToolPath() const
{
- QStringList sdkmanagerPaths = {"cmdline-tools/latest/bin/sdkmanager",
- "tools/bin/sdkmanager"};
+ const QStringList sdkmanagerPaths = {
+ QString(Constants::cmdlineToolsName).append("/latest/bin/sdkmanager"),
+ "tools/bin/sdkmanager"};
- for (QString &toolPath : sdkmanagerPaths) {
+ for (const QString &toolPath : sdkmanagerPaths) {
+ QString toolPathWithSuffix = toolPath;
if (HostOsInfo::isWindowsHost())
- toolPath += ANDROID_BAT_SUFFIX;
-
- const FilePath sdkmanagerPath = m_sdkLocation / toolPath;
+ toolPathWithSuffix += ANDROID_BAT_SUFFIX;
+ const FilePath sdkmanagerPath = m_sdkLocation / toolPathWithSuffix;
if (sdkmanagerPath.exists())
return sdkmanagerPath;
}
+ // If it's a first time install use the path of Constants::cmdlineToolsName temporary download
+ const FilePath tmpSdkPath = m_temporarySdkToolsPath;
+ if (!tmpSdkPath.isEmpty()) {
+ QString suffix = "bin/sdkmanager";
+ if (HostOsInfo::isWindowsHost())
+ suffix += ANDROID_BAT_SUFFIX;
+ const FilePath tmpsdkManagerPath = tmpSdkPath.pathAppended(suffix);
+ if (tmpsdkManagerPath.exists())
+ return tmpsdkManagerPath;
+ }
+
return FilePath();
}
FilePath AndroidConfig::avdManagerToolPath() const
{
- QStringList sdkmanagerPaths = {"cmdline-tools/latest/bin/avdmanager",
- "tools/bin/avdmanager"};
+ const QStringList sdkmanagerPaths = {
+ QString(Constants::cmdlineToolsName).append("/latest/bin/avdmanager"),
+ "tools/bin/avdmanager"};
- for (QString &toolPath : sdkmanagerPaths) {
+ for (const QString &toolPath : sdkmanagerPaths) {
+ QString toolPathWithSuffix = toolPath;
if (HostOsInfo::isWindowsHost())
- toolPath += ANDROID_BAT_SUFFIX;
-
- const FilePath sdkmanagerPath = m_sdkLocation / toolPath;
+ toolPathWithSuffix += ANDROID_BAT_SUFFIX;
+ const FilePath sdkmanagerPath = m_sdkLocation / toolPathWithSuffix;
if (sdkmanagerPath.exists())
return sdkmanagerPath;
}
@@ -530,6 +546,34 @@ FilePath AndroidConfig::avdManagerToolPath() const
return FilePath();
}
+void AndroidConfig::setTemporarySdkToolsPath(const Utils::FilePath &path)
+{
+ m_temporarySdkToolsPath = path;
+}
+
+FilePath AndroidConfig::sdkToolsVersionPath() const
+{
+ const QStringList sdkVersionPaths = {
+ QString(Constants::cmdlineToolsName).append("/latest/source.properties"),
+ "tools/source.properties"};
+
+ for (const QString &versionPath : sdkVersionPaths) {
+ const FilePath sdkVersionPath = m_sdkLocation / versionPath;
+ if (sdkVersionPath.exists())
+ return sdkVersionPath;
+ }
+
+ // If it's a first time install use the path of Constants::cmdlineToolsName temporary download
+ const FilePath tmpSdkPath = m_temporarySdkToolsPath;
+ if (!tmpSdkPath.isEmpty()) {
+ const FilePath sdkVersionPath = tmpSdkPath.pathAppended("source.properties");
+ if (sdkVersionPath.exists())
+ return sdkVersionPath;
+ }
+
+ return FilePath();
+}
+
FilePath AndroidConfig::toolchainPathFromNdk(const FilePath &ndkLocation, OsType hostOs)
{
const FilePath tcPath = ndkLocation / "toolchains/";
@@ -861,18 +905,12 @@ void AndroidConfig::setSdkLocation(const FilePath &sdkLocation)
QVersionNumber AndroidConfig::sdkToolsVersion() const
{
- QVersionNumber version;
- if (m_sdkLocation.exists()) {
- FilePath sdkToolsPropertiesPath;
- if (isCmdlineSdkToolsInstalled())
- sdkToolsPropertiesPath = m_sdkLocation / "cmdline-tools/latest/source.properties";
- else
- sdkToolsPropertiesPath = m_sdkLocation / "tools/source.properties";
- QSettings settings(sdkToolsPropertiesPath.toString(), QSettings::IniFormat);
- auto versionStr = settings.value(sdkToolsVersionKey).toString();
- version = QVersionNumber::fromString(versionStr);
- }
- return version;
+ if (!m_sdkLocation.exists())
+ return {};
+
+ const FilePath sdkToolsPropertiesPath = sdkToolsVersionPath();
+ const QSettings settings(sdkToolsPropertiesPath.toString(), QSettings::IniFormat);
+ return QVersionNumber::fromString(settings.value(sdkToolsVersionKey).toString());
}
QVersionNumber AndroidConfig::buildToolsVersion() const
diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h
index e1fe859e54f..c9726370eef 100644
--- a/src/plugins/android/androidconfigurations.h
+++ b/src/plugins/android/androidconfigurations.h
@@ -96,6 +96,7 @@ public:
Utils::FilePath sdkLocation() const;
void setSdkLocation(const Utils::FilePath &sdkLocation);
QVersionNumber sdkToolsVersion() const;
+ Utils::FilePath sdkToolsVersionPath() const;
QVersionNumber buildToolsVersion() const;
QStringList sdkManagerToolArgs() const;
void setSdkManagerToolArgs(const QStringList &args);
@@ -134,6 +135,8 @@ public:
Utils::FilePath sdkManagerToolPath() const;
Utils::FilePath avdManagerToolPath() const;
+ void setTemporarySdkToolsPath(const Utils::FilePath &path);
+
Utils::FilePath toolchainPath(const QtSupport::QtVersion *qtVersion) const;
static Utils::FilePath toolchainPathFromNdk(const Utils::FilePath &ndkLocation,
Utils::OsType hostOs = Utils::HostOsInfo::hostOs());
@@ -158,7 +161,7 @@ public:
QString getProductModel(const QString &device) const;
bool isConnected(const QString &serialNumber) const;
- bool isCmdlineSdkToolsInstalled() const;
+ bool preCmdlineSdkToolsInstalled() const;
bool sdkFullyConfigured() const { return m_sdkFullyConfigured; }
void setSdkFullyConfigured(bool allEssentialsInstalled) { m_sdkFullyConfigured = allEssentialsInstalled; }
@@ -188,6 +191,7 @@ private:
QList<int> availableNdkPlatforms(const QtSupport::QtVersion *qtVersion) const;
Utils::FilePath m_sdkLocation;
+ Utils::FilePath m_temporarySdkToolsPath;
QStringList m_sdkManagerToolArgs;
Utils::FilePath m_openJDKLocation;
Utils::FilePath m_keystoreLocation;
diff --git a/src/plugins/android/androidconstants.h b/src/plugins/android/androidconstants.h
index 0b82feb2d48..83012d8073e 100644
--- a/src/plugins/android/androidconstants.h
+++ b/src/plugins/android/androidconstants.h
@@ -102,5 +102,8 @@ const Utils::Id AndroidCpuAbi = "AndroidCpuAbi";
const Utils::Id AndroidSdk = "AndroidSdk";
const Utils::Id AndroidAvdPath = "AndroidAvdPath";
+// SDK Tools
+const char cmdlineToolsName[] = "cmdline-tools";
+
} // namespace Constants;
} // namespace Android
diff --git a/src/plugins/android/androidsdkdownloader.cpp b/src/plugins/android/androidsdkdownloader.cpp
index c9512b464a9..91319cb8a96 100644
--- a/src/plugins/android/androidsdkdownloader.cpp
+++ b/src/plugins/android/androidsdkdownloader.cpp
@@ -25,6 +25,8 @@
#include "androidsdkdownloader.h"
+#include "androidconstants.h"
+
#include <utils/archive.h>
#include <utils/filepath.h>
@@ -61,7 +63,7 @@ void AndroidSdkDownloader::sslErrors(const QList<QSslError> &sslErrors)
}
#endif
-void AndroidSdkDownloader::downloadAndExtractSdk(const FilePath &sdkExtractPath)
+void AndroidSdkDownloader::downloadAndExtractSdk()
{
if (m_androidConfig.sdkToolsUrl().isEmpty()) {
logError(tr("The SDK Tools download URL is empty."));
@@ -88,11 +90,17 @@ void AndroidSdkDownloader::downloadAndExtractSdk(const FilePath &sdkExtractPath)
connect(m_progressDialog, &QProgressDialog::canceled, this, &AndroidSdkDownloader::cancel);
- connect(this, &AndroidSdkDownloader::sdkPackageWriteFinished, this, [this, sdkExtractPath]() {
- if (Archive *archive = Archive::unarchive(m_sdkFilename, sdkExtractPath)) {
- connect(archive, &Archive::finished, [this, sdkExtractPath](bool success){
- if (success)
+ connect(this, &AndroidSdkDownloader::sdkPackageWriteFinished, this, [this]() {
+ const FilePath extractDir = m_sdkFilename.parentDir();
+ if (Archive *archive = Archive::unarchive(m_sdkFilename, extractDir)) {
+ connect(archive, &Archive::finished, [this, extractDir](bool success) {
+ if (success) {
+ // Save the extraction path temporarily which can be used by sdkmanager
+ // to install essential packages at firt time setup.
+ m_androidConfig.setTemporarySdkToolsPath(
+ extractDir.pathAppended(Constants::cmdlineToolsName));
emit sdkExtracted();
+ }
});
}
});
@@ -153,7 +161,7 @@ FilePath AndroidSdkDownloader::getSaveFilename(const QUrl &url)
basename += QString::number(i);
}
- return FilePath::fromString(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation))
+ return FilePath::fromString(QStandardPaths::writableLocation(QStandardPaths::TempLocation))
/ basename;
}
diff --git a/src/plugins/android/androidsdkdownloader.h b/src/plugins/android/androidsdkdownloader.h
index 76375132397..1cfe5b950dd 100644
--- a/src/plugins/android/androidsdkdownloader.h
+++ b/src/plugins/android/androidsdkdownloader.h
@@ -43,7 +43,7 @@ class AndroidSdkDownloader : public QObject
public:
AndroidSdkDownloader();
- void downloadAndExtractSdk(const Utils::FilePath &sdkExtractPath);
+ void downloadAndExtractSdk();
static QString dialogTitle();
void cancel();
@@ -71,7 +71,7 @@ private:
QNetworkReply *m_reply = nullptr;
Utils::FilePath m_sdkFilename;
QProgressDialog *m_progressDialog = nullptr;
- const AndroidConfig &m_androidConfig;
+ AndroidConfig &m_androidConfig;
};
} // Internal
diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp
index faa4a7b089b..41dab000895 100644
--- a/src/plugins/android/androidsdkmanager.cpp
+++ b/src/plugins/android/androidsdkmanager.cpp
@@ -303,18 +303,18 @@ private:
using MarkerTagsType = std::map<SdkManagerOutputParser::MarkerTag, const char *>;
Q_GLOBAL_STATIC_WITH_ARGS(MarkerTagsType, markerTags, ({
- {SdkManagerOutputParser::MarkerTag::InstalledPackagesMarker, "Installed packages:"},
- {SdkManagerOutputParser::MarkerTag::AvailablePackagesMarkers, "Available Packages:"},
- {SdkManagerOutputParser::MarkerTag::AvailableUpdatesMarker, "Available Updates:"},
- {SdkManagerOutputParser::MarkerTag::PlatformMarker, "platforms"},
- {SdkManagerOutputParser::MarkerTag::SystemImageMarker, "system-images"},
- {SdkManagerOutputParser::MarkerTag::BuildToolsMarker, "build-tools"},
- {SdkManagerOutputParser::MarkerTag::SdkToolsMarker, "tools"},
- {SdkManagerOutputParser::MarkerTag::CmdlineSdkToolsMarker, "cmdline-tools"},
- {SdkManagerOutputParser::MarkerTag::PlatformToolsMarker, "platform-tools"},
- {SdkManagerOutputParser::MarkerTag::EmulatorToolsMarker, "emulator"},
- {SdkManagerOutputParser::MarkerTag::NdkMarker, "ndk"},
- {SdkManagerOutputParser::MarkerTag::ExtrasMarker, "extras"}
+ {SdkManagerOutputParser::MarkerTag::InstalledPackagesMarker, "Installed packages:"},
+ {SdkManagerOutputParser::MarkerTag::AvailablePackagesMarkers, "Available Packages:"},
+ {SdkManagerOutputParser::MarkerTag::AvailableUpdatesMarker, "Available Updates:"},
+ {SdkManagerOutputParser::MarkerTag::PlatformMarker, "platforms"},
+ {SdkManagerOutputParser::MarkerTag::SystemImageMarker, "system-images"},
+ {SdkManagerOutputParser::MarkerTag::BuildToolsMarker, "build-tools"},
+ {SdkManagerOutputParser::MarkerTag::SdkToolsMarker, "tools"},
+ {SdkManagerOutputParser::MarkerTag::CmdlineSdkToolsMarker, Constants::cmdlineToolsName},
+ {SdkManagerOutputParser::MarkerTag::PlatformToolsMarker, "platform-tools"},
+ {SdkManagerOutputParser::MarkerTag::EmulatorToolsMarker, "emulator"},
+ {SdkManagerOutputParser::MarkerTag::NdkMarker, "ndk"},
+ {SdkManagerOutputParser::MarkerTag::ExtrasMarker, "extras"}
}));
AndroidSdkManager::AndroidSdkManager(const AndroidConfig &config):
diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp
index cf920f53f13..00e597b39fb 100644
--- a/src/plugins/android/androidsettingswidget.cpp
+++ b/src/plugins/android/androidsettingswidget.cpp
@@ -452,6 +452,13 @@ AndroidSettingsWidget::AndroidSettingsWidget()
QMessageBox::warning(this, AndroidSdkDownloader::dialogTitle(), error);
});
connect(&m_sdkDownloader, &AndroidSdkDownloader::sdkExtracted, this, [this] {
+ // Make sure the sdk path is created before installing packages
+ const FilePath sdkPath = m_androidConfig.sdkLocation();
+ if (!sdkPath.createDir()) {
+ QMessageBox::warning(this, AndroidSdkDownloader::dialogTitle(),
+ tr("Failed to create the SDK Tools path %1.")
+ .arg("\n\"" + sdkPath.toUserOutput() + "\""));
+ }
m_sdkManager.reloadPackages(true);
updateUI();
apply();
@@ -708,7 +715,7 @@ void AndroidSettingsWidget::downloadSdk()
auto userInput = QMessageBox::information(this, AndroidSdkDownloader::dialogTitle(),
message, QMessageBox::Yes | QMessageBox::No);
if (userInput == QMessageBox::Yes)
- m_sdkDownloader.downloadAndExtractSdk(m_ui.SDKLocationPathChooser->filePath().cleanPath());
+ m_sdkDownloader.downloadAndExtractSdk();
}
// AndroidSettingsPage