forked from qt-creator/qt-creator
Android: Use sdkmanager tool
android tool is deprecated since sdk tools version 25.3.0. Use the new sdkmanager tool Task-number: QTCREATORBUG-17814 Change-Id: I96446f5a64c1c400066b4ac7771c8c7e1bf567ed Reviewed-by: BogDan Vatra <bogdan@kdab.com>
This commit is contained in:
@@ -48,7 +48,8 @@ HEADERS += \
|
|||||||
androidbuildapkstep.h \
|
androidbuildapkstep.h \
|
||||||
androidbuildapkwidget.h \
|
androidbuildapkwidget.h \
|
||||||
androidrunnable.h \
|
androidrunnable.h \
|
||||||
androidtoolmanager.h
|
androidtoolmanager.h \
|
||||||
|
androidsdkmanager.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
androidconfigurations.cpp \
|
androidconfigurations.cpp \
|
||||||
@@ -90,7 +91,8 @@ SOURCES += \
|
|||||||
androidbuildapkwidget.cpp \
|
androidbuildapkwidget.cpp \
|
||||||
androidqtsupport.cpp \
|
androidqtsupport.cpp \
|
||||||
androidrunnable.cpp \
|
androidrunnable.cpp \
|
||||||
androidtoolmanager.cpp
|
androidtoolmanager.cpp \
|
||||||
|
androidsdkmanager.cpp
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
androidsettingswidget.ui \
|
androidsettingswidget.ui \
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ Project {
|
|||||||
"androidrunnable.h",
|
"androidrunnable.h",
|
||||||
"androidrunner.cpp",
|
"androidrunner.cpp",
|
||||||
"androidrunner.h",
|
"androidrunner.h",
|
||||||
|
"androidsdkmanager.cpp",
|
||||||
|
"androidsdkmanager.h",
|
||||||
"androidsettingspage.cpp",
|
"androidsettingspage.cpp",
|
||||||
"androidsettingspage.h",
|
"androidsettingspage.h",
|
||||||
"androidsettingswidget.cpp",
|
"androidsettingswidget.cpp",
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "androidmanager.h"
|
#include "androidmanager.h"
|
||||||
#include "androidqtversion.h"
|
#include "androidqtversion.h"
|
||||||
#include "androiddevicedialog.h"
|
#include "androiddevicedialog.h"
|
||||||
|
#include "androidsdkmanager.h"
|
||||||
#include "androidtoolmanager.h"
|
#include "androidtoolmanager.h"
|
||||||
#include "avddialog.h"
|
#include "avddialog.h"
|
||||||
|
|
||||||
@@ -109,6 +110,8 @@ namespace {
|
|||||||
const QLatin1String keytoolName("keytool");
|
const QLatin1String keytoolName("keytool");
|
||||||
const QLatin1String changeTimeStamp("ChangeTimeStamp");
|
const QLatin1String changeTimeStamp("ChangeTimeStamp");
|
||||||
|
|
||||||
|
const QLatin1String sdkToolsVersionKey("Pkg.Revision");
|
||||||
|
|
||||||
static QString sdkSettingsFileName()
|
static QString sdkSettingsFileName()
|
||||||
{
|
{
|
||||||
return QFileInfo(Core::ICore::settings(QSettings::SystemScope)->fileName()).absolutePath()
|
return QFileInfo(Core::ICore::settings(QSettings::SystemScope)->fileName()).absolutePath()
|
||||||
@@ -315,24 +318,14 @@ void AndroidConfig::updateNdkInformation() const
|
|||||||
m_NdkInformationUpToDate = true;
|
m_NdkInformationUpToDate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidConfig::sortSdkPlatformByApiLevel(const SdkPlatform &a, const SdkPlatform &b)
|
|
||||||
{
|
|
||||||
if (a.apiLevel != b.apiLevel)
|
|
||||||
return a.apiLevel > b.apiLevel;
|
|
||||||
if (a.name != b.name)
|
|
||||||
return a.name < b.name;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidConfig::updateAvailableSdkPlatforms() const
|
void AndroidConfig::updateAvailableSdkPlatforms() const
|
||||||
{
|
{
|
||||||
if (m_availableSdkPlatformsUpToDate)
|
if (m_availableSdkPlatformsUpToDate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_availableSdkPlatforms.clear();
|
m_availableSdkPlatforms.clear();
|
||||||
AndroidToolManager toolManager(*this);
|
AndroidSdkManager sdkManager(*this);
|
||||||
m_availableSdkPlatforms = toolManager.availableSdkPlatforms();
|
m_availableSdkPlatforms = sdkManager.availableSdkPlatforms();
|
||||||
Utils::sort(m_availableSdkPlatforms, sortSdkPlatformByApiLevel);
|
|
||||||
m_availableSdkPlatformsUpToDate = true;
|
m_availableSdkPlatformsUpToDate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,6 +399,16 @@ FileName AndroidConfig::toolPath(const Abi &abi, const QString &ndkToolChainVers
|
|||||||
.arg(toolsPrefix(abi)));
|
.arg(toolsPrefix(abi)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileName AndroidConfig::sdkManagerToolPath() const
|
||||||
|
{
|
||||||
|
FileName sdkPath = m_sdkLocation;
|
||||||
|
QString toolPath = "tools/bin/sdkmanager";
|
||||||
|
if (HostOsInfo::isWindowsHost())
|
||||||
|
toolPath += ANDROID_BAT_SUFFIX;
|
||||||
|
sdkPath = sdkPath.appendPath(toolPath);
|
||||||
|
return sdkPath;
|
||||||
|
}
|
||||||
|
|
||||||
FileName AndroidConfig::gccPath(const Abi &abi, Core::Id lang,
|
FileName AndroidConfig::gccPath(const Abi &abi, Core::Id lang,
|
||||||
const QString &ndkToolChainVersion) const
|
const QString &ndkToolChainVersion) const
|
||||||
{
|
{
|
||||||
@@ -809,6 +812,19 @@ void AndroidConfig::setSdkLocation(const FileName &sdkLocation)
|
|||||||
m_availableSdkPlatformsUpToDate = false;
|
m_availableSdkPlatformsUpToDate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVersionNumber AndroidConfig::sdkToolsVersion() const
|
||||||
|
{
|
||||||
|
QVersionNumber version;
|
||||||
|
if (m_sdkLocation.exists()) {
|
||||||
|
Utils::FileName sdkToolsPropertiesPath(m_sdkLocation);
|
||||||
|
sdkToolsPropertiesPath.appendPath("tools/source.properties");
|
||||||
|
QSettings settings(sdkToolsPropertiesPath.toString(), QSettings::IniFormat);
|
||||||
|
auto versionStr = settings.value(sdkToolsVersionKey).toString();
|
||||||
|
version = QVersionNumber::fromString(versionStr);
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
FileName AndroidConfig::ndkLocation() const
|
FileName AndroidConfig::ndkLocation() const
|
||||||
{
|
{
|
||||||
return m_ndkLocation;
|
return m_ndkLocation;
|
||||||
@@ -1264,4 +1280,13 @@ void AndroidConfigurations::updateAndroidDevice()
|
|||||||
|
|
||||||
AndroidConfigurations *AndroidConfigurations::m_instance = 0;
|
AndroidConfigurations *AndroidConfigurations::m_instance = 0;
|
||||||
|
|
||||||
|
bool SdkPlatform::operator <(const SdkPlatform &other) const
|
||||||
|
{
|
||||||
|
if (apiLevel != other.apiLevel)
|
||||||
|
return apiLevel > other.apiLevel;
|
||||||
|
if (name != other.name)
|
||||||
|
return name < other.name;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Android
|
} // namespace Android
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QFutureInterface>
|
#include <QFutureInterface>
|
||||||
|
#include <QVersionNumber>
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
@@ -79,6 +80,8 @@ public:
|
|||||||
bool isValid() const { return (apiLevel != -1) && !abiName.isEmpty(); }
|
bool isValid() const { return (apiLevel != -1) && !abiName.isEmpty(); }
|
||||||
int apiLevel = -1;
|
int apiLevel = -1;
|
||||||
QString abiName;
|
QString abiName;
|
||||||
|
QString package;
|
||||||
|
Utils::FileName installedLocation;
|
||||||
};
|
};
|
||||||
using SystemImageList = QList<SystemImage>;
|
using SystemImageList = QList<SystemImage>;
|
||||||
|
|
||||||
@@ -86,8 +89,10 @@ using SystemImageList = QList<SystemImage>;
|
|||||||
class SdkPlatform
|
class SdkPlatform
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
bool operator <(const SdkPlatform &other) const;
|
||||||
int apiLevel = -1;
|
int apiLevel = -1;
|
||||||
QString name;
|
QString name;
|
||||||
|
QString package;
|
||||||
Utils::FileName installedLocation;
|
Utils::FileName installedLocation;
|
||||||
SystemImageList systemImages;
|
SystemImageList systemImages;
|
||||||
};
|
};
|
||||||
@@ -105,6 +110,7 @@ public:
|
|||||||
|
|
||||||
Utils::FileName sdkLocation() const;
|
Utils::FileName sdkLocation() const;
|
||||||
void setSdkLocation(const Utils::FileName &sdkLocation);
|
void setSdkLocation(const Utils::FileName &sdkLocation);
|
||||||
|
QVersionNumber sdkToolsVersion() const;
|
||||||
|
|
||||||
Utils::FileName ndkLocation() const;
|
Utils::FileName ndkLocation() const;
|
||||||
void setNdkLocation(const Utils::FileName &ndkLocation);
|
void setNdkLocation(const Utils::FileName &ndkLocation);
|
||||||
@@ -134,6 +140,7 @@ public:
|
|||||||
Utils::FileName androidToolPath() const;
|
Utils::FileName androidToolPath() const;
|
||||||
Utils::FileName antToolPath() const;
|
Utils::FileName antToolPath() const;
|
||||||
Utils::FileName emulatorToolPath() const;
|
Utils::FileName emulatorToolPath() const;
|
||||||
|
Utils::FileName sdkManagerToolPath() const;
|
||||||
|
|
||||||
Utils::FileName gccPath(const ProjectExplorer::Abi &abi, Core::Id lang,
|
Utils::FileName gccPath(const ProjectExplorer::Abi &abi, Core::Id lang,
|
||||||
const QString &ndkToolChainVersion) const;
|
const QString &ndkToolChainVersion) const;
|
||||||
@@ -205,7 +212,6 @@ private:
|
|||||||
//caches
|
//caches
|
||||||
mutable bool m_availableSdkPlatformsUpToDate = false;
|
mutable bool m_availableSdkPlatformsUpToDate = false;
|
||||||
mutable SdkPlatformList m_availableSdkPlatforms;
|
mutable SdkPlatformList m_availableSdkPlatforms;
|
||||||
static bool sortSdkPlatformByApiLevel(const SdkPlatform &a, const SdkPlatform &b);
|
|
||||||
|
|
||||||
mutable bool m_NdkInformationUpToDate = false;
|
mutable bool m_NdkInformationUpToDate = false;
|
||||||
mutable QString m_toolchainHost;
|
mutable QString m_toolchainHost;
|
||||||
|
|||||||
337
src/plugins/android/androidsdkmanager.cpp
Normal file
337
src/plugins/android/androidsdkmanager.cpp
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include "androidsdkmanager.h"
|
||||||
|
|
||||||
|
#include "androidmanager.h"
|
||||||
|
#include "androidtoolmanager.h"
|
||||||
|
|
||||||
|
#include "utils/algorithm.h"
|
||||||
|
#include "utils/qtcassert.h"
|
||||||
|
#include "utils/synchronousprocess.h"
|
||||||
|
#include "utils/environment.h"
|
||||||
|
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
Q_LOGGING_CATEGORY(sdkManagerLog, "qtc.android.sdkManager")
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
// Though sdk manager is introduced in 25.2.3 but the verbose mode is avaialble in 25.3.0
|
||||||
|
// and android tool is supported in 25.2.3
|
||||||
|
const QVersionNumber sdkManagerIntroVersion(25, 3 ,0);
|
||||||
|
|
||||||
|
const char installLocationKey[] = "Installed Location:";
|
||||||
|
const char apiLevelPropertyKey[] = "AndroidVersion.ApiLevel";
|
||||||
|
const char abiPropertyKey[] = "SystemImage.Abi";
|
||||||
|
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Parses the \a line for a [spaces]key[spaces]value[spaces] pattern and returns
|
||||||
|
\c true if \a key is found, false otherwise. Result is copied into \a value.
|
||||||
|
*/
|
||||||
|
static bool valueForKey(QString key, const QString &line, QString *value = nullptr)
|
||||||
|
{
|
||||||
|
auto trimmedInput = line.trimmed();
|
||||||
|
if (trimmedInput.startsWith(key)) {
|
||||||
|
if (value)
|
||||||
|
*value = trimmedInput.section(key, 1, 1).trimmed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Runs the \c sdkmanger tool specific to configuration \a config with arguments \a args. Returns
|
||||||
|
\c true if the command is successfully executed. Output is copied into \a output. The function
|
||||||
|
blocks the calling thread.
|
||||||
|
*/
|
||||||
|
static bool sdkManagerCommand(const AndroidConfig config, const QStringList &args, QString *output)
|
||||||
|
{
|
||||||
|
QString sdkManagerToolPath = config.sdkManagerToolPath().toString();
|
||||||
|
SynchronousProcess proc;
|
||||||
|
SynchronousProcessResponse response = proc.runBlocking(sdkManagerToolPath, args);
|
||||||
|
if (response.result == SynchronousProcessResponse::Finished) {
|
||||||
|
if (output)
|
||||||
|
*output = response.allOutput();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class SdkManagerOutputParser
|
||||||
|
\brief The SdkManagerOutputParser class is a helper class to parse the output of the \c sdkmanager
|
||||||
|
commands.
|
||||||
|
*/
|
||||||
|
class SdkManagerOutputParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum MarkerTag
|
||||||
|
{
|
||||||
|
None = 0x01,
|
||||||
|
InstalledPackagesMarker = 0x02,
|
||||||
|
AvailablePackagesMarkers = 0x04,
|
||||||
|
AvailableUpdatesMarker = 0x08,
|
||||||
|
EmptyMarker = 0x10,
|
||||||
|
PlatformMarker = 0x20,
|
||||||
|
SystemImageMarker = 0x40,
|
||||||
|
SectionMarkers = InstalledPackagesMarker | AvailablePackagesMarkers | AvailableUpdatesMarker
|
||||||
|
};
|
||||||
|
|
||||||
|
void parsePackageListing(const QString &output);
|
||||||
|
|
||||||
|
SdkPlatformList m_installedPlatforms;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void compileData();
|
||||||
|
void parsePackageData(MarkerTag packageMarker, const QStringList &data);
|
||||||
|
bool parsePlatform(const QStringList &data, SdkPlatform *platform) const;
|
||||||
|
bool parseSystemImage(const QStringList &data, SystemImage *image);
|
||||||
|
MarkerTag parseMarkers(const QString &line);
|
||||||
|
|
||||||
|
MarkerTag m_currentSection = MarkerTag::None;
|
||||||
|
SystemImageList m_installedSystemImages;
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::map<SdkManagerOutputParser::MarkerTag, const char *> markerTags {
|
||||||
|
{SdkManagerOutputParser::MarkerTag::InstalledPackagesMarker, "Installed packages:"},
|
||||||
|
{SdkManagerOutputParser::MarkerTag::AvailablePackagesMarkers, "Available Packages:"},
|
||||||
|
{SdkManagerOutputParser::MarkerTag::AvailablePackagesMarkers, "Available Updates:"},
|
||||||
|
{SdkManagerOutputParser::MarkerTag::PlatformMarker, "platforms"},
|
||||||
|
{SdkManagerOutputParser::MarkerTag::SystemImageMarker, "system-images"}
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidSdkManager::AndroidSdkManager(const AndroidConfig &config):
|
||||||
|
m_config(config),
|
||||||
|
m_parser(new SdkManagerOutputParser)
|
||||||
|
{
|
||||||
|
QString packageListing;
|
||||||
|
if (sdkManagerCommand(config, QStringList({"--list", "--verbose"}), &packageListing)) {
|
||||||
|
m_parser->parsePackageListing(packageListing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidSdkManager::~AndroidSdkManager()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SdkPlatformList AndroidSdkManager::availableSdkPlatforms()
|
||||||
|
{
|
||||||
|
if (m_config.sdkToolsVersion() < sdkManagerIntroVersion) {
|
||||||
|
AndroidToolManager toolManager(m_config);
|
||||||
|
return toolManager.availableSdkPlatforms();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_parser->m_installedPlatforms;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SdkManagerOutputParser::parsePackageListing(const QString &output)
|
||||||
|
{
|
||||||
|
QStringList packageData;
|
||||||
|
bool collectingPackageData = false;
|
||||||
|
MarkerTag currentPackageMarker = MarkerTag::None;
|
||||||
|
|
||||||
|
auto processCurrentPackage = [&]() {
|
||||||
|
if (collectingPackageData) {
|
||||||
|
collectingPackageData = false;
|
||||||
|
parsePackageData(currentPackageMarker, packageData);
|
||||||
|
packageData.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (QString outputLine, output.split('\n')) {
|
||||||
|
MarkerTag marker = parseMarkers(outputLine);
|
||||||
|
|
||||||
|
if (marker & SectionMarkers) {
|
||||||
|
// Section marker found. Update the current section being parsed.
|
||||||
|
m_currentSection = marker;
|
||||||
|
processCurrentPackage();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_currentSection == None
|
||||||
|
|| m_currentSection == AvailablePackagesMarkers // At this point. Not interested in
|
||||||
|
|| m_currentSection == AvailableUpdatesMarker) { // available or update packages.
|
||||||
|
// Let go of verbose output utill a valid section starts.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (marker == EmptyMarker) {
|
||||||
|
// Empty marker. Occurs at the end of a package details.
|
||||||
|
// Process the collected package data, if any.
|
||||||
|
processCurrentPackage();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (marker == None) {
|
||||||
|
if (collectingPackageData)
|
||||||
|
packageData << outputLine; // Collect data until next marker.
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// Package marker found.
|
||||||
|
processCurrentPackage(); // New package starts. Process the collected package data, if any.
|
||||||
|
currentPackageMarker = marker;
|
||||||
|
collectingPackageData = true;
|
||||||
|
packageData << outputLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileData();
|
||||||
|
Utils::sort(m_installedPlatforms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SdkManagerOutputParser::compileData()
|
||||||
|
{
|
||||||
|
// Associate the system images with sdk platforms.
|
||||||
|
for (auto &image : m_installedSystemImages) {
|
||||||
|
auto findPlatfom = [image](const SdkPlatform &platform) {
|
||||||
|
return platform.apiLevel == image.apiLevel;
|
||||||
|
};
|
||||||
|
auto itr = std::find_if(m_installedPlatforms.begin(), m_installedPlatforms.end(), findPlatfom);
|
||||||
|
if (itr != m_installedPlatforms.end())
|
||||||
|
itr->systemImages.append(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SdkManagerOutputParser::parsePackageData(MarkerTag packageMarker, const QStringList &data)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(!data.isEmpty() && packageMarker != None, return);
|
||||||
|
|
||||||
|
if (m_currentSection != MarkerTag::InstalledPackagesMarker)
|
||||||
|
return; // For now, only interested in installed packages.
|
||||||
|
|
||||||
|
switch (packageMarker) {
|
||||||
|
case MarkerTag::PlatformMarker:
|
||||||
|
{
|
||||||
|
SdkPlatform platform;
|
||||||
|
if (parsePlatform(data, &platform))
|
||||||
|
m_installedPlatforms.append(platform);
|
||||||
|
else
|
||||||
|
qCDebug(sdkManagerLog) << "Platform: Parsing failed: " << data;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MarkerTag::SystemImageMarker:
|
||||||
|
{
|
||||||
|
SystemImage image;
|
||||||
|
if (parseSystemImage(data, &image))
|
||||||
|
m_installedSystemImages.append(image);
|
||||||
|
else
|
||||||
|
qCDebug(sdkManagerLog) << "System Image: Parsing failed: " << data;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
qCDebug(sdkManagerLog) << "Unhandled package: " << markerTags.at(packageMarker);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SdkManagerOutputParser::parsePlatform(const QStringList &data, SdkPlatform *platform) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(platform && !data.isEmpty(), return false);
|
||||||
|
|
||||||
|
QStringList parts = data.at(0).split(';');
|
||||||
|
if (parts.count() < 2) {
|
||||||
|
qCDebug(sdkManagerLog) << "Platform: Unexpected header: "<< data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
platform->name = parts[1];
|
||||||
|
platform->package = data.at(0);
|
||||||
|
|
||||||
|
foreach (QString line, data) {
|
||||||
|
QString value;
|
||||||
|
if (valueForKey(installLocationKey, line, &value))
|
||||||
|
platform->installedLocation = Utils::FileName::fromString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int apiLevel = AndroidManager::findApiLevel(platform->installedLocation);
|
||||||
|
if (apiLevel != -1)
|
||||||
|
platform->apiLevel = apiLevel;
|
||||||
|
else
|
||||||
|
qCDebug(sdkManagerLog) << "Platform: Can not parse api level: "<< data;
|
||||||
|
|
||||||
|
return apiLevel != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SdkManagerOutputParser::parseSystemImage(const QStringList &data, SystemImage *image)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(image && !data.isEmpty(), return false);
|
||||||
|
|
||||||
|
QStringList parts = data.at(0).split(';');
|
||||||
|
QTC_ASSERT(!data.isEmpty() && parts.count() >= 4,
|
||||||
|
qCDebug(sdkManagerLog) << "System Image: Unexpected header: " << data);
|
||||||
|
|
||||||
|
image->package = data.at(0);
|
||||||
|
foreach (QString line, data) {
|
||||||
|
QString value;
|
||||||
|
if (valueForKey(installLocationKey, line, &value))
|
||||||
|
image->installedLocation = Utils::FileName::fromString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::FileName propertiesPath = image->installedLocation;
|
||||||
|
propertiesPath.appendPath("/source.properties");
|
||||||
|
if (propertiesPath.exists()) {
|
||||||
|
// Installed System Image.
|
||||||
|
QSettings imageProperties(propertiesPath.toString(), QSettings::IniFormat);
|
||||||
|
bool validApiLevel = false;
|
||||||
|
image->apiLevel = imageProperties.value(apiLevelPropertyKey).toInt(&validApiLevel);
|
||||||
|
if (!validApiLevel) {
|
||||||
|
qCDebug(sdkManagerLog) << "System Image: Can not parse api level: "<< data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
image->abiName = imageProperties.value(abiPropertyKey).toString();
|
||||||
|
} else if (parts.count() >= 4){
|
||||||
|
image->apiLevel = parts[1].section('-', 1, 1).toInt();
|
||||||
|
image->abiName = parts[3];
|
||||||
|
} else {
|
||||||
|
qCDebug(sdkManagerLog) << "System Image: Can not parse: "<< data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SdkManagerOutputParser::MarkerTag SdkManagerOutputParser::parseMarkers(const QString &line)
|
||||||
|
{
|
||||||
|
if (line.isEmpty())
|
||||||
|
return EmptyMarker;
|
||||||
|
|
||||||
|
for (auto pair: markerTags) {
|
||||||
|
if (line.startsWith(QLatin1String(pair.second)))
|
||||||
|
return pair.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Android
|
||||||
51
src/plugins/android/androidsdkmanager.h
Normal file
51
src/plugins/android/androidsdkmanager.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "utils/fileutils.h"
|
||||||
|
#include "androidconfigurations.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Android {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class SdkManagerOutputParser;
|
||||||
|
|
||||||
|
class AndroidSdkManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AndroidSdkManager(const AndroidConfig &config);
|
||||||
|
~AndroidSdkManager();
|
||||||
|
|
||||||
|
SdkPlatformList availableSdkPlatforms();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const AndroidConfig &m_config;
|
||||||
|
std::unique_ptr<SdkManagerOutputParser> m_parser;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Android
|
||||||
@@ -339,6 +339,8 @@ void AndroidToolOutputParser::parseTargetListing(const QString &output,
|
|||||||
addSystemImage(abiList, platform);
|
addSystemImage(abiList, platform);
|
||||||
*platformList << platform;
|
*platformList << platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils::sort(*platformList);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
Reference in New Issue
Block a user