Android: optionally add a default system image for an AVD

Find out the highest API level that Qt versions are using,
and add a Google Play Store Emulator image to the list of
packages to install only if there are missing essential
packages. This can practically work as an optional package
so that it be most suitable for users doing first time setup
but if the essential packages are all installed, then don't
invalidate the settings.

Fixes: QTCREATORBUG-24754
Task-number: QTCREATORBUG-31837
Change-Id: Ia1911637a846eb2963d69db6d33346dc04dc16b6
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
Assam Boudjelthia
2024-10-17 14:43:06 +03:00
parent 99a4184761
commit bf7db9af43
4 changed files with 57 additions and 1 deletions

View File

@@ -49,6 +49,7 @@
#include <QRegularExpression> #include <QRegularExpression>
#include <QSettings> #include <QSettings>
#include <QStandardPaths> #include <QStandardPaths>
#include <QSysInfo>
#include <functional> #include <functional>
#include <memory> #include <memory>
@@ -971,6 +972,50 @@ QStringList allEssentials()
return allPackages; return allPackages;
} }
QString optionalSystemImagePackage(AndroidSdkManager *sdkManager)
{
const QStringList essentialPkgs(allEssentials());
QStringList platforms = Utils::filtered(essentialPkgs, [](const QString &item) {
return item.startsWith(platformsPackageMarker(), Qt::CaseInsensitive);
});
if (platforms.isEmpty())
return {};
platforms.sort();
const QStringList platformBits = platforms.last().split('-');
if (platformBits.isEmpty())
return {};
const int apiLevel = platformBits.last().toInt();
if (apiLevel < 1)
return {};
QString hostArch = QSysInfo::currentCpuArchitecture();
if (hostArch == "arm64")
hostArch = ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A;
else if (hostArch == "i386")
hostArch = ProjectExplorer::Constants::ANDROID_ABI_X86;
else if (hostArch == "arm")
hostArch = ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A;
const auto imageName = QLatin1String("%1;android-%2;google_apis_playstore;%3")
.arg(Constants::systemImagesPackageName).arg(apiLevel).arg(hostArch);
const SdkPlatformList sdkPlatforms = sdkManager->filteredSdkPlatforms(
apiLevel, AndroidSdkPackage::AnyValidState);
if (sdkPlatforms.isEmpty())
return {};
const SystemImageList images = sdkPlatforms.first()->systemImages(AndroidSdkPackage::Available);
for (const SystemImage *img : images) {
if (img->sdkStylePath() == imageName)
return imageName;
}
return {};
}
static QStringList packagesWithoutNdks(const QStringList &packages) static QStringList packagesWithoutNdks(const QStringList &packages)
{ {
return Utils::filtered(packages, [] (const QString &p) { return Utils::filtered(packages, [] (const QString &p) {

View File

@@ -55,6 +55,8 @@ QVersionNumber ndkVersion(const Utils::FilePath &ndkPath);
QUrl sdkToolsUrl(); QUrl sdkToolsUrl();
QByteArray getSdkToolsSha256(); QByteArray getSdkToolsSha256();
QString optionalSystemImagePackage(Internal::AndroidSdkManager *sdkManager);
QStringList allEssentials(); QStringList allEssentials();
bool allEssentialsInstalled(Internal::AndroidSdkManager *sdkManager); bool allEssentialsInstalled(Internal::AndroidSdkManager *sdkManager);
bool sdkToolsOk(); bool sdkToolsOk();

View File

@@ -80,5 +80,6 @@ const char cmdlineToolsName[] = "cmdline-tools";
const char ndkPackageName[] = "ndk"; const char ndkPackageName[] = "ndk";
const char platformsPackageName[] = "platforms"; const char platformsPackageName[] = "platforms";
const char buildToolsPackageName[] = "build-tools"; const char buildToolsPackageName[] = "build-tools";
const char systemImagesPackageName[] = "system-images";
} // Android::Constants } // Android::Constants

View File

@@ -670,7 +670,15 @@ void AndroidSettingsWidget::validateSdk()
.arg(QGuiApplication::applicationDisplayName(), .arg(QGuiApplication::applicationDisplayName(),
notFoundEssentials.join("\", \""))); notFoundEssentials.join("\", \"")));
} }
m_sdkManager.runInstallationChange({m_sdkManager.missingEssentialSdkPackages()}, QStringList missingPkgs = m_sdkManager.missingEssentialSdkPackages();
// Add the a system image with highest API level only if there are other
// essentials needed, so it would practicaly be somewhat optional.
if (!missingPkgs.isEmpty()) {
const QString sysImage = AndroidConfig::optionalSystemImagePackage(&m_sdkManager);
if (!sysImage.isEmpty())
missingPkgs.append(sysImage);
}
m_sdkManager.runInstallationChange({missingPkgs},
Tr::tr("Android SDK installation is missing necessary packages. " Tr::tr("Android SDK installation is missing necessary packages. "
"Do you want to install the missing packages?")); "Do you want to install the missing packages?"));
} }