Commit 12623107 authored by Daniel Teske's avatar Daniel Teske
Browse files

Android: androiddeployqt support



Change-Id: I37d706b4e11c6e1353a8ee73378b7d080080678c
Reviewed-by: default avatarEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
parent 455d597a
...@@ -42,7 +42,10 @@ HEADERS += \ ...@@ -42,7 +42,10 @@ HEADERS += \
androidmanifesteditor.h \ androidmanifesteditor.h \
androidmanifesteditorwidget.h \ androidmanifesteditorwidget.h \
androidmanifestdocument.h \ androidmanifestdocument.h \
androiddevicedialog.h androiddevicedialog.h \
androiddeployqtstep.h \
certificatesmodel.h \
androiddeployqtwidget.h
SOURCES += \ SOURCES += \
androidconfigurations.cpp \ androidconfigurations.cpp \
...@@ -79,7 +82,10 @@ SOURCES += \ ...@@ -79,7 +82,10 @@ SOURCES += \
androidmanifesteditor.cpp \ androidmanifesteditor.cpp \
androidmanifesteditorwidget.cpp \ androidmanifesteditorwidget.cpp \
androidmanifestdocument.cpp \ androidmanifestdocument.cpp \
androiddevicedialog.cpp androiddevicedialog.cpp \
androiddeployqtstep.cpp \
certificatesmodel.cpp \
androiddeployqtwidget.cpp
FORMS += \ FORMS += \
androidsettingswidget.ui \ androidsettingswidget.ui \
...@@ -87,7 +93,8 @@ FORMS += \ ...@@ -87,7 +93,8 @@ FORMS += \
androiddeploystepwidget.ui \ androiddeploystepwidget.ui \
addnewavddialog.ui \ addnewavddialog.ui \
androidcreatekeystorecertificate.ui \ androidcreatekeystorecertificate.ui \
androiddevicedialog.ui androiddevicedialog.ui \
androiddeployqtwidget.ui
exists(../../shared/qbs/qbs.pro) { exists(../../shared/qbs/qbs.pro) {
HEADERS += \ HEADERS += \
......
...@@ -36,6 +36,8 @@ QtcPlugin { ...@@ -36,6 +36,8 @@ QtcPlugin {
"androidcreatekeystorecertificate.cpp", "androidcreatekeystorecertificate.cpp",
"androidcreatekeystorecertificate.h", "androidcreatekeystorecertificate.h",
"androidcreatekeystorecertificate.ui", "androidcreatekeystorecertificate.ui",
"androiddeployqtstep.cpp",
"androiddeployqtstep.h",
"androiddebugsupport.cpp", "androiddebugsupport.cpp",
"androiddebugsupport.h", "androiddebugsupport.h",
"androiddevicedialog.cpp", "androiddevicedialog.cpp",
...@@ -50,6 +52,9 @@ QtcPlugin { ...@@ -50,6 +52,9 @@ QtcPlugin {
"androiddeploystepwidget.cpp", "androiddeploystepwidget.cpp",
"androiddeploystepwidget.h", "androiddeploystepwidget.h",
"androiddeploystepwidget.ui", "androiddeploystepwidget.ui",
"androiddeployqtwidget.cpp",
"androiddeployqtwidget.h",
"androiddeployqtwidget.ui",
"androiddevice.cpp", "androiddevice.cpp",
"androiddevice.h", "androiddevice.h",
"androiddevicefactory.cpp", "androiddevicefactory.cpp",
...@@ -103,6 +108,8 @@ QtcPlugin { ...@@ -103,6 +108,8 @@ QtcPlugin {
"androidsettingswidget.ui", "androidsettingswidget.ui",
"androidtoolchain.cpp", "androidtoolchain.cpp",
"androidtoolchain.h", "androidtoolchain.h",
"certificatesmodel.cpp",
"certificatesmodel.h",
"javaparser.cpp", "javaparser.cpp",
"javaparser.h", "javaparser.h",
] ]
......
...@@ -715,6 +715,13 @@ QStringList AndroidConfigurations::getAbis(const QString &device) const ...@@ -715,6 +715,13 @@ QStringList AndroidConfigurations::getAbis(const QString &device) const
return result; 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 QString AndroidConfigurations::bestMatch(const QString &targetAPI) const
{ {
int target = targetAPI.mid(targetAPI.lastIndexOf(QLatin1Char('-')) + 1).toInt(); int target = targetAPI.mid(targetAPI.lastIndexOf(QLatin1Char('-')) + 1).toInt();
......
...@@ -124,6 +124,7 @@ public: ...@@ -124,6 +124,7 @@ public:
AndroidDeviceInfo showDeviceDialog(ProjectExplorer::Project *project, int apiLevel, const QString &abi); 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 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 defaultDevice(ProjectExplorer::Project *project, const QString &abi) const; // serial number or avd name
QString highestAvailableAndroidPlatform() const;
public slots: public slots:
void clearDefaultDevices(ProjectExplorer::Project *project); void clearDefaultDevices(ProjectExplorer::Project *project);
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "androiddeploystep.h" #include "androiddeploystep.h"
#include "androidpackageinstallationstep.h" #include "androidpackageinstallationstep.h"
#include "androidpackagecreationstep.h" #include "androidpackagecreationstep.h"
#include "androiddeployqtstep.h"
#include "androidmanager.h" #include "androidmanager.h"
#include <projectexplorer/buildsteplist.h> #include <projectexplorer/buildsteplist.h>
...@@ -76,9 +77,15 @@ DeployConfiguration *AndroidDeployConfigurationFactory::create(Target *parent, c ...@@ -76,9 +77,15 @@ DeployConfiguration *AndroidDeployConfigurationFactory::create(Target *parent, c
AndroidDeployConfiguration *dc = new AndroidDeployConfiguration(parent, id); AndroidDeployConfiguration *dc = new AndroidDeployConfiguration(parent, id);
if (!dc) if (!dc)
return 0; return 0;
dc->stepList()->insertStep(0, new AndroidPackageInstallationStep(dc->stepList()));
dc->stepList()->insertStep(1, new AndroidPackageCreationStep(dc->stepList())); if (id == ANDROID_DEPLOYCONFIGURATION_ID) {
dc->stepList()->insertStep(2, new AndroidDeployStep(dc->stepList())); 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; return dc;
} }
...@@ -104,7 +111,7 @@ bool AndroidDeployConfigurationFactory::canClone(Target *parent, DeployConfigura ...@@ -104,7 +111,7 @@ bool AndroidDeployConfigurationFactory::canClone(Target *parent, DeployConfigura
{ {
if (!AndroidManager::supportsAndroid(parent)) if (!AndroidManager::supportsAndroid(parent))
return false; return false;
return source->id() == ANDROID_DEPLOYCONFIGURATION_ID; return canCreate(parent, source->id());
} }
DeployConfiguration *AndroidDeployConfigurationFactory::clone(Target *parent, DeployConfiguration *source) DeployConfiguration *AndroidDeployConfigurationFactory::clone(Target *parent, DeployConfiguration *source)
...@@ -128,16 +135,20 @@ QList<Core::Id> AndroidDeployConfigurationFactory::availableCreationIds(Target * ...@@ -128,16 +135,20 @@ QList<Core::Id> AndroidDeployConfigurationFactory::availableCreationIds(Target *
if (!tc || tc->targetAbi().osFlavor() != Abi::AndroidLinuxFlavor) if (!tc || tc->targetAbi().osFlavor() != Abi::AndroidLinuxFlavor)
return ids; 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; return ids;
if (qt->qtVersion() < QtSupport::QtVersionNumber(5, 2, 0))
ids << Core::Id(ANDROID_DEPLOYCONFIGURATION_ID); ids << Core::Id(ANDROID_DEPLOYCONFIGURATION_ID);
else
ids << Core::Id(ANDROID_DEPLOYCONFIGURATION2_ID);
return ids; return ids;
} }
QString AndroidDeployConfigurationFactory::displayNameForId(const Core::Id id) const 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 tr("Deploy on Android");
return QString(); return QString();
} }
......
...@@ -38,6 +38,10 @@ namespace Internal { ...@@ -38,6 +38,10 @@ namespace Internal {
const char ANDROID_DEPLOYCONFIGURATION_ID[] = "Qt4ProjectManager.AndroidDeployConfiguration"; const char ANDROID_DEPLOYCONFIGURATION_ID[] = "Qt4ProjectManager.AndroidDeployConfiguration";
const char ANDROID_DC_PREFIX[] = "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 class AndroidDeployConfiguration : public ProjectExplorer::DeployConfiguration
{ {
Q_OBJECT Q_OBJECT
......
This diff is collapsed.
/**************************************************************************
**
** 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
/**************************************************************************
**
** 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()