Commit 3bcae525 authored by BogDan Vatra's avatar BogDan Vatra
Browse files

Android: Say hello to gradle!



Switching from Ant to Gradle brings lots of advantages:
 - it is way faster when rebuilding (25-50% faster than ant).
 - it enables first class Android Studio integration.
 - adding Android Extras libs (e.g. Google Play services, OBB, etc.) to
   your project is now painless.

[ChangeLog][Android] Added Gradle support to build the APK.

Change-Id: Iee492954f8ffb2c22e6ab14a8a25faf644de9a51
Reviewed-by: default avatarDaniel Teske <daniel.teske@digia.com>
parent 222fbdb5
......@@ -139,18 +139,20 @@ bool FileUtils::removeRecursively(const FileName &filePath, QString *error)
Returns whether the operation succeeded.
*/
bool FileUtils::copyRecursively(const FileName &srcFilePath, const FileName &tgtFilePath,
QString *error)
QString *error, const std::function<bool (QFileInfo, QFileInfo, QString *)> &copyHelper)
{
QFileInfo srcFileInfo = srcFilePath.toFileInfo();
if (srcFileInfo.isDir()) {
QDir targetDir(tgtFilePath.toString());
targetDir.cdUp();
if (!targetDir.mkdir(tgtFilePath.toFileInfo().fileName())) {
if (error) {
*error = QCoreApplication::translate("Utils::FileUtils", "Failed to create directory \"%1\".")
.arg(tgtFilePath.toUserOutput());
if (!tgtFilePath.toFileInfo().exists()) {
QDir targetDir(tgtFilePath.toString());
targetDir.cdUp();
if (!targetDir.mkdir(tgtFilePath.toFileInfo().fileName())) {
if (error) {
*error = QCoreApplication::translate("Utils::FileUtils", "Failed to create directory \"%1\".")
.arg(tgtFilePath.toUserOutput());
}
return false;
}
return false;
}
QDir sourceDir(srcFilePath.toString());
QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot
......@@ -160,16 +162,21 @@ bool FileUtils::copyRecursively(const FileName &srcFilePath, const FileName &tgt
newSrcFilePath.appendPath(fileName);
FileName newTgtFilePath = tgtFilePath;
newTgtFilePath.appendPath(fileName);
if (!copyRecursively(newSrcFilePath, newTgtFilePath, error))
if (!copyRecursively(newSrcFilePath, newTgtFilePath, error, copyHelper))
return false;
}
} else {
if (!QFile::copy(srcFilePath.toString(), tgtFilePath.toString())) {
if (error) {
*error = QCoreApplication::translate("Utils::FileUtils", "Could not copy file \"%1\" to \"%2\".")
.arg(srcFilePath.toUserOutput(), tgtFilePath.toUserOutput());
if (copyHelper) {
if (!copyHelper(srcFileInfo, tgtFilePath.toFileInfo(), error))
return false;
} else {
if (!QFile::copy(srcFilePath.toString(), tgtFilePath.toString())) {
if (error) {
*error = QCoreApplication::translate("Utils::FileUtils", "Could not copy file \"%1\" to \"%2\".")
.arg(srcFilePath.toUserOutput(), tgtFilePath.toUserOutput());
}
return false;
}
return false;
}
}
return true;
......
......@@ -100,11 +100,12 @@ private:
FileName(const QString &string);
};
class QTCREATOR_UTILS_EXPORT FileUtils {
public:
static bool removeRecursively(const FileName &filePath, QString *error = 0);
static bool copyRecursively(const FileName &srcFilePath, const FileName &tgtFilePath,
QString *error = 0);
QString *error = 0, const std::function<bool (QFileInfo, QFileInfo, QString *)> &copyHelper = std::function<bool (QFileInfo, QFileInfo, QString *)>());
static bool isFileNewerThan(const FileName &filePath, const QDateTime &timeStamp);
static FileName resolveSymlinks(const FileName &path);
static QString shortNativePath(const FileName &path);
......
......@@ -89,7 +89,8 @@ SOURCES += \
javafilewizard.cpp \
avddialog.cpp \
androidbuildapkstep.cpp \
androidbuildapkwidget.cpp
androidbuildapkwidget.cpp \
androidqtsupport.cpp
FORMS += \
androidsettingswidget.ui \
......
......@@ -67,6 +67,7 @@ QtcPlugin {
"androidplugin.h",
"androidpotentialkit.cpp",
"androidpotentialkit.h",
"androidqtsupport.cpp",
"androidqtsupport.h",
"androidqtversion.cpp",
"androidqtversion.h",
......
......@@ -59,18 +59,22 @@ const QLatin1String DeployActionKey("Qt4ProjectManager.AndroidDeployQtStep.Deplo
const QLatin1String KeystoreLocationKey("KeystoreLocation");
const QLatin1String BuildTargetSdkKey("BuildTargetSdk");
const QLatin1String VerboseOutputKey("VerboseOutput");
const QLatin1String UseGradleKey("UseGradle");
AndroidBuildApkStep::AndroidBuildApkStep(ProjectExplorer::BuildStepList *parent, const Core::Id id)
: ProjectExplorer::AbstractProcessStep(parent, id),
m_deployAction(BundleLibrariesDeployment),
m_signPackage(false),
m_verbose(false),
m_useGradle(false),
m_openPackageLocation(false),
m_buildTargetSdk(AndroidConfig::apiLevelNameFor(AndroidConfigurations::currentConfig().highestAndroidSdk()))
{
const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
if (version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0))
if (version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0)) {
m_deployAction = DebugDeployment;
m_useGradle = AndroidConfigurations::currentConfig().useGrandle();
}
//: AndroidBuildApkStep default display name
setDefaultDisplayName(tr("Build Android APK"));
}
......@@ -81,6 +85,7 @@ AndroidBuildApkStep::AndroidBuildApkStep(ProjectExplorer::BuildStepList *parent,
m_deployAction(other->deployAction()),
m_signPackage(other->signPackage()),
m_verbose(other->m_verbose),
m_useGradle(other->m_useGradle),
m_openPackageLocation(other->m_openPackageLocation),
m_buildTargetSdk(other->m_buildTargetSdk)
{
......@@ -88,6 +93,8 @@ AndroidBuildApkStep::AndroidBuildApkStep(ProjectExplorer::BuildStepList *parent,
if (version->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0)) {
if (m_deployAction == DebugDeployment)
m_deployAction = BundleLibrariesDeployment;
if (m_useGradle)
m_useGradle = false;
}
}
......@@ -123,8 +130,7 @@ bool AndroidBuildApkStep::init()
setOutputParser(parser);
m_openPackageLocationForRun = m_openPackageLocation;
m_apkPath = AndroidManager::androidQtSupport(target())->apkPath(target(), m_signPackage ? AndroidQtSupport::ReleaseBuildSigned
: AndroidQtSupport::DebugBuild).toString();
m_apkPath = AndroidManager::androidQtSupport(target())->apkPath(target()).toString();
bool result = AbstractProcessStep::init();
if (!result)
......@@ -169,6 +175,7 @@ bool AndroidBuildApkStep::fromMap(const QVariantMap &map)
if (m_buildTargetSdk.isEmpty())
m_buildTargetSdk = AndroidConfig::apiLevelNameFor(AndroidConfigurations::currentConfig().highestAndroidSdk());
m_verbose = map.value(VerboseOutputKey).toBool();
m_useGradle = map.value(UseGradleKey).toBool();
return ProjectExplorer::BuildStep::fromMap(map);
}
......@@ -179,6 +186,7 @@ QVariantMap AndroidBuildApkStep::toMap() const
map.insert(KeystoreLocationKey, m_keystorePath.toString());
map.insert(BuildTargetSdkKey, m_buildTargetSdk);
map.insert(VerboseOutputKey, m_verbose);
map.insert(UseGradleKey, m_useGradle);
return map;
}
......@@ -195,6 +203,8 @@ QString AndroidBuildApkStep::buildTargetSdk() const
void AndroidBuildApkStep::setBuildTargetSdk(const QString &sdk)
{
m_buildTargetSdk = sdk;
if (m_useGradle)
AndroidManager::updateGradleProperties(target());
}
AndroidBuildApkStep::AndroidDeployAction AndroidBuildApkStep::deployAction() const
......@@ -254,6 +264,18 @@ void AndroidBuildApkStep::setVerboseOutput(bool verbose)
m_verbose = verbose;
}
bool AndroidBuildApkStep::useGradle() const
{
return m_useGradle;
}
void AndroidBuildApkStep::setUseGradle(bool b)
{
m_useGradle = b;
if (m_useGradle)
AndroidManager::updateGradleProperties(target());
}
bool AndroidBuildApkStep::runInGuiThread() const
{
return true;
......
......@@ -72,13 +72,19 @@ public:
bool openPackageLocation() const;
void setOpenPackageLocation(bool open);
bool verboseOutput() const;
void setVerboseOutput(bool verbose);
bool useGradle() const;
void setUseGradle(bool b);
bool runInGuiThread() const;
QString buildTargetSdk() const;
void setBuildTargetSdk(const QString &sdk);
virtual Utils::FileName androidPackageSourceDir() const = 0;
public slots:
void setDeployAction(AndroidDeployAction deploy);
......@@ -95,12 +101,12 @@ protected:
ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
bool immutable() const { return true; }
void processFinished(int exitCode, QProcess::ExitStatus status);
virtual Utils::FileName androidPackageSourceDir() const = 0;
protected:
AndroidDeployAction m_deployAction;
bool m_signPackage;
bool m_verbose;
bool m_useGradle;
bool m_openPackageLocation;
bool m_openPackageLocationForRun;
QString m_buildTargetSdk;
......
......@@ -91,6 +91,7 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
m_ui->signingDebugWarningLabel->hide();
signPackageCheckBoxToggled(m_step->signPackage());
m_ui->useGradleCheckBox->setChecked(m_step->useGradle());
m_ui->verboseOutputCheckBox->setChecked(m_step->verboseOutput());
m_ui->openPackageLocationCheckBox->setChecked(m_step->openPackageLocation());
......@@ -105,6 +106,8 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
connect(m_ui->temporaryQtOption, SIGNAL(clicked()), SLOT(updateDebugDeploySigningWarning()));
connect(m_ui->bundleQtOption, SIGNAL(clicked()), SLOT(updateDebugDeploySigningWarning()));
connect(m_ui->useGradleCheckBox, SIGNAL(toggled(bool)),
this, SLOT(useGradleCheckBoxToggled(bool)));
connect(m_ui->openPackageLocationCheckBox, SIGNAL(toggled(bool)),
this, SLOT(openPackageLocationCheckBoxToggled(bool)));
connect(m_ui->verboseOutputCheckBox, SIGNAL(toggled(bool)),
......@@ -128,7 +131,9 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
updateSigningWarning();
updateDebugDeploySigningWarning();
QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(step->target()->kit());
m_ui->temporaryQtOption->setVisible(qt->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0));
bool qt54 = qt->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0);
m_ui->temporaryQtOption->setVisible(qt54);
m_ui->useGradleCheckBox->setVisible(qt54);
}
AndroidBuildApkWidget::~AndroidBuildApkWidget()
......@@ -254,3 +259,7 @@ void AndroidBuildApkWidget::updateDebugDeploySigningWarning()
}
}
void AndroidBuildApkWidget::useGradleCheckBoxToggled(bool checked)
{
m_step->setUseGradle(checked);
}
......@@ -64,6 +64,7 @@ private slots:
void certificatesAliasComboBoxActivated(const QString &alias);
void updateSigningWarning();
void updateDebugDeploySigningWarning();
void useGradleCheckBoxToggled(bool checked);
void openPackageLocationCheckBoxToggled(bool checked);
void verboseOutputCheckBoxToggled(bool checked);
void updateKeyStorePath(const QString &path);
......
......@@ -184,20 +184,27 @@
<string>Advanced Actions</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<item row="2" column="0">
<widget class="QCheckBox" name="verboseOutputCheckBox">
<property name="text">
<string>Verbose output</string>
</property>
</widget>
</item>
<item row="0" column="0">
<item row="1" column="0">
<widget class="QCheckBox" name="openPackageLocationCheckBox">
<property name="text">
<string>Open package location after build</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="useGradleCheckBox">
<property name="text">
<string>Use Gradle</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
......
......@@ -84,6 +84,7 @@ namespace {
const QLatin1String OpenJDKLocationKey("OpenJDKLocation");
const QLatin1String KeystoreLocationKey("KeystoreLocation");
const QLatin1String AutomaticKitCreationKey("AutomatiKitCreation");
const QLatin1String UseGradleKey("UseGradle");
const QLatin1String MakeExtraSearchDirectory("MakeExtraSearchDirectory");
const QLatin1String DefaultDevice("DefaultDevice");
const QLatin1String PartitionSizeKey("PartitionSize");
......@@ -181,6 +182,7 @@ void AndroidConfig::load(const QSettings &settings)
m_sdkLocation = FileName::fromString(settings.value(SDKLocationKey).toString());
m_ndkLocation = FileName::fromString(settings.value(NDKLocationKey).toString());
m_antLocation = FileName::fromString(settings.value(AntLocationKey).toString());
m_useGradle = settings.value(UseGradleKey, true).toBool();
m_openJDKLocation = FileName::fromString(settings.value(OpenJDKLocationKey).toString());
m_keystoreLocation = FileName::fromString(settings.value(KeystoreLocationKey).toString());
m_toolchainHost = settings.value(ToolchainHostKey).toString();
......@@ -214,7 +216,8 @@ void AndroidConfig::load(const QSettings &settings)
}
AndroidConfig::AndroidConfig()
: m_availableSdkPlatformsUpToDate(false),
: m_useGradle(true),
m_availableSdkPlatformsUpToDate(false),
m_NdkInformationUpToDate(false)
{
......@@ -230,6 +233,7 @@ void AndroidConfig::save(QSettings &settings) const
settings.setValue(SDKLocationKey, m_sdkLocation.toString());
settings.setValue(NDKLocationKey, m_ndkLocation.toString());
settings.setValue(AntLocationKey, m_antLocation.toString());
settings.setValue(UseGradleKey, m_useGradle);
settings.setValue(OpenJDKLocationKey, m_openJDKLocation.toString());
settings.setValue(KeystoreLocationKey, m_keystoreLocation.toString());
settings.setValue(PartitionSizeKey, m_partitionSize);
......@@ -912,6 +916,16 @@ void AndroidConfig::setAutomaticKitCreation(bool b)
m_automaticKitCreation = b;
}
bool AndroidConfig::useGrandle() const
{
return m_useGradle;
}
void AndroidConfig::setUseGradle(bool b)
{
m_useGradle = b;
}
///////////////////////////////////
// AndroidConfigurations
///////////////////////////////////
......
......@@ -115,6 +115,9 @@ public:
bool automaticKitCreation() const;
void setAutomaticKitCreation(bool b);
bool useGrandle() const;
void setUseGradle(bool b);
Utils::FileName adbToolPath() const;
Utils::FileName androidToolPath() const;
Utils::Environment androidToolEnvironment() const;
......@@ -179,6 +182,7 @@ private:
QStringList m_makeExtraSearchDirectories;
unsigned m_partitionSize;
bool m_automaticKitCreation;
bool m_useGradle;
//caches
mutable bool m_availableSdkPlatformsUpToDate;
......
......@@ -165,6 +165,8 @@ void AndroidDeployQtStep::ctor()
bool AndroidDeployQtStep::init()
{
m_androiddeployqtArgs.clear();
if (AndroidManager::checkForQt51Files(project()->projectDirectory()))
emit addOutput(tr("Found old folder \"android\" in source directory. Qt 5.2 does not use that folder by default."), ErrorOutput);
......@@ -252,12 +254,12 @@ bool AndroidDeployQtStep::init()
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("bundled"));
break;
}
if (androidBuildApkStep->useGradle())
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--gradle"));
} else {
m_uninstallPreviousPackageRun = true;
pp->setCommand(AndroidConfigurations::currentConfig().adbToolPath().toString());
m_apkPath = AndroidManager::androidQtSupport(target())->apkPath(target(), AndroidManager::signPackage(target())
? AndroidQtSupport::ReleaseBuildSigned
: AndroidQtSupport::DebugBuild).toString();
m_apkPath = AndroidManager::androidQtSupport(target())->apkPath(target()).toString();
pp->setWorkingDirectory(bc->buildDirectory().toString());
}
pp->setMacroExpander(bc->macroExpander());
......
......@@ -595,4 +595,112 @@ AndroidQtSupport *AndroidManager::androidQtSupport(ProjectExplorer::Target *targ
return 0;
}
bool AndroidManager::useGradle(ProjectExplorer::Target *target)
{
if (!target)
return false;
AndroidBuildApkStep *buildApkStep
= AndroidGlobal::buildStep<AndroidBuildApkStep>(target->activeBuildConfiguration());
return buildApkStep && buildApkStep->useGradle();
}
typedef QMap<QByteArray, QByteArray> GradleProperties;
static GradleProperties readGradleProperties(const QString &path)
{
GradleProperties properties;
QFile file(path);
if (!file.open(QIODevice::ReadOnly))
return properties;
foreach (const QByteArray &line, file.readAll().split('\n')) {
if (line.trimmed().startsWith('#'))
continue;
QList<QByteArray> prop(line.split('='));
if (prop.size() > 1)
properties[prop.at(0).trimmed()] = prop.at(1).trimmed();
}
file.close();
return properties;
}
static bool mergeGradleProperties(const QString &path, GradleProperties properties)
{
QFile::remove(path + QLatin1Char('~'));
QFile::rename(path, path + QLatin1Char('~'));
QFile file(path);
if (!file.open(QIODevice::Truncate | QIODevice::WriteOnly | QIODevice::Text))
return false;
QFile oldFile(path + QLatin1Char('~'));
if (oldFile.open(QIODevice::ReadOnly)) {
while (!oldFile.atEnd()) {
QByteArray line(oldFile.readLine());
QList<QByteArray> prop(line.split('='));
if (prop.size() > 1) {
GradleProperties::iterator it = properties.find(prop.at(0).trimmed());
if (it != properties.end()) {
file.write(it.key() + '=' + it.value() + '\n');
properties.erase(it);
continue;
}
}
file.write(line);
}
oldFile.close();
} else {
file.write("## This file is automatically generated by QtCreator.\n"
"#\n"
"# This file must *NOT* be checked into Version Control Systems,\n"
"# as it contains information specific to your local configuration.\n\n");
}
for (GradleProperties::const_iterator it = properties.begin(); it != properties.end(); ++it)
file.write(it.key() + '=' + it.value() + '\n');
file.close();
return true;
}
bool AndroidManager::updateGradleProperties(ProjectExplorer::Target *target)
{
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit());
if (!version)
return false;
AndroidBuildApkStep *buildApkStep
= AndroidGlobal::buildStep<AndroidBuildApkStep>(target->activeBuildConfiguration());
if (!buildApkStep || !buildApkStep->androidPackageSourceDir().appendPath(QLatin1String("gradlew")).toFileInfo().exists())
return false;
GradleProperties localProperties;
localProperties["sdk.dir"] = AndroidConfigurations::currentConfig().sdkLocation().toString().toLocal8Bit();
if (!mergeGradleProperties(buildApkStep->androidPackageSourceDir().appendPath(QLatin1String("local.properties")).toString(), localProperties))
return false;
QString gradlePropertiesPath = buildApkStep->androidPackageSourceDir().appendPath(QLatin1String("gradle.properties")).toString();
GradleProperties gradleProperties = readGradleProperties(gradlePropertiesPath);
gradleProperties["qt5AndroidDir"] = version->qmakeProperty("QT_INSTALL_PREFIX")
.append(QLatin1String("/src/android/java")).toLocal8Bit();
gradleProperties["buildDir"] = ".build";
gradleProperties["androidCompileSdkVersion"] = buildTargetSDK(target).split(QLatin1Char('-')).last().toLocal8Bit();
if (gradleProperties["androidBuildToolsVersion"].isEmpty()) {
QString maxVersion;
QDir buildToolsDir(AndroidConfigurations::currentConfig().sdkLocation().appendPath(QLatin1String("build-tools")).toString());
foreach (const QFileInfo &file, buildToolsDir.entryList(QDir::Dirs|QDir::NoDotAndDotDot)) {
QString ver(file.fileName());
if (maxVersion < ver)
maxVersion = ver;
}
if (maxVersion.isEmpty())
return false;
gradleProperties["androidBuildToolsVersion"] = maxVersion.toLocal8Bit();
}
return mergeGradleProperties(gradlePropertiesPath, gradleProperties);
}
} // namespace Android
......@@ -96,6 +96,8 @@ public:
static bool checkCertificatePassword(const QString &keystorePath, const QString &keystorePasswd, const QString &alias, const QString &certificatePasswd);
static bool checkForQt51Files(Utils::FileName fileName);
static AndroidQtSupport *androidQtSupport(ProjectExplorer::Target *target);
static bool useGradle(ProjectExplorer::Target *target);
static bool updateGradleProperties(ProjectExplorer::Target *target);
};
} // namespace Android
......
/**************************************************************************
**
** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: http://www.qt-project.org/legal
**
** 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "androidbuildapkstep.h"
#include "androidconstants.h"
#include "androidglobal.h"
#include "androidqtsupport.h"
#include <projectexplorer/target.h>
Utils::FileName Android::AndroidQtSupport::apkPath(ProjectExplorer::Target *target) const
{
if (!target)
return Utils::FileName();
AndroidBuildApkStep *buildApkStep
= Android::AndroidGlobal::buildStep<AndroidBuildApkStep>(target->activeBuildConfiguration());
if (!buildApkStep)
return Utils::FileName();
QString apkPath;
if (buildApkStep->useGradle())
apkPath = QLatin1String("/build/outputs/apk/android-build-");
else
apkPath = QLatin1String("/bin/QtApp-");
if (buildApkStep->buildConfiguration()->buildType() == ProjectExplorer::BuildConfiguration::Release) {
apkPath += QLatin1String("release-");
if (!buildApkStep->signPackage())
apkPath += QLatin1String("un");
apkPath += QLatin1String("signed.apk");
} else {
apkPath += QLatin1String("debug");
if (buildApkStep->signPackage())
apkPath += QLatin1String("-signed");
apkPath += QLatin1String(".apk");
}
return target->activeBuildConfiguration()->buildDirectory()
.appendPath(QLatin1String(Android::Constants::ANDROID_BUILDDIRECTORY))
.appendPath(apkPath);
}
......@@ -62,10 +62,9 @@ public:
virtual bool canHandle(const ProjectExplorer::Target *target) const = 0;
virtual QStringList soLibSearchPath(const ProjectExplorer::Target *target) const = 0;
virtual QStringList projectTargetApplications(const ProjectExplorer::Target *target) const = 0;
virtual Utils::FileName apkPath(ProjectExplorer::Target *target, BuildType buildType) const = 0;
virtual Utils::FileName apkPath(ProjectExplorer::Target *target) const;
virtual Utils::FileName androiddeployqtPath(ProjectExplorer::Target *target) const = 0;
virtual Utils::FileName androiddeployJsonPath(ProjectExplorer::Target *target) const = 0;