summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Teske <daniel.teske@digia.com>2013-09-17 18:24:57 +0200
committerDaniel Teske <daniel.teske@digia.com>2013-09-26 17:13:27 +0200
commit1262310798c699c13c2878c5eee66f94a6be8469 (patch)
tree18e7129681a0571dee91211e199669e50103c30c
parent455d597ac3cb6f1f6e1cc500c0a009df12cb4fcc (diff)
downloadqt-creator-1262310798c699c13c2878c5eee66f94a6be8469.tar.gz
Android: androiddeployqt support
Change-Id: I37d706b4e11c6e1353a8ee73378b7d080080678c Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
-rw-r--r--src/plugins/android/android.pro13
-rw-r--r--src/plugins/android/android.qbs7
-rw-r--r--src/plugins/android/androidconfigurations.cpp7
-rw-r--r--src/plugins/android/androidconfigurations.h1
-rw-r--r--src/plugins/android/androiddeployconfiguration.cpp27
-rw-r--r--src/plugins/android/androiddeployconfiguration.h4
-rw-r--r--src/plugins/android/androiddeployqtstep.cpp554
-rw-r--r--src/plugins/android/androiddeployqtstep.h160
-rw-r--r--src/plugins/android/androiddeployqtwidget.cpp314
-rw-r--r--src/plugins/android/androiddeployqtwidget.h86
-rw-r--r--src/plugins/android/androiddeployqtwidget.ui295
-rw-r--r--src/plugins/android/androiddeploystep.cpp72
-rw-r--r--src/plugins/android/androiddeploystep.h5
-rw-r--r--src/plugins/android/androiddeploystepwidget.cpp8
-rw-r--r--src/plugins/android/androiddeploystepwidget.ui2
-rw-r--r--src/plugins/android/androidmanager.cpp235
-rw-r--r--src/plugins/android/androidmanager.h8
-rw-r--r--src/plugins/android/androidpackagecreationstep.cpp42
-rw-r--r--src/plugins/android/androidpackagecreationwidget.ui2
-rw-r--r--src/plugins/android/androidpackageinstallationfactory.cpp27
-rw-r--r--src/plugins/android/androidpackageinstallationstep.cpp28
-rw-r--r--src/plugins/android/androidpackageinstallationstep.h7
-rw-r--r--src/plugins/android/androidplugin.cpp2
-rw-r--r--src/plugins/android/androidrunconfiguration.cpp10
-rw-r--r--src/plugins/android/androidrunconfiguration.h2
-rw-r--r--src/plugins/android/androidrunner.cpp15
-rw-r--r--src/plugins/android/certificatesmodel.cpp71
-rw-r--r--src/plugins/android/certificatesmodel.h56
-rw-r--r--src/plugins/qt4projectmanager/qt4nodes.cpp1
-rw-r--r--src/plugins/qt4projectmanager/qt4nodes.h3
30 files changed, 1876 insertions, 188 deletions
diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro
index afa6577723..3cb2e1de1e 100644
--- a/src/plugins/android/android.pro
+++ b/src/plugins/android/android.pro
@@ -42,7 +42,10 @@ HEADERS += \
androidmanifesteditor.h \
androidmanifesteditorwidget.h \
androidmanifestdocument.h \
- androiddevicedialog.h
+ androiddevicedialog.h \
+ androiddeployqtstep.h \
+ certificatesmodel.h \
+ androiddeployqtwidget.h
SOURCES += \
androidconfigurations.cpp \
@@ -79,7 +82,10 @@ SOURCES += \
androidmanifesteditor.cpp \
androidmanifesteditorwidget.cpp \
androidmanifestdocument.cpp \
- androiddevicedialog.cpp
+ androiddevicedialog.cpp \
+ androiddeployqtstep.cpp \
+ certificatesmodel.cpp \
+ androiddeployqtwidget.cpp
FORMS += \
androidsettingswidget.ui \
@@ -87,7 +93,8 @@ FORMS += \
androiddeploystepwidget.ui \
addnewavddialog.ui \
androidcreatekeystorecertificate.ui \
- androiddevicedialog.ui
+ androiddevicedialog.ui \
+ androiddeployqtwidget.ui
exists(../../shared/qbs/qbs.pro) {
HEADERS += \
diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs
index 8abc6e8110..13a4c91058 100644
--- a/src/plugins/android/android.qbs
+++ b/src/plugins/android/android.qbs
@@ -36,6 +36,8 @@ QtcPlugin {
"androidcreatekeystorecertificate.cpp",
"androidcreatekeystorecertificate.h",
"androidcreatekeystorecertificate.ui",
+ "androiddeployqtstep.cpp",
+ "androiddeployqtstep.h",
"androiddebugsupport.cpp",
"androiddebugsupport.h",
"androiddevicedialog.cpp",
@@ -50,6 +52,9 @@ QtcPlugin {
"androiddeploystepwidget.cpp",
"androiddeploystepwidget.h",
"androiddeploystepwidget.ui",
+ "androiddeployqtwidget.cpp",
+ "androiddeployqtwidget.h",
+ "androiddeployqtwidget.ui",
"androiddevice.cpp",
"androiddevice.h",
"androiddevicefactory.cpp",
@@ -103,6 +108,8 @@ QtcPlugin {
"androidsettingswidget.ui",
"androidtoolchain.cpp",
"androidtoolchain.h",
+ "certificatesmodel.cpp",
+ "certificatesmodel.h",
"javaparser.cpp",
"javaparser.h",
]
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index e0a3ed0048..fa71d84f90 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -715,6 +715,13 @@ QStringList AndroidConfigurations::getAbis(const QString &device) const
return result;
}
+QString AndroidConfigurations::highestAvailableAndroidPlatform() const
+{
+ if (m_availablePlatforms.isEmpty())
+ return QString();
+ return QLatin1String("android-") + QString::number(m_availablePlatforms.first());
+}
+
QString AndroidConfigurations::bestMatch(const QString &targetAPI) const
{
int target = targetAPI.mid(targetAPI.lastIndexOf(QLatin1Char('-')) + 1).toInt();
diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h
index 0b89957a4b..a8d044a205 100644
--- a/src/plugins/android/androidconfigurations.h
+++ b/src/plugins/android/androidconfigurations.h
@@ -124,6 +124,7 @@ public:
AndroidDeviceInfo showDeviceDialog(ProjectExplorer::Project *project, int apiLevel, const QString &abi);
void setDefaultDevice(ProjectExplorer::Project *project, const QString &abi, const QString &serialNumber); // serial number or avd name
QString defaultDevice(ProjectExplorer::Project *project, const QString &abi) const; // serial number or avd name
+ QString highestAvailableAndroidPlatform() const;
public slots:
void clearDefaultDevices(ProjectExplorer::Project *project);
diff --git a/src/plugins/android/androiddeployconfiguration.cpp b/src/plugins/android/androiddeployconfiguration.cpp
index 9c8305e3ab..ab1227d9c2 100644
--- a/src/plugins/android/androiddeployconfiguration.cpp
+++ b/src/plugins/android/androiddeployconfiguration.cpp
@@ -32,6 +32,7 @@
#include "androiddeploystep.h"
#include "androidpackageinstallationstep.h"
#include "androidpackagecreationstep.h"
+#include "androiddeployqtstep.h"
#include "androidmanager.h"
#include <projectexplorer/buildsteplist.h>
@@ -76,9 +77,15 @@ DeployConfiguration *AndroidDeployConfigurationFactory::create(Target *parent, c
AndroidDeployConfiguration *dc = new AndroidDeployConfiguration(parent, id);
if (!dc)
return 0;
- dc->stepList()->insertStep(0, new AndroidPackageInstallationStep(dc->stepList()));
- dc->stepList()->insertStep(1, new AndroidPackageCreationStep(dc->stepList()));
- dc->stepList()->insertStep(2, new AndroidDeployStep(dc->stepList()));
+
+ if (id == ANDROID_DEPLOYCONFIGURATION_ID) {
+ dc->stepList()->insertStep(0, new AndroidPackageInstallationStep(AndroidPackageInstallationStep::ProjectDirectory, dc->stepList()));
+ dc->stepList()->insertStep(1, new AndroidPackageCreationStep(dc->stepList()));
+ dc->stepList()->insertStep(2, new AndroidDeployStep(dc->stepList()));
+ } else {
+ dc->stepList()->insertStep(0, new AndroidPackageInstallationStep(AndroidPackageInstallationStep::BuildDirectory, dc->stepList()));
+ dc->stepList()->insertStep(1, new AndroidDeployQtStep(dc->stepList()));
+ }
return dc;
}
@@ -104,7 +111,7 @@ bool AndroidDeployConfigurationFactory::canClone(Target *parent, DeployConfigura
{
if (!AndroidManager::supportsAndroid(parent))
return false;
- return source->id() == ANDROID_DEPLOYCONFIGURATION_ID;
+ return canCreate(parent, source->id());
}
DeployConfiguration *AndroidDeployConfigurationFactory::clone(Target *parent, DeployConfiguration *source)
@@ -128,16 +135,20 @@ QList<Core::Id> AndroidDeployConfigurationFactory::availableCreationIds(Target *
if (!tc || tc->targetAbi().osFlavor() != Abi::AndroidLinuxFlavor)
return ids;
- if (QtSupport::QtKitInformation::qtVersion(parent->kit())->type() != QLatin1String(Constants::ANDROIDQT))
+ QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(parent->kit());
+ if (qt->type() != QLatin1String(Constants::ANDROIDQT))
return ids;
-
- ids << Core::Id(ANDROID_DEPLOYCONFIGURATION_ID);
+ if (qt->qtVersion() < QtSupport::QtVersionNumber(5, 2, 0))
+ ids << Core::Id(ANDROID_DEPLOYCONFIGURATION_ID);
+ else
+ ids << Core::Id(ANDROID_DEPLOYCONFIGURATION2_ID);
return ids;
}
QString AndroidDeployConfigurationFactory::displayNameForId(const Core::Id id) const
{
- if (id.name().startsWith(ANDROID_DC_PREFIX))
+ if (id.name().startsWith(ANDROID_DC_PREFIX)
+ || id.name().startsWith(ANDROID_DC2_PREFIX))
return tr("Deploy on Android");
return QString();
}
diff --git a/src/plugins/android/androiddeployconfiguration.h b/src/plugins/android/androiddeployconfiguration.h
index e464415548..654c5843c8 100644
--- a/src/plugins/android/androiddeployconfiguration.h
+++ b/src/plugins/android/androiddeployconfiguration.h
@@ -38,6 +38,10 @@ namespace Internal {
const char ANDROID_DEPLOYCONFIGURATION_ID[] = "Qt4ProjectManager.AndroidDeployConfiguration";
const char ANDROID_DC_PREFIX[] = "Qt4ProjectManager.AndroidDeployConfiguration.";
+// Qt 5.2 has a new form of deployment
+const char ANDROID_DEPLOYCONFIGURATION2_ID[] = "Qt4ProjectManager.AndroidDeployConfiguration2";
+const char ANDROID_DC2_PREFIX[] = "Qt4ProjectManager.AndroidDeployConfiguration2.";
+
class AndroidDeployConfiguration : public ProjectExplorer::DeployConfiguration
{
Q_OBJECT
diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp
new file mode 100644
index 0000000000..ea5d6eeac0
--- /dev/null
+++ b/src/plugins/android/androiddeployqtstep.cpp
@@ -0,0 +1,554 @@
+/**************************************************************************
+**
+** Copyright (c) 2013 BogDan Vatra <bog_dan_ro@yahoo.com>
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** 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 "androiddeployqtstep.h"
+#include "androiddeployqtwidget.h"
+#include "certificatesmodel.h"
+
+#include "javaparser.h"
+#include "androidmanager.h"
+
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+#include <coreplugin/fileutils.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/messagemanager.h>
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/target.h>
+#include <projectexplorer/project.h>
+#include <qtsupport/qtkitinformation.h>
+#include <qt4projectmanager/qt4buildconfiguration.h>
+#include <qt4projectmanager/qt4project.h>
+#include <qt4projectmanager/qt4nodes.h>
+#include <QInputDialog>
+#include <QMessageBox>
+
+using namespace Android;
+using namespace Android::Internal;
+
+const QLatin1String DeployActionKey("Qt4ProjectManager.AndroidDeployQtStep.DeployQtAction");
+const QLatin1String KeystoreLocationKey("KeystoreLocation");
+const QLatin1String SignPackageKey("SignPackage");
+const QLatin1String BuildTargetSdkKey("BuildTargetSdk");
+const QLatin1String VerboseOutputKey("VerboseOutput");
+const QLatin1String InputFile("InputFile");
+const Core::Id AndroidDeployQtStep::Id("Qt4ProjectManager.AndroidDeployQtStep");
+
+//////////////////
+// AndroidDeployQtStepFactory
+/////////////////
+
+AndroidDeployQtStepFactory::AndroidDeployQtStepFactory(QObject *parent)
+ : IBuildStepFactory(parent)
+{
+}
+
+QList<Core::Id> AndroidDeployQtStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
+{
+ if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
+ return QList<Core::Id>();
+ if (!AndroidManager::supportsAndroid(parent->target()))
+ return QList<Core::Id>();
+ if (parent->contains(AndroidDeployQtStep::Id))
+ return QList<Core::Id>();
+ return QList<Core::Id>() << AndroidDeployQtStep::Id;
+}
+
+QString AndroidDeployQtStepFactory::displayNameForId(const Core::Id id) const
+{
+ if (id == AndroidDeployQtStep::Id)
+ return tr("Deploy to Android device or emulator");
+ return QString();
+}
+
+bool AndroidDeployQtStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const
+{
+ return availableCreationIds(parent).contains(id);
+}
+
+ProjectExplorer::BuildStep *AndroidDeployQtStepFactory::create(ProjectExplorer::BuildStepList *parent, const Core::Id id)
+{
+ Q_ASSERT(canCreate(parent, id));
+ Q_UNUSED(id);
+ return new AndroidDeployQtStep(parent);
+}
+
+bool AndroidDeployQtStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const
+{
+ return canCreate(parent, ProjectExplorer::idFromMap(map));
+}
+
+ProjectExplorer::BuildStep *AndroidDeployQtStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map)
+{
+ Q_ASSERT(canRestore(parent, map));
+ AndroidDeployQtStep * const step = new AndroidDeployQtStep(parent);
+ if (!step->fromMap(map)) {
+ delete step;
+ return 0;
+ }
+ return step;
+}
+
+bool AndroidDeployQtStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const
+{
+ return canCreate(parent, product->id());
+}
+
+ProjectExplorer::BuildStep *AndroidDeployQtStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product)
+{
+ Q_ASSERT(canClone(parent, product));
+ return new AndroidDeployQtStep(parent, static_cast<AndroidDeployQtStep *>(product));
+}
+
+//////////////////
+// AndroidDeployQtStep
+/////////////////
+
+AndroidDeployQtStep::AndroidDeployQtStep(ProjectExplorer::BuildStepList *parent)
+ : ProjectExplorer::AbstractProcessStep(parent, Id)
+{
+ ctor();
+}
+
+AndroidDeployQtStep::AndroidDeployQtStep(ProjectExplorer::BuildStepList *parent,
+ AndroidDeployQtStep *other)
+ : ProjectExplorer::AbstractProcessStep(parent, other)
+{
+ ctor();
+}
+
+void AndroidDeployQtStep::ctor()
+{
+ //: AndroidDeployQtStep default display name
+ setDefaultDisplayName(tr("Deploy to Android device"));
+ m_deployAction = BundleLibrariesDeployment;
+ m_signPackage = false;
+ m_openPackageLocation = false;
+ m_verbose = false;
+
+ // will be overwriten by settings if the user choose something different
+ m_buildTargetSdk = AndroidConfigurations::instance().highestAvailableAndroidPlatform();
+
+ connect(project(), SIGNAL(proFilesEvaluated()),
+ this, SLOT(updateInputFile()));
+}
+
+bool AndroidDeployQtStep::init()
+{
+ if (AndroidManager::checkForQt51Files(project()->projectDirectory()))
+ emit addOutput(tr("Found old android folder in source directory. Qt 5.2 does not use that folder by default."), ErrorOutput);
+
+ m_targetArch = AndroidManager::targetArch(target());
+ m_deviceAPILevel = AndroidManager::minimumSDK(target());
+ AndroidDeviceInfo info = AndroidConfigurations::instance().showDeviceDialog(project(), m_deviceAPILevel, m_targetArch);
+ if (info.serialNumber.isEmpty()) // aborted
+ return false;
+
+ if (info.type == AndroidDeviceInfo::Emulator) {
+ m_avdName = info.serialNumber;
+ m_serialNumber.clear();
+ m_deviceAPILevel = info.sdk;
+ } else {
+ m_avdName.clear();
+ m_serialNumber = info.serialNumber;
+ }
+
+ Qt4ProjectManager::Qt4BuildConfiguration *bc
+ = static_cast<Qt4ProjectManager::Qt4BuildConfiguration *>(target()->activeBuildConfiguration());
+
+ if (m_signPackage) {
+ // check keystore and certificate passwords
+ while (!AndroidManager::checkKeystorePassword(m_keystorePath.toString(), m_keystorePasswd)) {
+ if (!keystorePassword())
+ return false; // user canceled
+ }
+
+ while (!AndroidManager::checkCertificatePassword(m_keystorePath.toString(), m_keystorePasswd, m_certificateAlias, m_certificatePasswd)) {
+ if (!certificatePassword())
+ return false; // user canceled
+ }
+
+
+ if ((bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild))
+ emit addOutput(tr("Warning: Signing a debug package."), BuildStep::ErrorMessageOutput);
+ }
+
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
+ if (!version)
+ return false;
+
+ ProjectExplorer::Project *project = target()->project();
+ JavaParser *parser = new JavaParser;
+ parser->setProjectFileList(project->files(ProjectExplorer::Project::AllFiles));
+ setOutputParser(parser);
+
+ QString command = version->qmakeProperty("QT_HOST_BINS");
+ if (!command.endsWith(QLatin1Char('/')))
+ command += QLatin1Char('/');
+ command += QLatin1String("androiddeployqt");
+ if (Utils::HostOsInfo::isWindowsHost())
+ command += QLatin1String(".exe");
+
+ QString deploymentMethod;
+ if (m_deployAction == MinistroDeployment)
+ deploymentMethod = QLatin1String("ministro");
+ else if (m_deployAction == DebugDeployment)
+ deploymentMethod = QLatin1String("debug");
+ else if (m_deployAction == BundleLibrariesDeployment)
+ deploymentMethod = QLatin1String("bundled");
+
+ QString outputDir = bc->buildDirectory().appendPath(QLatin1String("android")).toString();
+
+ QStringList arguments;
+ arguments << QLatin1String("--input")
+ << m_inputFile
+ << QLatin1String("--output")
+ << outputDir
+ << QLatin1String("--deployment")
+ << deploymentMethod
+ << QLatin1String("--install")
+ << QLatin1String("--ant")
+ << AndroidConfigurations::instance().antToolPath().toString()
+ << QLatin1String("--android-platform")
+ << m_buildTargetSdk
+ << QLatin1String("--jdk")
+ << AndroidConfigurations::instance().openJDKPath().toString();
+
+ if (m_verbose)
+ arguments << QLatin1String("--verbose");
+ if (m_avdName.isEmpty())
+ arguments << QLatin1String("--device")
+ << info.serialNumber;
+
+ if (m_signPackage) {
+ arguments << QLatin1String("--sign")
+ << m_keystorePath.toString()
+ << m_certificateAlias
+ << QLatin1String("--storepass")
+ << m_keystorePasswd;
+ if (!m_certificatePasswd.isEmpty())
+ arguments << QLatin1String("--keypass")
+ << m_certificatePasswd;
+ }
+
+ ProjectExplorer::ProcessParameters *pp = processParameters();
+ pp->setMacroExpander(bc->macroExpander());
+ pp->setWorkingDirectory(bc->buildDirectory().toString());
+ Utils::Environment env = bc->environment();
+ // Force output to english for the parsers. Do this here and not in the toolchain's
+ // addToEnvironment() to not screw up the users run environment.
+ env.set(QLatin1String("LC_ALL"), QLatin1String("C"));
+ pp->setEnvironment(env);
+ pp->setCommand(command);
+ pp->setArguments(Utils::QtcProcess::joinArgs(arguments));
+ pp->resolveAll();
+
+ m_openPackageLocationForRun = m_openPackageLocation;
+ m_apkPath = AndroidManager::apkPath(target(), m_signPackage ? AndroidManager::ReleaseBuildSigned
+ : AndroidManager::DebugBuild).toString();
+ m_buildDirectory = bc->buildDirectory().toString();
+
+ bool result = AbstractProcessStep::init();
+ if (!result)
+ return false;
+
+ AndroidConfigurations::instance().startAVDAsync(m_avdName);
+ return true;
+}
+
+void AndroidDeployQtStep::run(QFutureInterface<bool> &fi)
+{
+ if (!m_avdName.isEmpty()) {
+ QString serialNumber = AndroidConfigurations::instance().waitForAvd(m_deviceAPILevel, m_targetArch);
+ if (serialNumber.isEmpty()) {
+ fi.reportResult(false);
+ return;
+ }
+ m_serialNumber = serialNumber;
+ QString args = processParameters()->arguments();
+ Utils::QtcProcess::addArg(&args, QLatin1String("--device"));
+ Utils::QtcProcess::addArg(&args, serialNumber);
+ processParameters()->setArguments(args);
+ }
+
+ AbstractProcessStep::run(fi);
+
+ emit addOutput(tr("Pulling files necessary for debugging."), MessageOutput);
+ runCommand(AndroidConfigurations::instance().adbToolPath().toString(),
+ AndroidDeviceInfo::adbSelector(m_serialNumber)
+ << QLatin1String("pull") << QLatin1String("/system/bin/app_process")
+ << QString::fromLatin1("%1/app_process").arg(m_buildDirectory));
+ runCommand(AndroidConfigurations::instance().adbToolPath().toString(),
+ AndroidDeviceInfo::adbSelector(m_serialNumber) << QLatin1String("pull")
+ << QLatin1String("/system/lib/libc.so")
+ << QString::fromLatin1("%1/libc.so").arg(m_buildDirectory));
+}
+
+void AndroidDeployQtStep::runCommand(const QString &program, const QStringList &arguments)
+{
+ QProcess buildProc;
+ emit addOutput(tr("Package deploy: Running command '%1 %2'.").arg(program).arg(arguments.join(QLatin1String(" "))), BuildStep::MessageOutput);
+ buildProc.start(program, arguments);
+ if (!buildProc.waitForStarted()) {
+ emit addOutput(tr("Packaging error: Could not start command '%1 %2'. Reason: %3")
+ .arg(program).arg(arguments.join(QLatin1String(" "))).arg(buildProc.errorString()), BuildStep::ErrorMessageOutput);
+ return;
+ }
+ if (!buildProc.waitForFinished(2 * 60 * 1000)
+ || buildProc.error() != QProcess::UnknownError
+ || buildProc.exitCode() != 0) {
+ QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.")
+ .arg(program).arg(arguments.join(QLatin1String(" ")));
+ if (buildProc.error() != QProcess::UnknownError)
+ mainMessage += tr(" Reason: %1").arg(buildProc.errorString());
+ else
+ mainMessage += tr("Exit code: %1").arg(buildProc.exitCode());
+ emit addOutput(mainMessage, BuildStep::ErrorMessageOutput);
+ }
+}
+
+void AndroidDeployQtStep::updateInputFile()
+{
+ Qt4ProjectManager::Qt4Project *pro = static_cast<Qt4ProjectManager::Qt4Project *>(project());
+ QList<Qt4ProjectManager::Qt4ProFileNode *> nodes = pro->applicationProFiles();
+
+ QStringList inputFiles;
+ foreach (Qt4ProjectManager::Qt4ProFileNode *node, nodes)
+ inputFiles << node->singleVariableValue(Qt4ProjectManager::AndroidDeploySettingsFile);
+
+ if (!inputFiles.contains(m_inputFile))
+ m_inputFile.clear();
+
+ if (m_inputFile.isEmpty()) {
+ // not yet selected one or no longer exists
+ if (!inputFiles.isEmpty())
+ m_inputFile = inputFiles.first();
+ }
+
+ emit inputFileChanged();
+}
+
+void AndroidDeployQtStep::showInGraphicalShell()
+{
+ Core::FileUtils::showInGraphicalShell(Core::ICore::instance()->mainWindow(), m_apkPath);
+}
+
+ProjectExplorer::BuildStepConfigWidget *AndroidDeployQtStep::createConfigWidget()
+{
+ return new AndroidDeployQtWidget(this);
+}
+
+void AndroidDeployQtStep::processFinished(int exitCode, QProcess::ExitStatus status)
+{
+ AbstractProcessStep::processFinished(exitCode, status);
+ if (m_openPackageLocationForRun)
+ QMetaObject::invokeMethod(this, "showInGraphicalShell", Qt::QueuedConnection);
+}
+
+bool AndroidDeployQtStep::fromMap(const QVariantMap &map)
+{
+ m_deployAction = AndroidDeployQtAction(map.value(QLatin1String(DeployActionKey),
+ BundleLibrariesDeployment).toInt());
+ m_keystorePath = Utils::FileName::fromString(map.value(KeystoreLocationKey).toString());
+ m_signPackage = map.value(SignPackageKey).toBool();
+ m_buildTargetSdk = map.value(BuildTargetSdkKey).toString();
+ m_verbose = map.value(VerboseOutputKey).toBool();
+ m_inputFile = map.value(InputFile).toString();
+ return ProjectExplorer::BuildStep::fromMap(map);
+}
+
+QVariantMap AndroidDeployQtStep::toMap() const
+{
+ QVariantMap map = ProjectExplorer::BuildStep::toMap();
+ map.insert(QLatin1String(DeployActionKey), m_deployAction);
+ map.insert(KeystoreLocationKey, m_keystorePath.toString());
+ map.insert(SignPackageKey, m_signPackage);
+ map.insert(BuildTargetSdkKey, m_buildTargetSdk);
+ map.insert(VerboseOutputKey, m_verbose);
+ map.insert(InputFile, m_inputFile);
+ return map;
+}
+
+void AndroidDeployQtStep::setBuildTargetSdk(const QString &sdk)
+{
+ m_buildTargetSdk = sdk;
+}
+
+QString AndroidDeployQtStep::buildTargetSdk() const
+{
+ return m_buildTargetSdk;
+}
+
+Utils::FileName AndroidDeployQtStep::keystorePath()
+{
+ return m_keystorePath;
+}
+
+AndroidDeployQtStep::AndroidDeployQtAction AndroidDeployQtStep::deployAction() const
+{
+ return m_deployAction;
+}
+
+void AndroidDeployQtStep::setDeployAction(AndroidDeployQtStep::AndroidDeployQtAction deploy)
+{
+ m_deployAction = deploy;
+}
+
+void AndroidDeployQtStep::setKeystorePath(const Utils::FileName &path)
+{
+ m_keystorePath = path;
+ m_certificatePasswd.clear();
+ m_keystorePasswd.clear();
+}
+
+void AndroidDeployQtStep::setKeystorePassword(const QString &pwd)
+{
+ m_keystorePasswd = pwd;
+}
+
+void AndroidDeployQtStep::setCertificateAlias(const QString &alias)
+{
+ m_certificateAlias = alias;
+}
+
+void AndroidDeployQtStep::setCertificatePassword(const QString &pwd)
+{
+ m_certificatePasswd = pwd;
+}
+
+bool AndroidDeployQtStep::signPackage() const
+{
+ return m_signPackage;
+}
+
+void AndroidDeployQtStep::setSignPackage(bool b)
+{
+ m_signPackage = b;
+}
+
+QString AndroidDeployQtStep::deviceSerialNumber()
+{
+ return m_serialNumber;
+}
+
+bool AndroidDeployQtStep::openPackageLocation() const
+{
+ return m_openPackageLocation;
+}
+
+void AndroidDeployQtStep::setOpenPackageLocation(bool open)
+{
+ m_openPackageLocation = open;
+}
+
+void AndroidDeployQtStep::setVerboseOutput(bool verbose)
+{
+ m_verbose = verbose;
+}
+
+QString AndroidDeployQtStep::inputFile() const
+{
+ return m_inputFile;
+}
+
+void AndroidDeployQtStep::setInputFile(const QString &file)
+{
+ m_inputFile = file;
+}
+
+bool AndroidDeployQtStep::verboseOutput() const
+{
+ return m_verbose;
+}
+
+// Note this functions is duplicated between AndroidDeployStep and AndroidDeployQtStep
+// since it does modify the stored password in AndroidDeployQtStep it's not easily
+// extractable. The situation will clean itself up once AndroidDeployStep is no longer
+// necessary
+QAbstractItemModel *AndroidDeployQtStep::keystoreCertificates()
+{
+ QString rawCerts;
+ QProcess keytoolProc;
+ while (!rawCerts.length() || !m_keystorePasswd.length()) {
+ QStringList params;
+ params << QLatin1String("-list") << QLatin1String("-v") << QLatin1String("-keystore") << m_keystorePath.toUserOutput() << QLatin1String("-storepass");
+ if (!m_keystorePasswd.length())
+ keystorePassword();
+ if (!m_keystorePasswd.length())
+ return 0;
+ params << m_keystorePasswd;
+ Utils::Environment env = Utils::Environment::systemEnvironment();
+ env.set(QLatin1String("LANG"), QLatin1String("C"));
+ keytoolProc.setProcessEnvironment(env.toProcessEnvironment());
+ keytoolProc.start(AndroidConfigurations::instance().keytoolPath().toString(), params);
+ if (!keytoolProc.waitForStarted() || !keytoolProc.waitForFinished()) {
+ QMessageBox::critical(0, tr("Error"),
+ tr("Failed to run keytool"));
+ return 0;
+ }
+
+ if (keytoolProc.exitCode()) {
+ QMessageBox::critical(0, tr("Error"),
+ tr("Invalid password"));
+ m_keystorePasswd.clear();
+ }
+ rawCerts = QString::fromLatin1(keytoolProc.readAllStandardOutput());
+ }
+ return new CertificatesModel(rawCerts, this);
+}
+
+bool AndroidDeployQtStep::keystorePassword()
+{
+ m_keystorePasswd.clear();
+ bool ok;
+ QString text = QInputDialog::getText(0, tr("Keystore"),
+ tr("Keystore password:"), QLineEdit::Password,
+ QString(), &ok);
+ if (ok && !text.isEmpty()) {
+ m_keystorePasswd = text;
+ return true;
+ }
+ return false;
+}
+
+bool AndroidDeployQtStep::certificatePassword()
+{
+ m_certificatePasswd.clear();
+ bool ok;
+ QString text = QInputDialog::getText(0, tr("Certificate"),
+ tr("Certificate password (%1):").arg(m_certificateAlias), QLineEdit::Password,
+ QString(), &ok);
+ if (ok && !text.isEmpty()) {
+ m_certificatePasswd = text;
+ return true;
+ }
+ return false;
+}
diff --git a/src/plugins/android/androiddeployqtstep.h b/src/plugins/android/androiddeployqtstep.h
new file mode 100644
index 0000000000..d51a46e60e
--- /dev/null
+++ b/src/plugins/android/androiddeployqtstep.h
@@ -0,0 +1,160 @@
+/**************************************************************************
+**
+** Copyright (c) 2013 BogDan Vatra <bog_dan_ro@yahoo.com>
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** 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.
+**
+****************************************************************************/
+
+#ifndef ANDROIDDEPLOYQTSTEP_H
+#define ANDROIDDEPLOYQTSTEP_H
+
+#include "androidconfigurations.h"
+
+#include <projectexplorer/abstractprocessstep.h>
+#include <qtsupport/baseqtversion.h>
+
+QT_BEGIN_NAMESPACE
+class QAbstractItemModel;
+QT_END_NAMESPACE
+
+namespace Android {
+namespace Internal {
+
+class AndroidDeployQtStepFactory : public ProjectExplorer::IBuildStepFactory
+{
+ Q_OBJECT
+public:
+ explicit AndroidDeployQtStepFactory(QObject *parent = 0);
+
+ QList<Core::Id> availableCreationIds(ProjectExplorer::BuildStepList *parent) const;
+ QString displayNameForId(const Core::Id id) const;
+
+ bool canCreate(ProjectExplorer::BuildStepList *parent,
+ const Core::Id id) const;
+ ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, const Core::Id id);
+
+ bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const;
+ ProjectExplorer::BuildStep *restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map);
+
+ bool canClone(ProjectExplorer::BuildStepList *parent,
+ ProjectExplorer::BuildStep *product) const;
+ ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildStepList *parent,
+ ProjectExplorer::BuildStep *product);
+};
+
+class AndroidDeployQtStep : public ProjectExplorer::AbstractProcessStep
+{
+ Q_OBJECT
+ friend class AndroidDeployQtStepFactory;
+public:
+ AndroidDeployQtStep(ProjectExplorer::BuildStepList *bc);
+
+ enum AndroidDeployQtAction
+ {
+ MinistroDeployment, // use ministro
+ DebugDeployment,
+ BundleLibrariesDeployment
+ };
+
+ bool fromMap(const QVariantMap &map);
+ QVariantMap toMap() const;
+
+ AndroidDeployQtStep::AndroidDeployQtAction deployAction() const;
+ QString deviceSerialNumber();
+
+ void setBuildTargetSdk(const QString &sdk);
+ QString buildTargetSdk() const;
+
+ // signing
+ Utils::FileName keystorePath();
+ void setKeystorePath(const Utils::FileName &path);
+ void setKeystorePassword(const QString &pwd);
+ void setCertificateAlias(const QString &alias);
+ void setCertificatePassword(const QString &pwd);
+
+ QAbstractItemModel *keystoreCertificates();
+ bool signPackage() const;
+ void setSignPackage(bool b);
+
+ bool openPackageLocation() const;
+ void setOpenPackageLocation(bool open);
+ bool verboseOutput() const;
+ void setVerboseOutput(bool verbose);
+
+ QString inputFile() const;
+ void setInputFile(const QString &file);
+
+signals:
+ // also on purpose emitted if the possible values of this changed
+ void inputFileChanged();
+
+public slots:
+ void setDeployAction(AndroidDeployQtAction deploy); // slot?
+
+private slots:
+ void showInGraphicalShell();
+
+ void updateInputFile();
+private:
+ AndroidDeployQtStep(ProjectExplorer::BuildStepList *bc,
+ AndroidDeployQtStep *other);
+ void ctor();
+ bool keystorePassword();
+ bool certificatePassword();
+ void runCommand(const QString &program, const QStringList &arguments);
+
+ bool init();
+ void run(QFutureInterface<bool> &fi);
+ ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
+ bool immutable() const { return true; }
+ void processFinished(int exitCode, QProcess::ExitStatus status);
+
+ QString m_buildTargetSdk;
+ QString m_serialNumber;
+ AndroidDeployQtAction m_deployAction;
+ bool m_signPackage;
+ bool m_verbose;
+ bool m_openPackageLocation;
+ bool m_openPackageLocationForRun;
+ QString m_buildDirectory;
+
+ Utils::FileName m_keystorePath;
+ QString m_keystorePasswd;
+ QString m_certificateAlias;
+ QString m_certificatePasswd;
+ QString m_avdName;
+ QString m_apkPath;
+ QString m_targetArch;
+ QString m_inputFile;
+ int m_deviceAPILevel;
+
+ static const Core::Id Id;
+};
+
+}
+}
+
+#endif // ANDROIDDEPLOYQTSTEP_H
diff --git a/src/plugins/android/androiddeployqtwidget.cpp b/src/plugins/android/androiddeployqtwidget.cpp
new file mode 100644
index 0000000000..d6234b9932
--- /dev/null
+++ b/src/plugins/android/androiddeployqtwidget.cpp
@@ -0,0 +1,314 @@
+/**************************************************************************
+**
+** Copyright (c) 2013 BogDan Vatra <bog_dan_ro@yahoo.com>
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** 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 "androiddeployqtwidget.h"
+#include "ui_androiddeployqtwidget.h"
+
+#include "androidcreatekeystorecertificate.h"
+#include "androiddeployqtstep.h"
+#include "androidmanager.h"
+
+#include <projectexplorer/target.h>
+#include <qt4projectmanager/qt4buildconfiguration.h>
+#include <qt4projectmanager/qt4project.h>
+#include <qt4projectmanager/qt4nodes.h>
+
+#include <QFileDialog>
+
+#include <algorithm>
+
+
+using namespace Android;
+using namespace Internal;
+
+AndroidDeployQtWidget::AndroidDeployQtWidget(AndroidDeployQtStep *step)
+ : ProjectExplorer::BuildStepConfigWidget(),
+ m_ui(new Ui::AndroidDeployQtWidget),
+ m_step(step),
+ m_currentBuildConfiguration(0),
+ m_ignoreChange(false)
+{
+ m_ui->setupUi(this);
+
+ // Target sdk combobox
+ int minApiLevel = 9;
+ QStringList targets = AndroidConfigurations::instance().sdkTargets(minApiLevel);
+ m_ui->targetSDKComboBox->addItems(targets);
+ m_ui->targetSDKComboBox->setCurrentIndex(targets.indexOf(step->buildTargetSdk()));
+
+ // deployment option
+ switch (m_step->deployAction()) {
+ case AndroidDeployQtStep::MinistroDeployment:
+ m_ui->ministroOption->setChecked(true);
+ break;
+ case AndroidDeployQtStep::DebugDeployment:
+ m_ui->temporaryQtOption->setChecked(true);
+ break;
+ case AndroidDeployQtStep::BundleLibrariesDeployment:
+ m_ui->bundleQtOption->setChecked(true);
+ break;
+ default:
+ // can't happen
+ break;
+ }
+
+ // signing
+ m_ui->KeystoreLocationLineEdit->setText(m_step->keystorePath().toUserOutput());
+ m_ui->signingDebugWarningIcon->hide();
+ m_ui->signingDebugWarningLabel->hide();
+
+ m_ui->verboseOutputCheckBox->setChecked(m_step->verboseOutput());
+ m_ui->openPackageLocationCheckBox->setChecked(m_step->openPackageLocation());
+
+ bool oldFiles = AndroidManager::checkForQt51Files(m_step->project()->projectDirectory());
+ m_ui->oldFilesWarningIcon->setVisible(oldFiles);
+ m_ui->oldFilesWarningLabel->setVisible(oldFiles);
+
+ // target sdk
+ connect(m_ui->targetSDKComboBox, SIGNAL(activated(QString)), SLOT(setTargetSdk(QString)));
+
+ // deployment options
+ connect(m_ui->ministroOption, SIGNAL(clicked()), SLOT(setMinistro()));
+ connect(m_ui->temporaryQtOption, SIGNAL(clicked()), SLOT(setDeployLocalQtLibs()));
+ connect(m_ui->bundleQtOption, SIGNAL(clicked()), SLOT(setBundleQtLibs()));
+
+ connect(m_ui->installMinistroButton, SIGNAL(clicked()), SLOT(installMinistro()));
+ connect(m_ui->cleanLibsPushButton, SIGNAL(clicked()), SLOT(cleanLibsOnDevice()));
+ connect(m_ui->resetDefaultDevices, SIGNAL(clicked()), SLOT(resetDefaultDevices()));
+ connect(m_ui->openPackageLocationCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(openPackageLocationCheckBoxToggled(bool)));
+ connect(m_ui->verboseOutputCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(verboseOutputCheckBoxToggled(bool)));
+
+ //signing
+ connect(m_ui->signPackageCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(signPackageCheckBoxToggled(bool)));
+ connect(m_ui->KeystoreCreatePushButton, SIGNAL(clicked()),
+ this, SLOT(createKeyStore()));
+ connect(m_ui->KeystoreLocationPushButton, SIGNAL(clicked()),
+ this, SLOT(browseKeyStore()));
+ connect(m_ui->certificatesAliasComboBox, SIGNAL(activated(QString)),
+ this, SLOT(certificatesAliasComboBoxActivated(QString)));
+ connect(m_ui->certificatesAliasComboBox, SIGNAL(currentIndexChanged(QString)),
+ this, SLOT(certificatesAliasComboBoxCurrentIndexChanged(QString)));
+
+ activeBuildConfigurationChanged();
+ connect(m_step->target(), SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
+ this, SLOT(activeBuildConfigurationChanged()));
+
+ connect(m_ui->inputFileComboBox, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(inputFileComboBoxIndexChanged()));
+
+ updateInputFileUi();
+ connect(m_step, SIGNAL(inputFileChanged()),
+ this, SLOT(updateInputFileUi()));
+}
+
+AndroidDeployQtWidget::~AndroidDeployQtWidget()
+{
+ delete m_ui;
+}
+
+void AndroidDeployQtWidget::updateInputFileUi()
+{
+ Qt4ProjectManager::Qt4Project *project
+ = static_cast<Qt4ProjectManager::Qt4Project *>(m_step->project());
+ QList<Qt4ProjectManager::Qt4ProFileNode *> nodes = project->applicationProFiles();
+ int size = nodes.size();
+ if (size == 0 || size == 1) {
+ // there's nothing to select, e.g. before parsing
+ m_ui->inputFileLabel->setVisible(false);
+ m_ui->inputFileComboBox->setVisible(false);
+ } else {
+ m_ignoreChange = true;
+ m_ui->inputFileLabel->setVisible(true);
+ m_ui->inputFileComboBox->setVisible(true);
+
+ m_ui->inputFileComboBox->clear();
+ foreach (Qt4ProjectManager::Qt4ProFileNode *node, nodes) {
+ QString file = node->singleVariableValue(Qt4ProjectManager::AndroidDeploySettingsFile);
+ m_ui->inputFileComboBox->addItem(node->displayName(), file);
+ }
+
+ int index = m_ui->inputFileComboBox->findData(m_step->inputFile());
+ m_ui->inputFileComboBox->setCurrentIndex(index);
+ m_ignoreChange = false;
+ }
+}
+
+void AndroidDeployQtWidget::inputFileComboBoxIndexChanged()
+{
+ if (m_ignoreChange)
+ return;
+ QString text = m_ui->inputFileComboBox->currentData().toString();
+ m_step->setInputFile(text);
+}
+
+QString AndroidDeployQtWidget::displayName() const
+{
+ return tr("<b>Deploy configurations</b>");
+}
+
+QString AndroidDeployQtWidget::summaryText() const
+{
+ return displayName();
+}
+
+void AndroidDeployQtWidget::setTargetSdk(const QString &sdk)
+{
+ m_step->setBuildTargetSdk(sdk);
+}
+
+void AndroidDeployQtWidget::setMinistro()
+{
+ m_step->setDeployAction(AndroidDeployQtStep::MinistroDeployment);
+}
+
+void AndroidDeployQtWidget::setDeployLocalQtLibs()
+{
+ m_step->setDeployAction(AndroidDeployQtStep::DebugDeployment);
+}
+
+void AndroidDeployQtWidget::setBundleQtLibs()
+{
+ m_step->setDeployAction(AndroidDeployQtStep::BundleLibrariesDeployment);
+}
+
+void AndroidDeployQtWidget::installMinistro()
+{
+ QString packagePath =
+ QFileDialog::getOpenFileName(this, tr("Qt Android Smart Installer"),
+ QDir::homePath(), tr("Android package (*.apk)"));
+ if (!packagePath.isEmpty())
+ AndroidManager::installQASIPackage(m_step->target(), packagePath);
+}
+
+void AndroidDeployQtWidget::cleanLibsOnDevice()
+{
+ AndroidManager::cleanLibsOnDevice(m_step->target());
+}
+
+void AndroidDeployQtWidget::resetDefaultDevices()
+{
+ AndroidConfigurations::instance().clearDefaultDevices(m_step->project());
+}
+
+void AndroidDeployQtWidget::signPackageCheckBoxToggled(bool checked)
+{
+ m_ui->certificatesAliasComboBox->setEnabled(checked);
+ m_step->setSignPackage(checked);
+ updateSigningWarning();
+ if (!checked)
+ return;
+ if (!m_step->keystorePath().isEmpty())
+ setCertificates();
+}
+
+void AndroidDeployQtWidget::createKeyStore()
+{
+ AndroidCreateKeystoreCertificate d;
+ if (d.exec() != QDialog::Accepted)
+ return;
+ m_ui->KeystoreLocationLineEdit->setText(d.keystoreFilePath().toUserOutput());
+ m_step->setKeystorePath(d.keystoreFilePath());
+ m_step->setKeystorePassword(d.keystorePassword());
+ m_step->setCertificateAlias(d.certificateAlias());
+ m_step->setCertificatePassword(d.certificatePassword());
+ setCertificates();
+}
+
+void AndroidDeployQtWidget::setCertificates()
+{
+ QAbstractItemModel *certificates = m_step->keystoreCertificates();
+ m_ui->signPackageCheckBox->setChecked(certificates);
+ m_ui->certificatesAliasComboBox->setModel(certificates);
+}
+
+void AndroidDeployQtWidget::browseKeyStore()
+{
+ Utils::FileName keystorePath = m_step->keystorePath();
+ if (keystorePath.isEmpty())
+ keystorePath = Utils::FileName::fromString(QDir::homePath());
+ Utils::FileName file = Utils::FileName::fromString(QFileDialog::getOpenFileName(this, tr("Select keystore file"), keystorePath.toString(), tr("Keystore files (*.keystore *.jks)")));
+ if (file.isEmpty())
+ return;
+ m_ui->KeystoreLocationLineEdit->setText(file.toUserOutput());
+ m_step->setKeystorePath(file);
+ m_ui->signPackageCheckBox->setChecked(false);
+}
+
+void AndroidDeployQtWidget::certificatesAliasComboBoxActivated(const QString &alias)
+{
+ if (alias.length())
+ m_step->setCertificateAlias(alias);
+}
+
+void AndroidDeployQtWidget::certificatesAliasComboBoxCurrentIndexChanged(const QString &alias)
+{
+ if (alias.length())
+ m_step->setCertificateAlias(alias);
+}
+
+void AndroidDeployQtWidget::openPackageLocationCheckBoxToggled(bool checked)
+{
+ m_step->setOpenPackageLocation(checked);
+}
+
+void AndroidDeployQtWidget::verboseOutputCheckBoxToggled(bool checked)
+{
+ m_step->setVerboseOutput(checked);
+}
+
+void AndroidDeployQtWidget::activeBuildConfigurationChanged()
+{
+ if (m_currentBuildConfiguration)
+ disconnect(m_currentBuildConfiguration, SIGNAL(qmakeBuildConfigurationChanged()),
+ this, SLOT(updateSigningWarning()));
+ updateSigningWarning();
+ Qt4ProjectManager::Qt4BuildConfiguration *bc
+ = qobject_cast<Qt4ProjectManager::Qt4BuildConfiguration *>(m_step->target()->activeBuildConfiguration());
+ m_currentBuildConfiguration = bc;
+ if (bc)
+ connect(bc, SIGNAL(qmakeBuildConfigurationChanged()), this, SLOT(updateSigningWarning()));
+ m_currentBuildConfiguration = bc;
+}
+
+void AndroidDeployQtWidget::updateSigningWarning()
+{
+ Qt4ProjectManager::Qt4BuildConfiguration *bc = qobject_cast<Qt4ProjectManager::Qt4BuildConfiguration *>(m_step->target()->activeBuildConfiguration());
+ bool debug = bc && (bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild);
+ if (m_step->signPackage() && debug) {
+ m_ui->signingDebugWarningIcon->setVisible(true);
+ m_ui->signingDebugWarningLabel->setVisible(true);
+ } else {
+ m_ui->signingDebugWarningIcon->setVisible(false);
+ m_ui->signingDebugWarningLabel->setVisible(false);
+ }
+}
diff --git a/src/plugins/android/androiddeployqtwidget.h b/src/plugins/android/androiddeployqtwidget.h
new file mode 100644
index 0000000000..e8b652ffb5
--- /dev/null
+++ b/src/plugins/android/androiddeployqtwidget.h
@@ -0,0 +1,86 @@
+/**************************************************************************
+**
+** Copyright (c) 2013 BogDan Vatra <bog_dan_ro@yahoo.com>
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** 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.
+**
+****************************************************************************/
+#ifndef ANDROIDDEPLOYQTWIDGET_H
+#define ANDROIDDEPLOYQTWIDGET_H
+
+#include <projectexplorer/buildstep.h>
+
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class AndroidDeployQtWidget; }
+QT_END_NAMESPACE
+
+namespace Qt4ProjectManager { class Qt4BuildConfiguration; }
+
+namespace Android {
+namespace Internal {
+class AndroidDeployQtStep;
+class AndroidDeployQtWidget : public ProjectExplorer::BuildStepConfigWidget
+{
+ Q_OBJECT
+
+public:
+ AndroidDeployQtWidget(AndroidDeployQtStep *step);
+ ~AndroidDeployQtWidget();
+
+private slots:
+ void setTargetSdk(const QString &sdk);
+ void setMinistro();
+ void setDeployLocalQtLibs();
+ void setBundleQtLibs();
+ void installMinistro();
+ void cleanLibsOnDevice();
+ void resetDefaultDevices();
+ void createKeyStore();
+ void certificatesAliasComboBoxCurrentIndexChanged(const QString &alias);
+ void certificatesAliasComboBoxActivated(const QString &alias);
+ void activeBuildConfigurationChanged();
+ void updateSigningWarning();
+ void openPackageLocationCheckBoxToggled(bool checked);
+ void verboseOutputCheckBoxToggled(bool checked);
+ void browseKeyStore();
+ void signPackageCheckBoxToggled(bool checked);
+ void updateInputFileUi();
+ void inputFileComboBoxIndexChanged();
+private:
+ virtual QString summaryText() const;
+ virtual QString displayName() const;
+ void setCertificates();
+
+ Ui::AndroidDeployQtWidget *m_ui;
+ AndroidDeployQtStep *m_step;
+ Qt4ProjectManager::Qt4BuildConfiguration *m_currentBuildConfiguration;
+ bool m_ignoreChange;
+};
+
+}
+}
+#endif // ANDROIDDEPLOYQTWIDGET_H
diff --git a/src/plugins/android/androiddeployqtwidget.ui b/src/plugins/android/androiddeployqtwidget.ui
new file mode 100644
index 0000000000..d1f1461909
--- /dev/null
+++ b/src/plugins/android/androiddeployqtwidget.ui
@@ -0,0 +1,295 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AndroidDeployQtWidget</class>
+ <widget class="QWidget" name="AndroidDeployQtWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>682</width>
+ <height>415</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="2" column="0" colspan="2">
+ <widget class="QGroupBox" name="signPackage">
+ <property name="title">
+ <string>Sign package</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="KeystoreLocationLabel">
+ <property name="text">
+ <string>Keystore:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="KeystoreLocationLineEdit">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="KeystoreCreatePushButton">
+ <property name="text">
+ <string>Create</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="KeystoreLocationPushButton">
+ <property name="text">
+ <string>Browse</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QCheckBox" name="signPackageCheckBox">
+ <property name="text">
+ <string>Sign package</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="signingDebugWarningIcon">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="../projectexplorer/projectexplorer.qrc">:/projectexplorer/images/compile_warning.png</pixmap>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="signingDebugWarningLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Signing a debug package</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="KeystoreLocationLabel_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Certificate alias:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="certificatesAliasComboBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QGroupBox" name="qtDeployment">
+ <property name="title">
+ <string>Qt Deployment</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QRadioButton" name="ministroOption">
+ <property name="toolTip">
+ <string>Use the external Ministro application to download and maintain Qt libraries.</string>
+ </property>
+ <property name="text">
+ <string>Use Ministro service to install Qt</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="temporaryQtOption">
+ <property name="toolTip">
+ <string>Push local Qt libraries to device. You must have Qt libraries compiled for that platform.
+The APK will not be usable on any other device.</string>
+ </property>
+ <property name="text">
+ <string>Deploy local Qt libraries to temporary directory</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="bundleQtOption">
+ <property name="toolTip">
+ <string>Creates a standalone APK.</string>
+ </property>
+ <property name="text">
+ <string>Bundle Qt libraries in APK</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QGroupBox" name="advancedActions">
+ <property name="title">
+ <string>Advanced Actions</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="3" column="0">
+ <widget class="QPushButton" name="cleanLibsPushButton">
+ <property name="text">
+ <string>Clean Temporary Libraries Directory on Device</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QPushButton" name="installMinistroButton">
+ <property name="text">
+ <string>Install Ministro from APK</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QPushButton" name="resetDefaultDevices">
+ <property name="text">
+ <string>Reset Default Devices</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="openPackageLocationCheckBox">
+ <property name="text">
+ <string>Open package location after is complete</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="verboseOutputCheckBox">
+ <property name="text">
+ <string>Verbose Output</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QGroupBox" name="application">
+ <property name="title">
+ <string>Application</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="1" column="1">
+ <widget class="QComboBox" name="targetSDKComboBox"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="targetSDKLabel">
+ <property name="text">
+ <string>Android target SDK:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="inputFileComboBox"/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="inputFileLabel">
+ <property name="text">
+ <string>Android deploy Qt Input File:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="oldFilesWarningIcon">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="../projectexplorer/projectexplorer.qrc">:/projectexplorer/images/compile_warning.png</pixmap>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="oldFilesWarningLabel">
+ <property name="text">
+ <string>Qt no longer uses the android folder in the project's source directory.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../projectexplorer/projectexplorer.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/plugins/android/androiddeploystep.cpp b/src/plugins/android/androiddeploystep.cpp
index e004e12032..2af881aff6 100644
--- a/src/plugins/android/androiddeploystep.cpp
+++ b/src/plugins/android/androiddeploystep.cpp
@@ -193,44 +193,6 @@ QVariantMap AndroidDeployStep::toMap() const
return map;
}
-void AndroidDeployStep::cleanLibsOnDevice()
-{
- const QString targetArch = AndroidManager::targetArch(target());
- int deviceAPILevel = AndroidManager::minimumSDK(target());
-
- AndroidDeviceInfo info = AndroidConfigurations::instance().showDeviceDialog(project(), m_deviceAPILevel, m_targetArch);
- if (info.serialNumber.isEmpty()) // aborted
- return;
-
- deviceAPILevel = info.sdk;
- QString deviceSerialNumber = info.serialNumber;
-
- if (info.type == AndroidDeviceInfo::Emulator) {
- deviceSerialNumber = AndroidConfigurations::instance().startAVD(deviceSerialNumber, deviceAPILevel, targetArch);
- if (deviceSerialNumber.isEmpty())
- MessageManager::write(tr("Starting android virtual device failed."));
- }
-
- QProcess *process = new QProcess(this);
- QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber);
- arguments << QLatin1String("shell") << QLatin1String("rm") << QLatin1String("-r") << QLatin1String("/data/local/tmp/qt");
- connect(process, SIGNAL(finished(int)), this, SLOT(processFinished()));
- const QString adb = AndroidConfigurations::instance().adbToolPath().toString();
- MessageManager::write(adb + QLatin1Char(' ') + arguments.join(QLatin1String(" ")));
- process->start(adb, arguments);
- if (!process->waitForStarted(500))
- delete process;
-}
-
-void AndroidDeployStep::processFinished()
-{
- QProcess *process = qobject_cast<QProcess *>(sender());
- QTC_ASSERT(process, return);
- MessageManager::write(QString::fromLocal8Bit(process->readAll()));
- MessageManager::write(tr("adb finished with exit code %1.").arg(process->exitCode()));
- process->deleteLater();
-}
-
void AndroidDeployStep::kitUpdated(Kit *kit)
{
if (kit != target()->kit())
@@ -249,35 +211,6 @@ void AndroidDeployStep::kitUpdated(Kit *kit)
}
}
-void AndroidDeployStep::installQASIPackage(const QString &packagePath)
-{
- const QString targetArch = AndroidManager::targetArch(target());
- int deviceAPILevel = AndroidManager::minimumSDK(target());
-
- AndroidDeviceInfo info = AndroidConfigurations::instance().showDeviceDialog(project(), m_deviceAPILevel, m_targetArch);
- if (info.serialNumber.isEmpty()) // aborted
- return;
-
- deviceAPILevel = info.sdk;
- QString deviceSerialNumber = info.serialNumber;
- if (info.type == AndroidDeviceInfo::Emulator) {
- deviceSerialNumber = AndroidConfigurations::instance().startAVD(deviceSerialNumber, deviceAPILevel, targetArch);
- if (deviceSerialNumber.isEmpty())
- MessageManager::write(tr("Starting android virtual device failed."));
- }
-
- QProcess *process = new QProcess(this);
- QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber);
- arguments << QLatin1String("install") << QLatin1String("-r ") << packagePath;
-
- connect(process, SIGNAL(finished(int)), this, SLOT(processFinished()));
- const QString adb = AndroidConfigurations::instance().adbToolPath().toString();
- MessageManager::write(adb + QLatin1Char(' ') + arguments.join(QLatin1String(" ")));
- process->start(adb, arguments);
- if (!process->waitForFinished(500))
- delete process;
-}
-
bool AndroidDeployStep::bundleQtOptionAvailable()
{
return m_bundleQtAvailable;
@@ -338,11 +271,6 @@ QString AndroidDeployStep::deviceSerialNumber()
return m_deviceSerialNumber;
}
-int AndroidDeployStep::deviceAPILevel()
-{
- return m_deviceAPILevel;
-}
-
unsigned int AndroidDeployStep::remoteModificationTime(const QString &fullDestination, QHash<QString, unsigned int> *cache)
{
QString destination = QFileInfo(fullDestination).absolutePath();
diff --git a/src/plugins/android/androiddeploystep.h b/src/plugins/android/androiddeploystep.h
index 31dce0cbd6..df7ebd7e2b 100644
--- a/src/plugins/android/androiddeploystep.h
+++ b/src/plugins/android/androiddeploystep.h
@@ -87,15 +87,12 @@ public:
virtual ~AndroidDeployStep();
QString deviceSerialNumber();
- int deviceAPILevel();
AndroidDeployAction deployAction();
bool fromMap(const QVariantMap &map);
QVariantMap toMap() const;
- void cleanLibsOnDevice();
- void installQASIPackage(const QString &packagePath);
bool bundleQtOptionAvailable();
public slots:
@@ -110,7 +107,6 @@ private slots:
bool deployPackage();
void handleBuildOutput();
void handleBuildError();
- void processFinished();
void kitUpdated(ProjectExplorer::Kit *kit);
private:
@@ -134,6 +130,7 @@ private:
void fetchRemoteModificationTimes(QList<DeployItem> *deployList);
void stripFiles(const QList<DeployItem> &deployList, ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolchainVersion);
void deployFiles(QProcess *process, const QList<DeployItem> &deployList);
+ bool checkForQt51Files();
private:
QString m_deviceSerialNumber;
diff --git a/src/plugins/android/androiddeploystepwidget.cpp b/src/plugins/android/androiddeploystepwidget.cpp
index b661bae5cf..68cb6b0c83 100644
--- a/src/plugins/android/androiddeploystepwidget.cpp
+++ b/src/plugins/android/androiddeploystepwidget.cpp
@@ -31,6 +31,7 @@
#include "ui_androiddeploystepwidget.h"
#include "androiddeploystep.h"
+#include "androidmanager.h"
#include "androidrunconfiguration.h"
#include <coreplugin/icore.h>
@@ -116,14 +117,15 @@ void AndroidDeployStepWidget::setQASIPackagePath()
QString packagePath =
QFileDialog::getOpenFileName(this, tr("Qt Android Smart Installer"),
QDir::homePath(), tr("Android package (*.apk)"));
- if (!packagePath.isEmpty())
- m_step->installQASIPackage(packagePath);
+ if (!packagePath.isEmpty()) {
+ AndroidManager::installQASIPackage(m_step->target(), packagePath);
+ }
}
void AndroidDeployStepWidget::cleanLibsOnDevice()
{
- m_step->cleanLibsOnDevice();
+ AndroidManager::cleanLibsOnDevice(m_step->target());
}
void AndroidDeployStepWidget::resetDefaultDevices()
diff --git a/src/plugins/android/androiddeploystepwidget.ui b/src/plugins/android/androiddeploystepwidget.ui
index 2c44ffc55d..9db955796d 100644
--- a/src/plugins/android/androiddeploystepwidget.ui
+++ b/src/plugins/android/androiddeploystepwidget.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>682</width>
- <height>155</height>
+ <height>183</height>
</rect>
</property>
<property name="sizePolicy">
diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp
index 8ed38e3e92..e87e972e84 100644
--- a/src/plugins/android/androidmanager.cpp
+++ b/src/plugins/android/androidmanager.cpp
@@ -35,8 +35,10 @@
#include "androidglobal.h"
#include "androidpackagecreationstep.h"
#include "androidtoolchain.h"
+#include "androiddeployqtstep.h"
#include <coreplugin/documentmanager.h>
+#include <coreplugin/messagemanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
@@ -216,14 +218,23 @@ int AndroidManager::minimumSDK(ProjectExplorer::Target *target)
QString AndroidManager::buildTargetSDK(ProjectExplorer::Target *target)
{
+ QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target->kit());
+ if (qt && qt->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0)) {
+ if (!target->activeDeployConfiguration())
+ return QLatin1String("android-9");
+ AndroidDeployQtStep *step = AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration());
+ if (step)
+ return step->buildTargetSdk();
+ return QLatin1String("android-9");
+ }
+
QVariant v = target->namedSettings(QLatin1String("AndroidManager.TargetSdk"));
if (v.isValid())
return v.toString();
QString fallback = QLatin1String("android-8");
- if (QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target->kit()))
- if (qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0))
- fallback = QLatin1String("android-9");
+ if (qt && qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0))
+ fallback = QLatin1String("android-9");
if (!createAndroidTemplatesIfNecessary(target))
return AndroidConfigurations::instance().bestMatch(fallback);
@@ -259,6 +270,9 @@ QString AndroidManager::targetArch(ProjectExplorer::Target *target)
Utils::FileName AndroidManager::dirPath(ProjectExplorer::Target *target)
{
+ QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(target->kit());
+ if (qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0))
+ return target->activeBuildConfiguration()->buildDirectory().appendPath(AndroidDirName);
return Utils::FileName::fromString(target->project()->projectDirectory()).appendPath(AndroidDirName);
}
@@ -289,15 +303,28 @@ Utils::FileName AndroidManager::srcPath(ProjectExplorer::Target *target)
Utils::FileName AndroidManager::apkPath(ProjectExplorer::Target *target, BuildType buildType)
{
+ QString packageName = QLatin1String("QtApp");
+ QString buildTypeName;
+ if (buildType == DebugBuild)
+ buildTypeName = QLatin1String("debug");
+ else if (buildType == ReleaseBuildUnsigned)
+ buildTypeName =QLatin1String("release-unsigned");
+ else
+ buildTypeName = QLatin1String("release");
+
+ QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target->kit());
+ if (!qt || qt->qtVersion() < QtSupport::QtVersionNumber(5, 2, 0)) {
+ // Qt 5.1 and earlier:
+ packageName = applicationName(target);
+ if (buildType == ReleaseBuildSigned)
+ buildTypeName = QLatin1String("signed");
+ }
+
return dirPath(target)
.appendPath(QLatin1String("bin"))
.appendPath(QString::fromLatin1("%1-%2.apk")
- .arg(applicationName(target))
- .arg(buildType == DebugBuild
- ? QLatin1String("debug")
- : (buildType == ReleaseBuildUnsigned)
- ? QLatin1String("release-unsigned")
- : QLatin1String("signed")));
+ .arg(packageName)
+ .arg(buildTypeName));
}
QStringList AndroidManager::availableTargetApplications(ProjectExplorer::Target *target)
@@ -333,18 +360,59 @@ QString AndroidManager::targetApplication(ProjectExplorer::Target *target)
return QString();
}
+// Note, this could be implemented via a base class and a couple of virtuals
+// but I intend to remove the indirection once we drop support for qt 4.8
+// and qt 5.1.
bool AndroidManager::bundleQt(ProjectExplorer::Target *target)
{
- ProjectExplorer::RunConfiguration *runConfiguration = target->activeRunConfiguration();
- AndroidRunConfiguration *androidRunConfiguration = qobject_cast<AndroidRunConfiguration *>(runConfiguration);
- if (androidRunConfiguration != 0) {
- AndroidDeployStep *deployStep = androidRunConfiguration->deployStep();
- return deployStep->deployAction() == AndroidDeployStep::BundleLibraries;
+ AndroidDeployStep *androidDeployStep
+ = AndroidGlobal::buildStep<AndroidDeployStep>(target->activeDeployConfiguration());
+ if (androidDeployStep) {
+ return androidDeployStep->deployAction() == AndroidDeployStep::BundleLibraries;
+ }
+
+ AndroidDeployQtStep *androidDeployQtStep
+ = AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration());
+ if (androidDeployQtStep) {
+ return androidDeployQtStep->deployAction() == AndroidDeployQtStep::BundleLibrariesDeployment;
}
return false;
}
+bool AndroidManager::useLocalLibs(ProjectExplorer::Target *target)
+{
+ AndroidDeployStep *androidDeployStep
+ = AndroidGlobal::buildStep<AndroidDeployStep>(target->activeDeployConfiguration());
+ if (androidDeployStep) {
+ return androidDeployStep->deployAction() == AndroidDeployStep::DeployLocal
+ || androidDeployStep->deployAction() == AndroidDeployStep::BundleLibraries;
+ }
+
+ AndroidDeployQtStep *androidDeployQtStep
+ = AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration());
+ if (androidDeployQtStep) {
+ return androidDeployQtStep->deployAction() == AndroidDeployQtStep::DebugDeployment
+ || androidDeployQtStep->deployAction() == AndroidDeployQtStep::BundleLibrariesDeployment;
+ }
+
+ return false;
+}
+
+QString AndroidManager::deviceSerialNumber(ProjectExplorer::Target *target)
+{
+ AndroidDeployStep *androidDeployStep
+ = AndroidGlobal::buildStep<AndroidDeployStep>(target->activeDeployConfiguration());
+ if (androidDeployStep)
+ return androidDeployStep->deviceSerialNumber();
+
+ AndroidDeployQtStep *androidDeployQtStep
+ = AndroidGlobal::buildStep<AndroidDeployQtStep>(target->activeDeployConfiguration());
+ if (androidDeployQtStep)
+ return androidDeployQtStep->deviceSerialNumber();
+ return QString();
+}
+
bool AndroidManager::updateDeploymentSettings(ProjectExplorer::Target *target)
{
// For Qt 4, the "use local libs" options is handled by passing command line arguments to the
@@ -353,16 +421,16 @@ bool AndroidManager::updateDeploymentSettings(ProjectExplorer::Target *target)
if (baseQtVersion == 0 || baseQtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0))
return true;
+ if (baseQtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0))
+ return true;
+
ProjectExplorer::RunConfiguration *runConfiguration = target->activeRunConfiguration();
AndroidRunConfiguration *androidRunConfiguration = qobject_cast<AndroidRunConfiguration *>(runConfiguration);
if (androidRunConfiguration == 0)
return false;
- AndroidDeployStep *deployStep = androidRunConfiguration->deployStep();
- AndroidDeployStep::AndroidDeployAction deployAction = deployStep->deployAction();
- bool useLocalLibs = deployAction == AndroidDeployStep::DeployLocal
- || deployAction == AndroidDeployStep::BundleLibraries;
- bool bundleQtLibs = deployAction == AndroidDeployStep::BundleLibraries;
+ bool useLocalLibs = AndroidManager::useLocalLibs(target);
+ bool bundleQtLibs = AndroidManager::bundleQt(target);
QDomDocument doc;
if (!openManifest(target, doc))
@@ -465,6 +533,10 @@ bool AndroidManager::createAndroidTemplatesIfNecessary(ProjectExplorer::Target *
if (!qt4Project || !qt4Project->rootProjectNode() || !version)
return false;
+ // TODO we should create the AndroidManifest.xml file for that version
+ if (version->qtVersion() >= QtSupport::QtVersionNumber(5, 2, 0))
+ return true;
+
Utils::FileName javaSrcPath
= Utils::FileName::fromString(version->qmakeProperty("QT_INSTALL_PREFIX"))
.appendPath(QLatin1String("src/android/java"));
@@ -568,6 +640,10 @@ bool AndroidManager::createAndroidTemplatesIfNecessary(ProjectExplorer::Target *
void AndroidManager::updateTarget(ProjectExplorer::Target *target, const QString &targetSDK, const QString &name)
{
+ QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(target->kit());
+ if (qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5,2,0))
+ return;
+
QString androidDir = dirPath(target).toString();
Utils::Environment env = Utils::Environment::systemEnvironment();
@@ -1115,5 +1191,126 @@ QString AndroidManager::libraryPrefix()
return AndroidLibraryPrefix;
}
+
+void AndroidManager::cleanLibsOnDevice(ProjectExplorer::Target *target)
+{
+ const QString targetArch = AndroidManager::targetArch(target);
+ int deviceAPILevel = AndroidManager::minimumSDK(target);
+ AndroidDeviceInfo info = AndroidConfigurations::instance().showDeviceDialog(target->project(), deviceAPILevel, targetArch);
+ if (info.serialNumber.isEmpty()) // aborted
+ return;
+
+ deviceAPILevel = info.sdk;
+ QString deviceSerialNumber = info.serialNumber;
+
+ if (info.type == AndroidDeviceInfo::Emulator) {
+ deviceSerialNumber = AndroidConfigurations::instance().startAVD(deviceSerialNumber, deviceAPILevel, targetArch);
+ if (deviceSerialNumber.isEmpty())
+ Core::MessageManager::write(tr("Starting android virtual device failed."));
+ }
+
+ QProcess *process = new QProcess();
+ QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber);
+ arguments << QLatin1String("shell") << QLatin1String("rm") << QLatin1String("-r") << QLatin1String("/data/local/tmp/qt");
+ process->connect(process, SIGNAL(finished(int)), process, SLOT(deleteLater()));
+ const QString adb = AndroidConfigurations::instance().adbToolPath().toString();
+ Core::MessageManager::write(adb + QLatin1Char(' ') + arguments.join(QLatin1String(" ")));
+ process->start(adb, arguments);
+ if (!process->waitForStarted(500))
+ delete process;
+}
+
+void AndroidManager::installQASIPackage(ProjectExplorer::Target *target, const QString &packagePath)
+{
+ const QString targetArch = AndroidManager::targetArch(target);
+ int deviceAPILevel = AndroidManager::minimumSDK(target);
+ AndroidDeviceInfo info = AndroidConfigurations::instance().showDeviceDialog(target->project(), deviceAPILevel, targetArch);
+ if (info.serialNumber.isEmpty()) // aborted
+ return;
+
+ deviceAPILevel = info.sdk;
+ QString deviceSerialNumber = info.serialNumber;
+ if (info.type == AndroidDeviceInfo::Emulator) {
+ deviceSerialNumber = AndroidConfigurations::instance().startAVD(deviceSerialNumber, deviceAPILevel, targetArch);
+ if (deviceSerialNumber.isEmpty())
+ Core::MessageManager::write(tr("Starting android virtual device failed."));
+ }
+
+ QProcess *process = new QProcess();
+ QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber);
+ arguments << QLatin1String("install") << QLatin1String("-r ") << packagePath;
+
+ process->connect(process, SIGNAL(finished(int)), process, SLOT(deleteLater()));
+ const QString adb = AndroidConfigurations::instance().adbToolPath().toString();
+ Core::MessageManager::write(adb + QLatin1Char(' ') + arguments.join(QLatin1String(" ")));
+ process->start(adb, arguments);
+ if (!process->waitForFinished(500))
+ delete process;
+
+}
+
+bool AndroidManager::checkKeystorePassword(const QString &keystorePath, const QString &keystorePasswd)
+{
+ if (keystorePasswd.isEmpty())
+ return false;
+ QStringList arguments;
+ arguments << QLatin1String("-list")
+ << QLatin1String("-keystore")
+ << keystorePath
+ << QLatin1String("--storepass")
+ << keystorePasswd;
+ QProcess proc;
+ proc.start(AndroidConfigurations::instance().keytoolPath().toString(), arguments);
+ if (!proc.waitForStarted(500))
+ return false;
+ if (!proc.waitForFinished(500)) {
+ proc.kill();
+ proc.waitForFinished();
+ return false;
+ }
+ return proc.exitCode() == 0;
+}
+
+bool AndroidManager::checkCertificatePassword(const QString &keystorePath, const QString &keystorePasswd, const QString &alias, const QString &certificatePasswd)
+{
+ // assumes that the keystore password is correct
+ QStringList arguments;
+ arguments << QLatin1String("-certreq")
+ << QLatin1String("-keystore")
+ << keystorePath
+ << QLatin1String("--storepass")
+ << keystorePasswd
+ << QLatin1String("-alias")
+ << alias
+ << QLatin1String("-keypass");
+ if (certificatePasswd.isEmpty())
+ arguments << keystorePasswd;
+ else
+ arguments << certificatePasswd;
+
+ QProcess proc;
+ proc.start(AndroidConfigurations::instance().keytoolPath().toString(), arguments);
+ if (!proc.waitForStarted(500))
+ return false;
+ if (!proc.waitForFinished(500)) {
+ proc.kill();
+ proc.waitForFinished();
+ return false;
+ }
+ return proc.exitCode() == 0;
+}
+
+bool AndroidManager::checkForQt51Files(const QString &projectDirectory)
+{
+ Utils::FileName fileName = Utils::FileName::fromString(projectDirectory);
+ fileName.appendPath(QLatin1String("android")).appendPath(QLatin1String("version.xml"));
+ if (!fileName.toFileInfo().exists())
+ return false;
+ QDomDocument dstVersionDoc;
+ if (!AndroidManager::openXmlFile(dstVersionDoc, fileName))
+ return false;
+ return dstVersionDoc.documentElement().attribute(QLatin1String("value")).toDouble() < 5.2;
+}
+
} // namespace Internal
} // namespace Qt4ProjectManager
diff --git a/src/plugins/android/androidmanager.h b/src/plugins/android/androidmanager.h
index f6ac5f038b..df81322e53 100644
--- a/src/plugins/android/androidmanager.h
+++ b/src/plugins/android/androidmanager.h
@@ -72,6 +72,8 @@ public:
static bool updateDeploymentSettings(ProjectExplorer::Target *target);
static bool bundleQt(ProjectExplorer::Target *target);
+ static bool useLocalLibs(ProjectExplorer::Target *target);
+ static QString deviceSerialNumber(ProjectExplorer::Target *target);
static QString buildTargetSDK(ProjectExplorer::Target *target);
static bool setBuildTargetSDK(ProjectExplorer::Target *target, const QString &sdk);
@@ -128,6 +130,12 @@ public:
static QString libGnuStl(const QString &arch, const QString &ndkToolChainVersion);
static QString libraryPrefix();
+ static void cleanLibsOnDevice(ProjectExplorer::Target *target);
+ static void installQASIPackage(ProjectExplorer::Target *target, const QString &packagePath);
+
+ static bool checkKeystorePassword(const QString &keystorePath, const QString &keystorePasswd);
+ static bool checkCertificatePassword(const QString &keystorePath, const QString &keystorePasswd, const QString &alias, const QString &certificatePasswd);
+ static bool checkForQt51Files(const QString &projectDirectory);
private:
static void raiseError(const QString &reason);
static bool openXmlFile(QDomDocument &doc, const Utils::FileName &fileName);
diff --git a/src/plugins/android/androidpackagecreationstep.cpp b/src/plugins/android/androidpackagecreationstep.cpp
index e337acd361..26d4f70306 100644
--- a/src/plugins/android/androidpackagecreationstep.cpp
+++ b/src/plugins/android/androidpackagecreationstep.cpp
@@ -36,6 +36,7 @@
#include "androidmanager.h"
#include "androidgdbserverkitinformation.h"
#include "androidtoolchain.h"
+#include "certificatesmodel.h"
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -73,47 +74,6 @@ namespace {
using namespace Qt4ProjectManager;
-class CertificatesModel: public QAbstractListModel
-{
-public:
- CertificatesModel(const QString &rowCertificates, QObject *parent)
- : QAbstractListModel(parent)
- {
- int from = rowCertificates.indexOf(AliasString);
- QPair<QString, QString> item;
- while (from > -1) {
- from += 11;// strlen(AliasString);
- const int eol = rowCertificates.indexOf(QLatin1Char('\n'), from);
- item.first = rowCertificates.mid(from, eol - from).trimmed();
- const int eoc = rowCertificates.indexOf(CertificateSeparator, eol);
- item.second = rowCertificates.mid(eol + 1, eoc - eol - 2).trimmed();
- from = rowCertificates.indexOf(AliasString, eoc);
- m_certs.push_back(item);
- }
- }
-
-protected:
- int rowCount(const QModelIndex &parent = QModelIndex()) const
- {
- if (parent.isValid())
- return 0;
- return m_certs.size();
- }
-
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
- {
- if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::ToolTipRole))
- return QVariant();
- if (role == Qt::DisplayRole)
- return m_certs[index.row()].first;
- return m_certs[index.row()].second;
- }
-
-private:
- QVector<QPair<QString, QString> > m_certs;
-};
-
-
AndroidPackageCreationStep::AndroidPackageCreationStep(BuildStepList *bsl)
: BuildStep(bsl, CreatePackageId)
{
diff --git a/src/plugins/android/androidpackagecreationwidget.ui b/src/plugins/android/androidpackagecreationwidget.ui
index 69695797d6..5f27b1d6e9 100644
--- a/src/plugins/android/androidpackagecreationwidget.ui
+++ b/src/plugins/android/androidpackagecreationwidget.ui
@@ -37,7 +37,7 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="groupBox_2">
+ <widget class="QGroupBox" name="librariesGroupBox">
<property name="title">
<string>Libraries</string>
</property>
diff --git a/src/plugins/android/androidpackageinstallationfactory.cpp b/src/plugins/android/androidpackageinstallationfactory.cpp
index e3f86b0e59..e054f903c8 100644
--- a/src/plugins/android/androidpackageinstallationfactory.cpp
+++ b/src/plugins/android/androidpackageinstallationfactory.cpp
@@ -50,13 +50,8 @@ AndroidPackageInstallationFactory::AndroidPackageInstallationFactory(QObject *pa
QList<Core::Id> AndroidPackageInstallationFactory::availableCreationIds(BuildStepList *parent) const
{
- if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
- return QList<Core::Id>();
- if (!AndroidManager::supportsAndroid(parent->target()))
- return QList<Core::Id>();
- if (parent->contains(AndroidPackageInstallationStep::Id))
- return QList<Core::Id>();
- return QList<Core::Id>() << AndroidPackageInstallationStep::Id;
+ Q_UNUSED(parent);
+ return QList<Core::Id>();
}
QString AndroidPackageInstallationFactory::displayNameForId(const Core::Id id) const
@@ -68,25 +63,33 @@ QString AndroidPackageInstallationFactory::displayNameForId(const Core::Id id) c
bool AndroidPackageInstallationFactory::canCreate(BuildStepList *parent, const Core::Id id) const
{
- return availableCreationIds(parent).contains(id);
+ Q_UNUSED(parent);
+ Q_UNUSED(id);
+ return false;
}
BuildStep *AndroidPackageInstallationFactory::create(BuildStepList *parent, const Core::Id id)
{
- Q_ASSERT(canCreate(parent, id));
+ Q_UNUSED(parent);
Q_UNUSED(id);
- return new AndroidPackageInstallationStep(parent);
+ return 0;
}
bool AndroidPackageInstallationFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const
{
- return canCreate(parent, idFromMap(map));
+ if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
+ return false;
+ if (!AndroidManager::supportsAndroid(parent->target()))
+ return false;
+ if (parent->contains(AndroidPackageInstallationStep::Id))
+ return false;
+ return ProjectExplorer::idFromMap(map) == AndroidPackageInstallationStep::Id;
}
BuildStep *AndroidPackageInstallationFactory::restore(BuildStepList *parent, const QVariantMap &map)
{
Q_ASSERT(canRestore(parent, map));
- AndroidPackageInstallationStep * const step = new AndroidPackageInstallationStep(parent);
+ AndroidPackageInstallationStep * const step = new AndroidPackageInstallationStep(AndroidPackageInstallationStep::ProjectDirectory, parent);
if (!step->fromMap(map)) {
delete step;
return 0;
diff --git a/src/plugins/android/androidpackageinstallationstep.cpp b/src/plugins/android/androidpackageinstallationstep.cpp
index 7b69ac3467..8541c3ef02 100644
--- a/src/plugins/android/androidpackageinstallationstep.cpp
+++ b/src/plugins/android/androidpackageinstallationstep.cpp
@@ -40,9 +40,12 @@
using namespace Android::Internal;
const Core::Id AndroidPackageInstallationStep::Id = Core::Id("Qt4ProjectManager.AndroidPackageInstallationStep");
+namespace {
+const char ANDROIDDIRECTORY[] = "Android.AndroidPackageInstallationStep.AndroidDirectory";
+}
-AndroidPackageInstallationStep::AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bsl)
- : MakeStep(bsl, Id)
+AndroidPackageInstallationStep::AndroidPackageInstallationStep(AndroidDirectory mode,ProjectExplorer::BuildStepList *bsl)
+ : MakeStep(bsl, Id), m_androidDirectory(mode)
{
const QString name = tr("Copy application data");
setDefaultDisplayName(name);
@@ -58,7 +61,11 @@ bool AndroidPackageInstallationStep::init()
ProjectExplorer::BuildConfiguration *bc = buildConfiguration();
if (!bc)
bc = target()->activeBuildConfiguration();
- QString dirPath = AndroidManager::dirPath(target()).toString();
+ QString dirPath;
+ if (m_androidDirectory == ProjectDirectory)
+ dirPath = AndroidManager::dirPath(target()).toString();
+ else
+ dirPath = bc->buildDirectory().appendPath((QLatin1String("android"))).toString();
if (Utils::HostOsInfo::isWindowsHost())
if (bc->environment().searchInPath(QLatin1String("sh.exe")).isEmpty())
dirPath = QDir::toNativeSeparators(dirPath);
@@ -66,3 +73,18 @@ bool AndroidPackageInstallationStep::init()
return MakeStep::init();
}
+
+bool AndroidPackageInstallationStep::fromMap(const QVariantMap &map)
+{
+ if (!MakeStep::fromMap(map))
+ return false;
+ m_androidDirectory = AndroidDirectory(map.value(QLatin1String(ANDROIDDIRECTORY)).toInt());
+ return true;
+}
+
+QVariantMap AndroidPackageInstallationStep::toMap() const
+{
+ QVariantMap map = MakeStep::toMap();
+ map.insert(QLatin1String(ANDROIDDIRECTORY), m_androidDirectory);
+ return map;
+}
diff --git a/src/plugins/android/androidpackageinstallationstep.h b/src/plugins/android/androidpackageinstallationstep.h
index 6763ef138e..2ccbc7ad69 100644
--- a/src/plugins/android/androidpackageinstallationstep.h
+++ b/src/plugins/android/androidpackageinstallationstep.h
@@ -41,12 +41,17 @@ class AndroidPackageInstallationStep : public Qt4ProjectManager::MakeStep
friend class AndroidPackageInstallationFactory;
public:
- explicit AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bsl);
+ enum AndroidDirectory { ProjectDirectory, BuildDirectory };
+ explicit AndroidPackageInstallationStep(AndroidDirectory mode, ProjectExplorer::BuildStepList *bsl);
bool init();
+ bool fromMap(const QVariantMap &map);
+ QVariantMap toMap() const;
+
private:
AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bc,
AndroidPackageInstallationStep *other);
+ AndroidDirectory m_androidDirectory;
static const Core::Id Id;
};
diff --git a/src/plugins/android/androidplugin.cpp b/src/plugins/android/androidplugin.cpp
index 508b4ce93d..41ebb56134 100644
--- a/src/plugins/android/androidplugin.cpp
+++ b/src/plugins/android/androidplugin.cpp
@@ -32,6 +32,7 @@
#include "androidconstants.h"
#include "androidconfigurations.h"
#include "androiddeploystepfactory.h"
+#include "androiddeployqtstep.h"
#include "androiddevice.h"
#include "androiddevicefactory.h"
#include "androidmanager.h"
@@ -74,6 +75,7 @@ bool AndroidPlugin::initialize(const QStringList &arguments, QString *errorMessa
addAutoReleasedObject(new Internal::AndroidPackageInstallationFactory);
addAutoReleasedObject(new Internal::AndroidPackageCreationFactory);
addAutoReleasedObject(new Internal::AndroidDeployStepFactory);
+ addAutoReleasedObject(new Internal::AndroidDeployQtStepFactory);
addAutoReleasedObject(new Internal::AndroidSettingsPage);
addAutoReleasedObject(new Internal::AndroidQtVersionFactory);
addAutoReleasedObject(new Internal::AndroidToolChainFactory);
diff --git a/src/plugins/android/androidrunconfiguration.cpp b/src/plugins/android/androidrunconfiguration.cpp
index 45e9e091b9..d84bce54b8 100644
--- a/src/plugins/android/androidrunconfiguration.cpp
+++ b/src/plugins/android/androidrunconfiguration.cpp
@@ -84,16 +84,6 @@ AndroidConfig AndroidRunConfiguration::config() const
return AndroidConfigurations::instance().config();
}
-AndroidDeployStep *AndroidRunConfiguration::deployStep() const
-{
- AndroidDeployStep * const step
- = AndroidGlobal::buildStep<AndroidDeployStep>(target()->activeDeployConfiguration());
- Q_ASSERT_X(step, Q_FUNC_INFO,
- "Impossible: Android build configuration without deploy step.");
- return step;
-}
-
-
const QString AndroidRunConfiguration::remoteChannel() const
{
return QLatin1String(":5039");
diff --git a/src/plugins/android/androidrunconfiguration.h b/src/plugins/android/androidrunconfiguration.h
index 947d44a385..9e0fd50cd7 100644
--- a/src/plugins/android/androidrunconfiguration.h
+++ b/src/plugins/android/androidrunconfiguration.h
@@ -52,8 +52,6 @@ public:
QWidget *createConfigurationWidget();
Utils::OutputFormatter *createOutputFormatter() const;
- AndroidDeployStep *deployStep() const;
-
void setArguments(const QString &args);
AndroidConfig config() const;
QString proFilePath() const;
diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp
index ef467d2bca..e00cb95e68 100644
--- a/src/plugins/android/androidrunner.cpp
+++ b/src/plugins/android/androidrunner.cpp
@@ -30,6 +30,7 @@
#include "androidrunner.h"
#include "androiddeploystep.h"
+#include "androiddeployqtstep.h"
#include "androidconfigurations.h"
#include "androidglobal.h"
#include "androidrunconfiguration.h"
@@ -73,17 +74,17 @@ AndroidRunner::AndroidRunner(QObject *parent,
m_qmlPort = server.serverPort();
}
ProjectExplorer::Target *target = runConfig->target();
- AndroidDeployStep *ds = runConfig->deployStep();
- m_useLocalQtLibs = ds->deployAction() == AndroidDeployStep::DeployLocal
- || ds->deployAction() == AndroidDeployStep::BundleLibraries;
+ m_useLocalQtLibs = AndroidManager::useLocalLibs(target);
if (m_useLocalQtLibs) {
- m_localLibs = AndroidManager::loadLocalLibs(target, ds->deviceAPILevel());
- m_localJars = AndroidManager::loadLocalJars(target, ds->deviceAPILevel());
- m_localJarsInitClasses = AndroidManager::loadLocalJarsInitClasses(target, ds->deviceAPILevel());
+ int deviceApiLevel = AndroidManager::minimumSDK(target);
+ m_localLibs = AndroidManager::loadLocalLibs(target, deviceApiLevel);
+ m_localJars = AndroidManager::loadLocalJars(target, deviceApiLevel);
+ m_localJarsInitClasses = AndroidManager::loadLocalJarsInitClasses(target, deviceApiLevel);
}
m_intentName = AndroidManager::intentName(target);
m_packageName = m_intentName.left(m_intentName.indexOf(QLatin1Char('/')));
- m_deviceSerialNumber = ds->deviceSerialNumber();
+
+ m_deviceSerialNumber = AndroidManager::deviceSerialNumber(target);
m_processPID = -1;
m_adb = AndroidConfigurations::instance().adbToolPath().toString();
m_selector = AndroidDeviceInfo::adbSelector(m_deviceSerialNumber);
diff --git a/src/plugins/android/certificatesmodel.cpp b/src/plugins/android/certificatesmodel.cpp
new file mode 100644
index 0000000000..c06d1b72d1
--- /dev/null
+++ b/src/plugins/android/certificatesmodel.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (c) 2013 BogDan Vatra <bog_dan_ro@yahoo.com>
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** 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 "certificatesmodel.h"
+
+using namespace Android;
+using namespace Android::Internal;
+
+namespace {
+const QLatin1String AliasString("Alias name:");
+const QLatin1String CertificateSeparator("*******************************************");
+}
+
+CertificatesModel::CertificatesModel(const QString &rowCertificates, QObject *parent)
+ : QAbstractListModel(parent)
+{
+ int from = rowCertificates.indexOf(AliasString);
+ QPair<QString, QString> item;
+ while (from > -1) {
+ from += 11;// strlen(AliasString);
+ const int eol = rowCertificates.indexOf(QLatin1Char('\n'), from);
+ item.first = rowCertificates.mid(from, eol - from).trimmed();
+ const int eoc = rowCertificates.indexOf(CertificateSeparator, eol);
+ item.second = rowCertificates.mid(eol + 1, eoc - eol - 2).trimmed();
+ from = rowCertificates.indexOf(AliasString, eoc);
+ m_certs.push_back(item);
+ }
+}
+
+int CertificatesModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+ return m_certs.size();
+}
+
+QVariant CertificatesModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::ToolTipRole))
+ return QVariant();
+ if (role == Qt::DisplayRole)
+ return m_certs[index.row()].first;
+ return m_certs[index.row()].second;
+}
diff --git a/src/plugins/android/certificatesmodel.h b/src/plugins/android/certificatesmodel.h
new file mode 100644
index 0000000000..fa0d53c219
--- /dev/null
+++ b/src/plugins/android/certificatesmodel.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (c) 2013 BogDan Vatra <bog_dan_ro@yahoo.com>
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** 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.
+**
+****************************************************************************/
+
+#ifndef CERTIFICATESMODEL_H
+#define CERTIFICATESMODEL_H
+
+#include <QAbstractListModel>
+
+namespace Android {
+namespace Internal {
+
+class CertificatesModel: public QAbstractListModel
+{
+public:
+ CertificatesModel(const QString &rowCertificates, QObject *parent);
+
+protected:
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+private:
+ QVector<QPair<QString, QString> > m_certs;
+};
+
+}
+}
+
+#endif // CERTIFICATESMODEL_H
diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp
index cad79fcf8d..8fc2f68b56 100644
--- a/src/plugins/qt4projectmanager/qt4nodes.cpp
+++ b/src/plugins/qt4projectmanager/qt4nodes.cpp
@@ -1963,6 +1963,7 @@ void Qt4ProFileNode::applyEvaluate(EvalResult evalResult, bool async)
newVarValues[StaticLibExtensionVar] = m_readerExact->values(QLatin1String("QMAKE_EXTENSION_STATICLIB"));
newVarValues[ShLibExtensionVar] = m_readerExact->values(QLatin1String("QMAKE_EXTENSION_SHLIB"));
newVarValues[AndroidArchVar] = m_readerExact->values(QLatin1String("ANDROID_TARGET_ARCH"));
+ newVarValues[AndroidDeploySettingsFile] = m_readerExact->values(QLatin1String("ANDROID_DEPLOYMENT_SETTINGS_FILE"));
m_isDeployable = false;
if (m_projectType == ApplicationTemplate) {
diff --git a/src/plugins/qt4projectmanager/qt4nodes.h b/src/plugins/qt4projectmanager/qt4nodes.h
index 3e657f7e19..d4b255bcf3 100644
--- a/src/plugins/qt4projectmanager/qt4nodes.h
+++ b/src/plugins/qt4projectmanager/qt4nodes.h
@@ -105,7 +105,8 @@ enum Qt4Variable {
TargetVersionExtVar,
StaticLibExtensionVar,
ShLibExtensionVar,
- AndroidArchVar
+ AndroidArchVar,
+ AndroidDeploySettingsFile
};
// Import base classes into namespace