diff --git a/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.cpp b/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.cpp
index 534f421c735..2aeda06921e 100644
--- a/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.cpp
+++ b/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.cpp
@@ -61,7 +61,7 @@ QString QmlApplicationViewerPrivate::adjustPath(const QString &path)
if (!QDir::isAbsolutePath(path))
return QString::fromLatin1("%1/../Resources/%2")
.arg(QCoreApplication::applicationDirPath(), path);
-#else
+#elif !defined(Q_OS_ANDROID)
const QString pathInInstallDir =
QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path);
if (QFileInfo(pathInInstallDir).exists())
@@ -77,6 +77,10 @@ QmlApplicationViewer::QmlApplicationViewer(QWidget *parent)
{
connect(engine(), SIGNAL(quit()), SLOT(close()));
setResizeMode(QDeclarativeView::SizeRootObjectToView);
+
+#ifdef Q_OS_ANDROID
+ engine()->setBaseUrl(QUrl::fromLocalFile(QLatin1String("/")));
+#endif
// Qt versions prior to 4.8.0 don't have QML/JS debugging services built in
#if defined(QMLJSDEBUGGER) && QT_VERSION < 0x040800
#if !defined(NO_JSDEBUGGER)
diff --git a/share/qtcreator/templates/shared/deployment.pri b/share/qtcreator/templates/shared/deployment.pri
index 4ebaa74be97..bd7a4c0226e 100644
--- a/share/qtcreator/templates/shared/deployment.pri
+++ b/share/qtcreator/templates/shared/deployment.pri
@@ -21,6 +21,28 @@ MAINPROFILEPWD = $$PWD
symbian {
isEmpty(ICON):exists($${TARGET}.svg):ICON = $${TARGET}.svg
isEmpty(TARGET.EPOCHEAPSIZE):TARGET.EPOCHEAPSIZE = 0x20000 0x2000000
+} else:android {
+ for(deploymentfolder, DEPLOYMENTFOLDERS) {
+ item = item$${deploymentfolder}
+ itemfiles = $${item}.files
+ $$itemfiles = $$eval($${deploymentfolder}.source)
+ itempath = $${item}.path
+ $$itempath = /assets/$$eval($${deploymentfolder}.target)
+ export($$itemfiles)
+ export($$itempath)
+ INSTALLS += $$item
+ }
+
+ x86 {
+ target.path = /libs/x86
+ } else: armeabi-v7a {
+ target.path = /libs/armeabi-v7a
+ } else {
+ target.path = /libs/armeabi
+ }
+
+ export(target.path)
+ INSTALLS += target
} else:win32 {
copyCommand =
for(deploymentfolder, DEPLOYMENTFOLDERS) {
diff --git a/src/plugins/android/Android.pluginspec.in b/src/plugins/android/Android.pluginspec.in
new file mode 100644
index 00000000000..94083f57664
--- /dev/null
+++ b/src/plugins/android/Android.pluginspec.in
@@ -0,0 +1,22 @@
+
+ KDE Necessitas
+ (C) 2010-2012 BogDan Vatra
+
+Commercial Usage
+
+Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Nokia.
+
+GNU Lesser General Public License Usage
+
+Alternatively, this plugin may be used under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. 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.
+
+ Support for deployment to and execution on Android Devices
+ Device Support
+ http://community.kde.org/Necessitas
+
+
+
+
+
+
+
diff --git a/src/plugins/android/addnewavddialog.ui b/src/plugins/android/addnewavddialog.ui
new file mode 100644
index 00000000000..149f79dfcf9
--- /dev/null
+++ b/src/plugins/android/addnewavddialog.ui
@@ -0,0 +1,133 @@
+
+
+ AddNewAVDDialog
+
+
+
+ 0
+ 0
+ 250
+ 149
+
+
+
+ Create new AVD
+
+
+ -
+
+
-
+
+
+ Name:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ -
+
+
+ Target:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ -
+
+
+ SD card size:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ MiB
+
+
+ 50
+
+
+ 9999999
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 20
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ AddNewAVDDialog
+ accept()
+
+
+ 222
+ 134
+
+
+ 157
+ 148
+
+
+
+
+ buttonBox
+ rejected()
+ AddNewAVDDialog
+ reject()
+
+
+ 245
+ 140
+
+
+ 249
+ 148
+
+
+
+
+
diff --git a/src/plugins/android/android.pri b/src/plugins/android/android.pri
new file mode 100644
index 00000000000..ca008aba34b
--- /dev/null
+++ b/src/plugins/android/android.pri
@@ -0,0 +1,3 @@
+include(android_dependencies.pri)
+
+LIBS *= -l$$qtLibraryName(Android)
diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro
new file mode 100644
index 00000000000..d7168d8746d
--- /dev/null
+++ b/src/plugins/android/android.pro
@@ -0,0 +1,77 @@
+TEMPLATE = lib
+TARGET = Android
+
+include(../../qtcreatorplugin.pri)
+include(android_dependencies.pri)
+
+QT += xml network
+
+HEADERS += \
+ androidconstants.h \
+ androidconfigurations.h \
+ androidrunconfiguration.h \
+ androidruncontrol.h \
+ androidrunfactories.h \
+ androidsettingspage.h \
+ androidsettingswidget.h \
+ androidtoolchain.h \
+ androidpackageinstallationstep.h \
+ androidpackageinstallationfactory.h \
+ androidpackagecreationstep.h \
+ androidpackagecreationfactory.h \
+ androidpackagecreationwidget.h \
+ androiddeploystep.h \
+ androiddeploystepwidget.h \
+ androiddeploystepfactory.h \
+ androidglobal.h \
+ androidrunner.h \
+ androiddebugsupport.h \
+ androidqtversionfactory.h \
+ androidqtversion.h \
+ androiddeployconfiguration.h \
+ androidtarget.h \
+ androidtargetfactory.h \
+ androidcreatekeystorecertificate.h \
+ javaparser.h \
+ androidplugin.h
+
+SOURCES += \
+ androidconfigurations.cpp \
+ androidrunconfiguration.cpp \
+ androidruncontrol.cpp \
+ androidrunfactories.cpp \
+ androidsettingspage.cpp \
+ androidsettingswidget.cpp \
+ androidtoolchain.cpp \
+ androidpackageinstallationstep.cpp \
+ androidpackageinstallationfactory.cpp \
+ androidpackagecreationstep.cpp \
+ androidpackagecreationfactory.cpp \
+ androidpackagecreationwidget.cpp \
+ androiddeploystep.cpp \
+ androiddeploystepwidget.cpp \
+ androiddeploystepfactory.cpp \
+ androidrunner.cpp \
+ androiddebugsupport.cpp \
+ androidqtversionfactory.cpp \
+ androidqtversion.cpp \
+ androiddeployconfiguration.cpp \
+ androidtarget.cpp \
+ androidtargetfactory.cpp \
+ androidcreatekeystorecertificate.cpp \
+ javaparser.cpp \
+ androidplugin.cpp
+
+
+FORMS += \
+ androidsettingswidget.ui \
+ androidpackagecreationwidget.ui \
+ androiddeploystepwidget.ui \
+ addnewavddialog.ui \
+ androidcreatekeystorecertificate.ui
+
+RESOURCES = android.qrc
+DEFINES += QT_NO_CAST_TO_ASCII
+DEFINES += ANDROID_LIBRARY
+
+
diff --git a/src/plugins/android/android.qrc b/src/plugins/android/android.qrc
new file mode 100644
index 00000000000..94570ee5f5d
--- /dev/null
+++ b/src/plugins/android/android.qrc
@@ -0,0 +1,5 @@
+
+
+ images/QtAndroid.png
+
+
diff --git a/src/plugins/android/android_dependencies.pri b/src/plugins/android/android_dependencies.pri
new file mode 100644
index 00000000000..c2940f93623
--- /dev/null
+++ b/src/plugins/android/android_dependencies.pri
@@ -0,0 +1,4 @@
+include(../../plugins/coreplugin/coreplugin.pri)
+include(../../plugins/debugger/debugger.pri)
+include(../../plugins/projectexplorer/projectexplorer.pri)
+include(../../plugins/qt4projectmanager/qt4projectmanager.pri)
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
new file mode 100644
index 00000000000..1da6fd6c994
--- /dev/null
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -0,0 +1,632 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidconfigurations.h"
+#include "androidconstants.h"
+#include "ui_addnewavddialog.h"
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#if defined(_WIN32)
+#include
+#include
+#define sleep(_n) Sleep(1000 * (_n))
+#endif
+
+using namespace Utils;
+
+namespace Android {
+namespace Internal {
+
+namespace {
+ const QLatin1String SettingsGroup("AndroidConfigurations");
+ const QLatin1String SDKLocationKey("SDKLocation");
+ const QLatin1String NDKLocationKey("NDKLocation");
+ const QLatin1String NDKToolchainVersionKey("NDKToolchainVersion");
+ const QLatin1String AntLocationKey("AntLocation");
+ const QLatin1String ArmGdbLocationKey("GdbLocation");
+ const QLatin1String ArmGdbserverLocationKey("GdbserverLocation");
+ const QLatin1String X86GdbLocationKey("X86GdbLocation");
+ const QLatin1String X86GdbserverLocationKey("X86GdbserverLocation");
+ const QLatin1String OpenJDKLocationKey("OpenJDKLocation");
+ const QLatin1String KeystoreLocationKey("KeystoreLocation");
+ const QLatin1String PartitionSizeKey("PartitionSize");
+ const QLatin1String NDKGccVersionRegExp("\\d\\.\\d\\.\\d");
+ const QLatin1String ArmToolchainPrefix("arm-linux-androideabi");
+ const QLatin1String X86ToolchainPrefix("x86");
+ const QLatin1String ArmToolsPrefix("arm-linux-androideabi");
+ const QLatin1String X86ToolsPrefix("i686-android-linux");
+ const QLatin1String Unknown("unknown");
+ const QLatin1String keytoolName("keytool");
+ const QLatin1String jarsignerName("jarsigner");
+ const QLatin1String androidFilename("/android.xml");
+ const QLatin1String changeTimeStamp("ChangeTimeStamp");
+
+ static QString settingsFileName()
+ {
+ return Core::ICore::instance()->resourcePath()
+ + QLatin1String("/Nokia") + androidFilename;
+ }
+
+ bool androidDevicesLessThan(const AndroidDevice &dev1, const AndroidDevice &dev2)
+ {
+ return dev1.sdk < dev2.sdk;
+ }
+}
+
+QLatin1String AndroidConfigurations::toolchainPrefix(ProjectExplorer::Abi::Architecture architecture)
+{
+ switch (architecture) {
+ case ProjectExplorer::Abi::ArmArchitecture:
+ return ArmToolchainPrefix;
+ case ProjectExplorer::Abi::X86Architecture:
+ return X86ToolchainPrefix;
+ default:
+ return Unknown;
+ }
+}
+
+
+QLatin1String AndroidConfigurations::toolsPrefix(ProjectExplorer::Abi::Architecture architecture)
+{
+ switch (architecture) {
+ case ProjectExplorer::Abi::ArmArchitecture:
+ return ArmToolsPrefix;
+ case ProjectExplorer::Abi::X86Architecture:
+ return X86ToolsPrefix;
+ default:
+ return Unknown;
+ }
+}
+
+AndroidConfig::AndroidConfig(const QSettings &settings)
+{
+ // user settings
+ armGdbLocation = settings.value(ArmGdbLocationKey).toString();
+ armGdbserverLocation = settings.value(ArmGdbserverLocationKey).toString();
+ x86GdbLocation = settings.value(X86GdbLocationKey).toString();
+ x86GdbserverLocation = settings.value(X86GdbserverLocationKey).toString();
+ partitionSize = settings.value(PartitionSizeKey, 1024).toInt();
+ sdkLocation = settings.value(SDKLocationKey).toString();
+ ndkLocation = settings.value(NDKLocationKey).toString();
+ antLocation = settings.value(AntLocationKey).toString();
+ openJDKLocation = settings.value(OpenJDKLocationKey).toString();
+ keystoreLocation = settings.value(KeystoreLocationKey).toString();
+
+ QRegExp versionRegExp(NDKGccVersionRegExp);
+ const QString &value = settings.value(NDKToolchainVersionKey).toString();
+ if (versionRegExp.exactMatch(value))
+ ndkToolchainVersion = value;
+ else
+ ndkToolchainVersion = value.mid(versionRegExp.indexIn(value));
+ // user settings
+
+ PersistentSettingsReader reader;
+ if (reader.load(settingsFileName())
+ && settings.value(changeTimeStamp).toInt() != QFileInfo(settingsFileName()).lastModified().toMSecsSinceEpoch() / 1000) {
+ // persisten settings
+ sdkLocation = reader.restoreValue(SDKLocationKey).toString();
+ ndkLocation = reader.restoreValue(NDKLocationKey).toString();
+ antLocation = reader.restoreValue(AntLocationKey).toString();
+ openJDKLocation = reader.restoreValue(OpenJDKLocationKey).toString();
+ keystoreLocation = reader.restoreValue(KeystoreLocationKey).toString();
+
+ QRegExp versionRegExp(NDKGccVersionRegExp);
+ const QString &value = reader.restoreValue(NDKToolchainVersionKey).toString();
+ if (versionRegExp.exactMatch(value))
+ ndkToolchainVersion = value;
+ else
+ ndkToolchainVersion = value.mid(versionRegExp.indexIn(value));
+
+ if (!armGdbLocation.length())
+ armGdbLocation = reader.restoreValue(ArmGdbLocationKey).toString();
+
+ if (!armGdbserverLocation.length())
+ armGdbserverLocation = reader.restoreValue(ArmGdbserverLocationKey).toString();
+
+ if (!x86GdbLocation.length())
+ x86GdbLocation = reader.restoreValue(X86GdbLocationKey).toString();
+
+ if (!x86GdbserverLocation.length())
+ x86GdbserverLocation = reader.restoreValue(X86GdbserverLocationKey).toString();
+ // persistent settings
+ }
+
+}
+
+AndroidConfig::AndroidConfig()
+{
+ partitionSize = 1024;
+}
+
+void AndroidConfig::save(QSettings &settings) const
+{
+ QFileInfo fileInfo(settingsFileName());
+ if (fileInfo.exists())
+ settings.setValue(changeTimeStamp, fileInfo.lastModified().toMSecsSinceEpoch() / 1000);
+
+ // user settings
+ settings.setValue(SDKLocationKey, sdkLocation);
+ settings.setValue(NDKLocationKey, ndkLocation);
+ settings.setValue(NDKToolchainVersionKey, ndkToolchainVersion);
+ settings.setValue(AntLocationKey, antLocation);
+ settings.setValue(OpenJDKLocationKey, openJDKLocation);
+ settings.setValue(KeystoreLocationKey, keystoreLocation);
+ settings.setValue(ArmGdbLocationKey, armGdbLocation);
+ settings.setValue(ArmGdbserverLocationKey, armGdbserverLocation);
+ settings.setValue(X86GdbLocationKey, x86GdbLocation);
+ settings.setValue(X86GdbserverLocationKey, x86GdbserverLocation);
+ settings.setValue(PartitionSizeKey, partitionSize);
+ // user settings
+
+}
+
+void AndroidConfigurations::setConfig(const AndroidConfig &devConfigs)
+{
+ m_config = devConfigs;
+ save();
+ updateAvailablePlatforms();
+ emit updated();
+}
+
+void AndroidConfigurations::updateAvailablePlatforms()
+{
+ m_availablePlatforms.clear();
+ QDirIterator it(m_config.ndkLocation + QLatin1String("/platforms"), QStringList() << QLatin1String("android-*"), QDir::Dirs);
+ while (it.hasNext()) {
+ const QString &fileName = it.next();
+ m_availablePlatforms.push_back(fileName.mid(fileName.lastIndexOf(QLatin1Char('-')) + 1).toInt());
+ }
+ qSort(m_availablePlatforms.begin(), m_availablePlatforms.end(), qGreater());
+}
+
+QStringList AndroidConfigurations::sdkTargets(int minApiLevel) const
+{
+ QStringList targets;
+ QProcess proc;
+ proc.start(androidToolPath(), QStringList() << QLatin1String("list") << QLatin1String("target")); // list avaialbe AVDs
+ if (!proc.waitForFinished(-1)) {
+ proc.terminate();
+ return targets;
+ }
+ QList avds = proc.readAll().trimmed().split('\n');
+ for (int i = 0; i < avds.size(); i++) {
+ QString line = QLatin1String(avds[i]);
+ int index = line.indexOf(QLatin1String("\"android-"));
+ if (index == -1)
+ continue;
+ QString apiLevel = line.mid(index + 1, line.length() - index - 2);
+ if (apiLevel.mid(apiLevel.lastIndexOf(QLatin1Char('-')) + 1).toInt() >= minApiLevel)
+ targets.push_back(apiLevel);
+ }
+ return targets;
+}
+
+QStringList AndroidConfigurations::ndkToolchainVersions() const
+{
+ QRegExp versionRegExp(NDKGccVersionRegExp);
+ QStringList result;
+ QDirIterator it(m_config.ndkLocation + QLatin1String("/toolchains"),
+ QStringList() << QLatin1String("*"), QDir::Dirs);
+ while (it.hasNext()) {
+ const QString &fileName = it.next();
+ int idx = versionRegExp.indexIn(fileName);
+ if (idx == -1)
+ continue;
+ QString version = fileName.mid(idx);
+ if (!result.contains(version))
+ result.append(version);
+ }
+ return result;
+}
+
+QString AndroidConfigurations::adbToolPath() const
+{
+ return m_config.sdkLocation + QLatin1String("/platform-tools/adb"ANDROID_EXE_SUFFIX);
+}
+
+QString AndroidConfigurations::androidToolPath() const
+{
+#ifdef Q_OS_WIN32
+ // I want to switch from using android.bat to using an executable. All it really does is call
+ // Java and I've made some progress on it. So if android.exe exists, return that instead.
+ QFileInfo fi(m_config.SDKLocation + QLatin1String("/tools/android"ANDROID_EXE_SUFFIX));
+ if (fi.exists())
+ return m_config.SDKLocation + QString("/tools/android"ANDROID_EXE_SUFFIX);
+ else
+ return m_config.SDKLocation + QLatin1String("/tools/android"ANDROID_BAT_SUFFIX);
+#else
+ return m_config.sdkLocation + QLatin1String("/tools/android"ANDROID_EXE_SUFFIX);
+#endif
+}
+
+QString AndroidConfigurations::antToolPath() const
+{
+ if (m_config.antLocation.length())
+ return m_config.antLocation;
+ else
+ return QLatin1String("ant");
+}
+
+QString AndroidConfigurations::emulatorToolPath() const
+{
+ return m_config.sdkLocation + QLatin1String("/tools/emulator"ANDROID_EXE_SUFFIX);
+}
+
+QString AndroidConfigurations::toolPath(ProjectExplorer::Abi::Architecture architecture) const
+{
+ return m_config.ndkLocation + QString::fromLatin1("/toolchains/%1-%2/prebuilt/%3/bin/%4")
+ .arg(toolchainPrefix(architecture))
+ .arg(m_config.ndkToolchainVersion)
+ .arg(ToolchainHost)
+ .arg(toolsPrefix(architecture));
+}
+
+QString AndroidConfigurations::stripPath(ProjectExplorer::Abi::Architecture architecture) const
+{
+ return toolPath(architecture) + QLatin1String("-strip"ANDROID_EXE_SUFFIX);
+}
+
+QString AndroidConfigurations::readelfPath(ProjectExplorer::Abi::Architecture architecture) const
+{
+ return toolPath(architecture) + QLatin1String("-readelf"ANDROID_EXE_SUFFIX);
+}
+
+QString AndroidConfigurations::gccPath(ProjectExplorer::Abi::Architecture architecture) const
+{
+ return toolPath(architecture) + QLatin1String("-gcc"ANDROID_EXE_SUFFIX);
+}
+
+QString AndroidConfigurations::gdbServerPath(ProjectExplorer::Abi::Architecture architecture) const
+{
+ QString gdbServerPath;
+ switch (architecture) {
+ case ProjectExplorer::Abi::ArmArchitecture:
+ gdbServerPath = m_config.armGdbserverLocation;
+ break;
+ case ProjectExplorer::Abi::X86Architecture:
+ gdbServerPath = m_config.x86GdbserverLocation;
+ break;
+ default:
+ gdbServerPath = Unknown;
+ break;
+ }
+
+ if (gdbServerPath.length())
+ return gdbServerPath;
+ return m_config.ndkLocation + QString::fromLatin1("/toolchains/%1-%2/prebuilt/gdbserver")
+ .arg(toolchainPrefix(architecture))
+ .arg(m_config.ndkToolchainVersion);
+}
+
+QString AndroidConfigurations::gdbPath(ProjectExplorer::Abi::Architecture architecture) const
+{
+ QString gdbPath;
+ switch (architecture) {
+ case ProjectExplorer::Abi::ArmArchitecture:
+ gdbPath = m_config.armGdbLocation;
+ break;
+ case ProjectExplorer::Abi::X86Architecture:
+ gdbPath = m_config.x86GdbLocation;
+ break;
+ default:
+ gdbPath = Unknown;
+ break;
+ }
+ if (!gdbPath.isEmpty())
+ return gdbPath;
+ return toolPath(architecture) + QLatin1String("-gdb"ANDROID_EXE_SUFFIX);
+}
+
+QString AndroidConfigurations::openJDKPath() const
+{
+ return m_config.openJDKLocation;
+}
+
+QString AndroidConfigurations::openJDKBinPath() const
+{
+ if (m_config.openJDKLocation.length())
+ return m_config.openJDKLocation + QLatin1String("/bin/");
+ return QString();
+}
+
+QString AndroidConfigurations::keytoolPath() const
+{
+ return openJDKBinPath() + keytoolName;
+}
+
+QString AndroidConfigurations::jarsignerPath() const
+{
+ return openJDKBinPath() + jarsignerName;
+}
+
+QString AndroidConfigurations::getDeployDeviceSerialNumber(int *apiLevel) const
+{
+ QVector devices = connectedDevices();
+
+ foreach (AndroidDevice device, devices)
+ if (device.sdk >= *apiLevel) {
+ *apiLevel = device.sdk;
+ return device.serialNumber;
+ }
+ return startAVD(apiLevel);
+}
+
+QVector AndroidConfigurations::connectedDevices(int apiLevel) const
+{
+ QVector devices;
+ QProcess adbProc;
+ adbProc.start(adbToolPath(), QStringList() << QLatin1String("devices"));
+ if (!adbProc.waitForFinished(-1)) {
+ adbProc.terminate();
+ return devices;
+ }
+ QList adbDevs = adbProc.readAll().trimmed().split('\n');
+ adbDevs.removeFirst();
+ AndroidDevice dev;
+ foreach (const QByteArray &device, adbDevs) {
+ dev.serialNumber = QString::fromLatin1(device.left(device.indexOf('\t')).trimmed());
+ dev.sdk = getSDKVersion(dev.serialNumber);
+ if (apiLevel != -1 && dev.sdk != apiLevel)
+ continue;
+ devices.push_back(dev);
+ }
+ qSort(devices.begin(), devices.end(), androidDevicesLessThan);
+ return devices;
+}
+
+bool AndroidConfigurations::createAVD(int minApiLevel) const
+{
+ QDialog d;
+ Ui::AddNewAVDDialog avdDialog;
+ avdDialog.setupUi(&d);
+ QStringListModel model(sdkTargets(minApiLevel));
+ avdDialog.targetComboBox->setModel(&model);
+ if (!model.rowCount()) {
+ QMessageBox::critical(0, tr("Create AVD error"),
+ tr("Can't create a new AVD, not enough android SDKs available\n"
+ "Please install one SDK with api version >=%1").arg(minApiLevel));
+ return false;
+ }
+
+ QRegExp rx(QLatin1String("\\S+"));
+ QRegExpValidator v(rx, 0);
+ avdDialog.nameLineEdit->setValidator(&v);
+ if (d.exec() != QDialog::Accepted)
+ return false;
+ return createAVD(avdDialog.targetComboBox->currentText(), avdDialog.nameLineEdit->text(), avdDialog.sizeSpinBox->value());
+}
+
+bool AndroidConfigurations::createAVD(const QString &target, const QString &name, int sdcardSize ) const
+{
+ QProcess proc;
+ proc.start(androidToolPath(),
+ QStringList() << QLatin1String("create") << QLatin1String("avd")
+ << QLatin1String("-a") << QLatin1String("-t") << target
+ << QLatin1String("-n") << name
+ << QLatin1String("-c") << QString::fromLatin1("%1M").arg(sdcardSize));
+ if (!proc.waitForStarted())
+ return false;
+ proc.write(QByteArray("no\n"));
+ if (!proc.waitForFinished(-1)) {
+ proc.terminate();
+ return false;
+ }
+ return !proc.exitCode();
+}
+
+bool AndroidConfigurations::removeAVD(const QString &name) const
+{
+ QProcess proc;
+ proc.start(androidToolPath(),
+ QStringList() << QLatin1String("delete") << QLatin1String("avd")
+ << QLatin1String("-n") << name);
+ if (!proc.waitForFinished(-1)) {
+ proc.terminate();
+ return false;
+ }
+ return !proc.exitCode();
+}
+
+QVector AndroidConfigurations::androidVirtualDevices() const
+{
+ QVector devices;
+ QProcess proc;
+ proc.start(androidToolPath(),
+ QStringList() << QLatin1String("list") << QLatin1String("avd")); // list available AVDs
+ if (!proc.waitForFinished(-1)) {
+ proc.terminate();
+ return devices;
+ }
+ QList avds = proc.readAll().trimmed().split('\n');
+ avds.removeFirst();
+ AndroidDevice dev;
+ for (int i = 0; i < avds.size(); i++) {
+ QString line = QLatin1String(avds[i]);
+ if (!line.contains(QLatin1String("Name:")))
+ continue;
+
+ dev.serialNumber = line.mid(line.indexOf(QLatin1Char(':')) + 2).trimmed();
+ ++i;
+ for (; i < avds.size(); ++i) {
+ line = QLatin1String(avds[i]);
+ if (line.contains(QLatin1String("---------")))
+ break;
+ if (line.contains(QLatin1String("Target:")))
+ dev.sdk = line.mid(line.lastIndexOf(QLatin1Char(' '))).remove(QLatin1Char(')')).toInt();
+ if (line.contains(QLatin1String("ABI:")))
+ dev.cpuABI = line.mid(line.lastIndexOf(QLatin1Char(' '))).trimmed();
+ }
+ devices.push_back(dev);
+ }
+ qSort(devices.begin(), devices.end(), androidDevicesLessThan);
+
+ return devices;
+}
+
+QString AndroidConfigurations::startAVD(int *apiLevel, const QString &name) const
+{
+ QProcess *m_avdProcess = new QProcess();
+ connect(this, SIGNAL(destroyed()), m_avdProcess, SLOT(deleteLater()));
+ connect(m_avdProcess, SIGNAL(finished(int)), m_avdProcess, SLOT(deleteLater()));
+
+ QString avdName = name;
+ QVector devices;
+ bool createAVDOnce = false;
+ while (true) {
+ if (avdName.isEmpty()) {
+ devices = androidVirtualDevices();
+ foreach (AndroidDevice device, devices)
+ if (device.sdk >= *apiLevel) { // take first emulator how supports this package
+ *apiLevel = device.sdk;
+ avdName = device.serialNumber;
+ break;
+ }
+ }
+ // if no emulators found try to create one once
+ if (avdName.isEmpty() && !createAVDOnce) {
+ createAVDOnce = true;
+ QMetaObject::invokeMethod(const_cast(static_cast(this)), "createAVD", Qt::AutoConnection,
+ Q_ARG(int, *apiLevel));
+ } else {
+ break;
+ }
+ }
+
+ if (avdName.isEmpty())// stop here if no emulators found
+ return avdName;
+
+ // start the emulator
+ m_avdProcess->start(emulatorToolPath(),
+ QStringList() << QLatin1String("-partition-size") << QString::number(config().partitionSize)
+ << QLatin1String("-avd") << avdName);
+ if (!m_avdProcess->waitForStarted(-1)) {
+ delete m_avdProcess;
+ return QString();
+ }
+
+ // wait until the emulator is online
+ QProcess proc;
+ proc.start(adbToolPath(), QStringList() << QLatin1String("-e") << QLatin1String("wait-for-device"));
+ if (!proc.waitForFinished(-1)) {
+ proc.terminate();
+ return QString();
+ }
+ sleep(5);// wait for pm to start
+
+ // workaround for stupid adb bug
+ proc.start(adbToolPath(), QStringList() << QLatin1String("devices"));
+ if (!proc.waitForFinished(-1)) {
+ proc.terminate();
+ return QString();
+ }
+
+ // get connected devices
+ devices = connectedDevices(*apiLevel);
+ foreach (AndroidDevice device, devices)
+ if (device.sdk == *apiLevel)
+ return device.serialNumber;
+ // this should not happen, but ...
+ return QString();
+}
+
+int AndroidConfigurations::getSDKVersion(const QString &device) const
+{
+
+ QProcess adbProc;
+ adbProc.start(adbToolPath(),
+ QStringList() << QLatin1String("-s") << device
+ << QLatin1String("shell") << QLatin1String("getprop")
+ << QLatin1String("ro.build.version.sdk"));
+ if (!adbProc.waitForFinished(-1)) {
+ adbProc.terminate();
+ return -1;
+ }
+ return adbProc.readAll().trimmed().toInt();
+}
+
+QString AndroidConfigurations::bestMatch(const QString &targetAPI) const
+{
+ int target = targetAPI.mid(targetAPI.lastIndexOf(QLatin1Char('-')) + 1).toInt();
+ foreach (int apiLevel, m_availablePlatforms) {
+ if (apiLevel <= target)
+ return QString::fromLatin1("android-%1").arg(apiLevel);
+ }
+ return QLatin1String("android-8");
+}
+
+AndroidConfigurations &AndroidConfigurations::instance(QObject *parent)
+{
+ if (m_instance == 0)
+ m_instance = new AndroidConfigurations(parent);
+ return *m_instance;
+}
+
+void AndroidConfigurations::save()
+{
+ QSettings *settings = Core::ICore::instance()->settings();
+ settings->beginGroup(SettingsGroup);
+ m_config.save(*settings);
+ settings->endGroup();
+}
+
+AndroidConfigurations::AndroidConfigurations(QObject *parent)
+ : QObject(parent)
+{
+ load();
+ updateAvailablePlatforms();
+}
+
+void AndroidConfigurations::load()
+{
+ QSettings *settings = Core::ICore::instance()->settings();
+ settings->beginGroup(SettingsGroup);
+ m_config = AndroidConfig(*settings);
+ settings->endGroup();
+}
+
+AndroidConfigurations *AndroidConfigurations::m_instance = 0;
+
+} // namespace Internal
+} // namespace Android
diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h
new file mode 100644
index 00000000000..6fc01f0796a
--- /dev/null
+++ b/src/plugins/android/androidconfigurations.h
@@ -0,0 +1,149 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDCONFIGURATIONS_H
+#define ANDROIDCONFIGURATIONS_H
+
+#include
+#include
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+class QSettings;
+QT_END_NAMESPACE
+
+namespace Android {
+namespace Internal {
+
+#ifdef Q_OS_LINUX
+ const QLatin1String ToolchainHost("linux-x86");
+#else
+# ifdef Q_OS_DARWIN
+ const QLatin1String ToolchainHost("darwin-x86");
+# else
+# ifdef Q_OS_WIN32
+ const QLatin1String ToolchainHost("windows");
+# else
+# warning No Android supported OSs found
+ const QLatin1String ToolchainHost("linux-x86");
+# endif
+# endif
+#endif
+
+class AndroidConfig
+{
+public:
+ AndroidConfig();
+ AndroidConfig(const QSettings &settings);
+ void save(QSettings &settings) const;
+
+ QString sdkLocation;
+ QString ndkLocation;
+ QString ndkToolchainVersion;
+ QString antLocation;
+ QString armGdbLocation;
+ QString armGdbserverLocation;
+ QString x86GdbLocation;
+ QString x86GdbserverLocation;
+ QString openJDKLocation;
+ QString keystoreLocation;
+ unsigned partitionSize;
+};
+
+struct AndroidDevice {
+ QString serialNumber;
+ QString cpuABI;
+ int sdk;
+};
+
+class AndroidConfigurations : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(AndroidConfigurations)
+public:
+
+ static AndroidConfigurations &instance(QObject *parent = 0);
+ AndroidConfig config() const { return m_config; }
+ void setConfig(const AndroidConfig &config);
+ QStringList sdkTargets(int minApiLevel = 0) const;
+ QStringList ndkToolchainVersions() const;
+ QString adbToolPath() const;
+ QString androidToolPath() const;
+ QString antToolPath() const;
+ QString emulatorToolPath() const;
+ QString gccPath(ProjectExplorer::Abi::Architecture architecture) const;
+ QString gdbServerPath(ProjectExplorer::Abi::Architecture architecture) const;
+ QString gdbPath(ProjectExplorer::Abi::Architecture architecture) const;
+ QString openJDKPath() const;
+ QString keytoolPath() const;
+ QString jarsignerPath() const;
+ QString stripPath(ProjectExplorer::Abi::Architecture architecture) const;
+ QString readelfPath(ProjectExplorer::Abi::Architecture architecture) const;
+ QString getDeployDeviceSerialNumber(int *apiLevel) const;
+ bool createAVD(const QString &target, const QString &name, int sdcardSize) const;
+ bool removeAVD(const QString &name) const;
+ QVector connectedDevices(int apiLevel = -1) const;
+ QVector androidVirtualDevices() const;
+ QString startAVD(int *apiLevel, const QString &name = QString()) const;
+ QString bestMatch(const QString &targetAPI) const;
+
+ static QLatin1String toolchainPrefix(ProjectExplorer::Abi::Architecture architecture);
+ static QLatin1String toolsPrefix(ProjectExplorer::Abi::Architecture architecture);
+
+signals:
+ void updated();
+
+public slots:
+ bool createAVD(int minApiLevel = 0) const;
+
+private:
+ QString toolPath(ProjectExplorer::Abi::Architecture architecture) const;
+ QString openJDKBinPath() const;
+
+ AndroidConfigurations(QObject *parent);
+ void load();
+ void save();
+
+ int getSDKVersion(const QString &device) const;
+ void updateAvailablePlatforms();
+
+
+ static AndroidConfigurations *m_instance;
+ AndroidConfig m_config;
+ QVector m_availablePlatforms;
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDCONFIGURATIONS_H
diff --git a/src/plugins/android/androidconstants.h b/src/plugins/android/androidconstants.h
new file mode 100644
index 00000000000..22798b17e7e
--- /dev/null
+++ b/src/plugins/android/androidconstants.h
@@ -0,0 +1,86 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDCONSTANTS_H
+#define ANDROIDCONSTANTS_H
+
+#include
+
+namespace Android {
+namespace Internal {
+
+enum AndroidQemuStatus {
+ AndroidQemuStarting,
+ AndroidQemuFailedToStart,
+ AndroidQemuFinished,
+ AndroidQemuCrashed,
+ AndroidQemuUserReason
+};
+
+#define ANDROID_PREFIX "Qt4ProjectManager.AndroidRunConfiguration"
+
+#ifdef Q_OS_WIN32
+#define ANDROID_EXE_SUFFIX ".exe"
+#define ANDROID_BAT_SUFFIX ".bat"
+#else
+#define ANDROID_EXE_SUFFIX ""
+#define ANDROID_BAT_SUFFIX ""
+#endif
+
+static const QLatin1String ANDROID_RC_ID(ANDROID_PREFIX);
+static const QLatin1String ANDROID_RC_ID_PREFIX(ANDROID_PREFIX ".");
+
+static const QLatin1String AndroidArgumentsKey(ANDROID_PREFIX ".Arguments");
+static const QLatin1String AndroidSimulatorPathKey(ANDROID_PREFIX ".Simulator");
+static const QLatin1String AndroidDeviceIdKey(ANDROID_PREFIX ".DeviceId");
+static const QLatin1String AndroidProFileKey(ANDROID_PREFIX ".ProFile");
+static const QLatin1String AndroidExportedLocalDirsKey(ANDROID_PREFIX ".ExportedLocalDirs");
+static const QLatin1String AndroidBaseEnvironmentBaseKey(ANDROID_PREFIX ".BaseEnvironmentBase");
+static const QLatin1String AndroidUserEnvironmentChangesKey(ANDROID_PREFIX ".UserEnvironmentChanges");
+static const QLatin1String AndroidUseRemoteGdbKey(ANDROID_PREFIX ".UseRemoteGdb");
+
+} // namespace Internal
+
+namespace Constants {
+const char ANDROID_SETTINGS_ID[] = "ZZ.Android Configurations";
+const char ANDROID_SETTINGS_CATEGORY[] = "X.Android";
+const char ANDROID_SETTINGS_TR_CATEGORY[] = QT_TRANSLATE_NOOP("Android", "Android");
+const char ANDROID_SETTINGS_CATEGORY_ICON[] = ":/android/images/QtAndroid.png";
+const char ANDROID_TOOLCHAIN_ID[] = "Qt4ProjectManager.ToolChain.Android";
+const char ANDROIDQT[] = "Qt4ProjectManager.QtVersion.Android";
+const char ANDROID_PLATFORM[] = "Android";
+const char ANDROID_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "Android");
+
+}
+} // namespace Android
+
+#endif // ANDROIDCONSTANTS_H
diff --git a/src/plugins/android/androidcreatekeystorecertificate.cpp b/src/plugins/android/androidcreatekeystorecertificate.cpp
new file mode 100644
index 00000000000..8a326c3b59c
--- /dev/null
+++ b/src/plugins/android/androidcreatekeystorecertificate.cpp
@@ -0,0 +1,198 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidcreatekeystorecertificate.h"
+#include "androidconfigurations.h"
+#include "ui_androidcreatekeystorecertificate.h"
+
+#include
+#include
+#include
+
+using namespace Android::Internal;
+
+AndroidCreateKeystoreCertificate::AndroidCreateKeystoreCertificate(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::AndroidCreateKeystoreCertificate)
+{
+ ui->setupUi(this);
+ connect(ui->keystorePassLineEdit, SIGNAL(textChanged(QString)), this, SLOT(checkKeystorePassword()));
+ connect(ui->keystoreRetypePassLineEdit, SIGNAL(textChanged(QString)), this, SLOT(checkKeystorePassword()));
+ connect(ui->certificatePassLineEdit, SIGNAL(textChanged(QString)), this, SLOT(checkCertificatePassword()));
+ connect(ui->certificateRetypePassLineEdit, SIGNAL(textChanged(QString)), this, SLOT(checkCertificatePassword()));
+}
+
+AndroidCreateKeystoreCertificate::~AndroidCreateKeystoreCertificate()
+{
+ delete ui;
+}
+
+QString AndroidCreateKeystoreCertificate::keystoreFilePath()
+{
+ return m_keystoreFilePath;
+}
+
+QString AndroidCreateKeystoreCertificate::keystorePassword()
+{
+ return ui->keystorePassLineEdit->text();
+}
+
+QString AndroidCreateKeystoreCertificate::certificateAlias()
+{
+ return ui->aliasNameLineEdit->text();
+}
+
+QString AndroidCreateKeystoreCertificate::certificatePassword()
+{
+ return ui->certificatePassLineEdit->text();
+}
+
+AndroidCreateKeystoreCertificate::PasswordStatus AndroidCreateKeystoreCertificate::checkKeystorePassword()
+{
+ if (ui->keystorePassLineEdit->text().length() < 6) {
+ ui->keystorePassInfoLabel->setText(tr("Password is too short"));
+ return Invalid;
+ }
+ if (ui->keystorePassLineEdit->text() != ui->keystoreRetypePassLineEdit->text()) {
+ ui->keystorePassInfoLabel->setText(tr("Passwords don't match"));
+ return NoMatch;
+ }
+ ui->keystorePassInfoLabel->setText(tr("Password is ok"));
+ return Match;
+}
+
+AndroidCreateKeystoreCertificate::PasswordStatus AndroidCreateKeystoreCertificate::checkCertificatePassword()
+{
+ if (ui->certificatePassLineEdit->text().length() < 6) {
+ ui->certificatePassInfoLabel->setText(tr("Password is too short"));
+ return Invalid;
+ }
+ if (ui->certificatePassLineEdit->text() != ui->certificateRetypePassLineEdit->text()) {
+ ui->certificatePassInfoLabel->setText(tr("Passwords don't match"));
+ return NoMatch;
+ }
+ ui->certificatePassInfoLabel->setText(tr("Password is ok"));
+ return Match;
+}
+
+void AndroidCreateKeystoreCertificate::on_keystoreShowPassCheckBox_stateChanged(int state)
+{
+ ui->keystorePassLineEdit->setEchoMode(state == Qt::Checked ? QLineEdit::Normal : QLineEdit::Password);
+ ui->keystoreRetypePassLineEdit->setEchoMode(ui->keystorePassLineEdit->echoMode());
+}
+
+void AndroidCreateKeystoreCertificate::on_certificateShowPassCheckBox_stateChanged(int state)
+{
+ ui->certificatePassLineEdit->setEchoMode(state == Qt::Checked ? QLineEdit::Normal : QLineEdit::Password);
+ ui->certificateRetypePassLineEdit->setEchoMode(ui->certificatePassLineEdit->echoMode());
+}
+
+void AndroidCreateKeystoreCertificate::on_buttonBox_accepted()
+{
+ switch (checkKeystorePassword()) {
+ case Invalid:
+ ui->keystorePassLineEdit->setFocus();
+ return;
+ case NoMatch:
+ ui->keystoreRetypePassLineEdit->setFocus();
+ return;
+ default:
+ break;
+ }
+
+ switch (checkCertificatePassword()) {
+ case Invalid:
+ ui->certificatePassLineEdit->setFocus();
+ return;
+ case NoMatch:
+ ui->certificateRetypePassLineEdit->setFocus();
+ return;
+ default:
+ break;
+ }
+
+ if (!ui->aliasNameLineEdit->text().length())
+ ui->aliasNameLineEdit->setFocus();
+
+ if (!ui->commonNameLineEdit->text().length())
+ ui->commonNameLineEdit->setFocus();
+
+ if (!ui->organizationNameLineEdit->text().length())
+ ui->organizationNameLineEdit->setFocus();
+
+ if (!ui->localityNameLineEdit->text().length())
+ ui->localityNameLineEdit->setFocus();
+
+ if (!ui->countryLineEdit->text().length())
+ ui->countryLineEdit->setFocus();
+
+ m_keystoreFilePath = QFileDialog::getSaveFileName(this, tr("Keystore file name"),
+ QDir::homePath() + QLatin1String("/android_release.keystore"),
+ tr("Keystore files (*.keystore *.jks)"));
+ if (!m_keystoreFilePath.length())
+ return;
+ QString distinguishedNames(QString::fromLatin1("CN=%1, O=%2, L=%3, C=%4")
+ .arg(ui->commonNameLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,")))
+ .arg(ui->organizationNameLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,")))
+ .arg(ui->localityNameLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,")))
+ .arg(ui->countryLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,"))));
+
+ if (ui->organizationUnitLineEdit->text().length())
+ distinguishedNames += QLatin1String(", OU=") + ui->organizationUnitLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,"));
+
+ if (ui->stateNameLineEdit->text().length())
+ distinguishedNames += QLatin1String(", S=") + ui->stateNameLineEdit->text().replace(QLatin1Char(','), QLatin1String("\\,"));
+
+ QStringList params;
+ params << QLatin1String("-genkey") << QLatin1String("-keyalg") << QLatin1String("RSA")
+ << QLatin1String("-keystore") << m_keystoreFilePath
+ << QLatin1String("-storepass") << ui->keystorePassLineEdit->text()
+ << QLatin1String("-alias") << ui->aliasNameLineEdit->text()
+ << QLatin1String("-keysize") << ui->keySizeSpinBox->text()
+ << QLatin1String("-validity") << ui->validitySpinBox->text()
+ << QLatin1String("-keypass") << ui->certificatePassLineEdit->text()
+ << QLatin1String("-dname") << distinguishedNames;
+
+ QProcess genKeyCertProc;
+ genKeyCertProc.start(AndroidConfigurations::instance().keytoolPath(), params );
+
+ if (!genKeyCertProc.waitForStarted() || !genKeyCertProc.waitForFinished())
+ return;
+
+ if (genKeyCertProc.exitCode()) {
+ QMessageBox::critical(this, tr("Error")
+ , QString::fromLatin1(genKeyCertProc.readAllStandardOutput())
+ + QString::fromLatin1(genKeyCertProc.readAllStandardError()));
+ return;
+ }
+ accept();
+}
diff --git a/src/plugins/android/androidcreatekeystorecertificate.h b/src/plugins/android/androidcreatekeystorecertificate.h
new file mode 100644
index 00000000000..bcdc68750e2
--- /dev/null
+++ b/src/plugins/android/androidcreatekeystorecertificate.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDCREATEKEYSTORECERTIFICATE_H
+#define ANDROIDCREATEKEYSTORECERTIFICATE_H
+
+#include
+
+namespace Ui {
+ class AndroidCreateKeystoreCertificate;
+}
+namespace Android {
+namespace Internal {
+class AndroidCreateKeystoreCertificate : public QDialog
+{
+ Q_OBJECT
+ enum PasswordStatus
+ {
+ Invalid,
+ NoMatch,
+ Match
+ };
+
+public:
+ explicit AndroidCreateKeystoreCertificate(QWidget *parent = 0);
+ ~AndroidCreateKeystoreCertificate();
+ QString keystoreFilePath();
+ QString keystorePassword();
+ QString certificateAlias();
+ QString certificatePassword();
+
+private slots:
+ PasswordStatus checkKeystorePassword();
+ PasswordStatus checkCertificatePassword();
+ void on_keystoreShowPassCheckBox_stateChanged(int state);
+ void on_certificateShowPassCheckBox_stateChanged(int state);
+ void on_buttonBox_accepted();
+
+private:
+ Ui::AndroidCreateKeystoreCertificate *ui;
+ QString m_keystoreFilePath;
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDCREATEKEYSTORECERTIFICATE_H
diff --git a/src/plugins/android/androidcreatekeystorecertificate.ui b/src/plugins/android/androidcreatekeystorecertificate.ui
new file mode 100644
index 00000000000..9a0cb0a02d9
--- /dev/null
+++ b/src/plugins/android/androidcreatekeystorecertificate.ui
@@ -0,0 +1,362 @@
+
+
+ AndroidCreateKeystoreCertificate
+
+
+
+ 0
+ 0
+ 638
+ 429
+
+
+
+ Create a keystore and a cetificate
+
+
+ -
+
+
+ Keystore
+
+
+
-
+
+
+ Password:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ QLineEdit::Password
+
+
+
+ -
+
+
+ Retype password:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ QLineEdit::Password
+
+
+
+ -
+
+
+ Show password
+
+
+
+ -
+
+
+ <span style=" color:#ff0000;">Password is too short</span>
+
+
+ Qt::RichText
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+ -
+
+
+ Certificate
+
+
+
-
+
+
+ Alias name:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ Aaaaaaaa;
+
+
+ 8
+
+
+
+ -
+
+
+ Keysize:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ 2048
+
+
+ 2097152
+
+
+
+ -
+
+
+ Validity (days):
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ 10000
+
+
+ 100000
+
+
+
+ -
+
+
+ Password:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ QLineEdit::Password
+
+
+
+ -
+
+
+ Retype password:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ QLineEdit::Password
+
+
+
+ -
+
+
+ Show password
+
+
+
+ -
+
+
+ <span style=" color:#ff0000;">Password is too short</span>
+
+
+ Qt::RichText
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+ -
+
+
+ Certificate Distinguished Names
+
+
+
-
+
+
+ First and last name:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ -
+
+
+ Organizational unit (e.g. Necessitas):
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ -
+
+
+ Organization (e.g. KDE):
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ -
+
+
+ City or Locality:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ -
+
+
+ State or Province:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ -
+
+
+ Two-letter country code for this unit (e.g. RO):
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ >AA;
+
+
+ 2
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Close|QDialogButtonBox::Save
+
+
+
+
+
+
+ keystorePassLineEdit
+ keystoreRetypePassLineEdit
+ aliasNameLineEdit
+ keySizeSpinBox
+ validitySpinBox
+ certificatePassLineEdit
+ certificateRetypePassLineEdit
+ commonNameLineEdit
+ organizationUnitLineEdit
+ organizationNameLineEdit
+ localityNameLineEdit
+ stateNameLineEdit
+ countryLineEdit
+ keystoreShowPassCheckBox
+ certificateShowPassCheckBox
+ buttonBox
+
+
+
+
+ buttonBox
+ rejected()
+ AndroidCreateKeystoreCertificate
+ reject()
+
+
+ 320
+ 422
+
+
+ 286
+ 274
+
+
+
+
+ keystorePassLineEdit
+ editingFinished()
+ keystoreRetypePassLineEdit
+ setFocus()
+
+
+ 201
+ 48
+
+
+ 213
+ 75
+
+
+
+
+
diff --git a/src/plugins/android/androiddebugsupport.cpp b/src/plugins/android/androiddebugsupport.cpp
new file mode 100644
index 00000000000..a6a863c3d1c
--- /dev/null
+++ b/src/plugins/android/androiddebugsupport.cpp
@@ -0,0 +1,165 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androiddebugsupport.h"
+
+#include "androiddeploystep.h"
+#include "androidglobal.h"
+#include "androidrunner.h"
+#include "androidtarget.h"
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+using namespace Debugger;
+using namespace ProjectExplorer;
+using namespace Qt4ProjectManager;
+
+namespace Android {
+namespace Internal {
+
+static const char * const qMakeVariables[] = {
+ "QT_INSTALL_LIBS",
+ "QT_INSTALL_PLUGINS",
+ "QT_INSTALL_IMPORTS"
+};
+
+
+RunControl *AndroidDebugSupport::createDebugRunControl(AndroidRunConfiguration *runConfig)
+{
+ DebuggerStartParameters params;
+ params.toolChainAbi = runConfig->abi();
+ params.dumperLibrary = runConfig->dumperLib();
+ params.startMode = AttachToRemoteServer;
+ params.executable = runConfig->androidTarget()->qt4Project()->rootQt4ProjectNode()->buildDir() + QLatin1String("/app_process");
+ params.debuggerCommand = runConfig->gdbCmd();
+ params.remoteChannel = runConfig->remoteChannel();
+ params.displayName = runConfig->androidTarget()->packageName();
+
+ params.solibSearchPath.clear();
+
+ QList nodes = runConfig->androidTarget()->qt4Project()->allProFiles();
+ foreach (Qt4ProFileNode *node, nodes)
+ if (node->projectType() == ApplicationTemplate)
+ params.solibSearchPath.append(node->targetInformation().buildDir);
+
+ params.solibSearchPath.append(qtSoPaths(runConfig->activeQt4BuildConfiguration()->qtVersion()));
+
+ params.useServerStartScript = true;
+ params.requestRemoteSetup = true;
+ params.remoteArchitecture = QLatin1String("arm");
+
+ DebuggerRunControl * const debuggerRunControl
+ = DebuggerPlugin::createDebugger(params, runConfig);
+ new AndroidDebugSupport(runConfig, debuggerRunControl);
+ return debuggerRunControl;
+}
+
+AndroidDebugSupport::AndroidDebugSupport(AndroidRunConfiguration *runConfig,
+ DebuggerRunControl *runControl)
+ : QObject(runControl), m_runControl(runControl),
+ m_runner(new AndroidRunner(this, runConfig, true)),
+ m_debuggingType(runConfig->debuggingType()),
+ m_gdbServerPort(5039), m_qmlPort(-1)
+{
+ connect(m_runControl->engine(), SIGNAL(requestRemoteSetup()),
+ m_runner, SLOT(start()));
+ connect(m_runControl, SIGNAL(finished()),
+ m_runner, SLOT(stop()));
+
+ connect(m_runner, SIGNAL(remoteProcessStarted(int,int)),
+ SLOT(handleRemoteProcessStarted(int,int)));
+ connect(m_runner, SIGNAL(remoteProcessFinished(const QString &)),
+ SLOT(handleRemoteProcessFinished(const QString &)));
+
+ connect(m_runner, SIGNAL(remoteErrorOutput(QByteArray)),
+ SLOT(handleRemoteErrorOutput(QByteArray)));
+ connect(m_runner, SIGNAL(remoteOutput(QByteArray)),
+ SLOT(handleRemoteOutput(QByteArray)));
+}
+
+AndroidDebugSupport::~AndroidDebugSupport()
+{
+}
+
+void AndroidDebugSupport::handleRemoteProcessStarted(int gdbServerPort, int qmlPort)
+{
+ disconnect(m_runner, SIGNAL(remoteProcessStarted(int,int)),
+ this, SLOT(handleRemoteProcessStarted(int,int)));
+ m_runControl->engine()->handleRemoteSetupDone(gdbServerPort, qmlPort);
+}
+
+void AndroidDebugSupport::handleRemoteProcessFinished(const QString &errorMsg)
+{
+ disconnect(m_runner, SIGNAL(remoteProcessFinished(const QString &)),
+ this,SLOT(handleRemoteProcessFinished(const QString &)));
+ m_runControl->engine()->handleRemoteSetupFailed(errorMsg);
+}
+
+void AndroidDebugSupport::handleRemoteOutput(const QByteArray &output)
+{
+ if (m_runControl)
+ m_runControl->showMessage(QString::fromUtf8(output), AppOutput);
+}
+
+void AndroidDebugSupport::handleRemoteErrorOutput(const QByteArray &output)
+{
+ if (m_runControl)
+ m_runControl->showMessage(QString::fromUtf8(output), AppError);
+}
+
+QStringList AndroidDebugSupport::qtSoPaths(QtSupport::BaseQtVersion *qtVersion)
+{
+ QSet paths;
+ for (uint i = 0; i < sizeof qMakeVariables / sizeof qMakeVariables[0]; ++i) {
+ if (!qtVersion->versionInfo().contains(QLatin1String(qMakeVariables[i])))
+ continue;
+ QDirIterator it(qtVersion->versionInfo()[QLatin1String(qMakeVariables[i])], QStringList() << QLatin1String("*.so"), QDir::Files, QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ it.next();
+ paths.insert(it.fileInfo().absolutePath());
+ }
+ }
+ return paths.toList();
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/android/androiddebugsupport.h b/src/plugins/android/androiddebugsupport.h
new file mode 100644
index 00000000000..d9cdfae34f9
--- /dev/null
+++ b/src/plugins/android/androiddebugsupport.h
@@ -0,0 +1,87 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDDEBUGSUPPORT_H
+#define ANDROIDDEBUGSUPPORT_H
+
+#include "androidrunconfiguration.h"
+
+#include
+#include
+
+namespace Debugger {
+class DebuggerRunControl;
+}
+namespace QtSupport {class BaseQtVersion; }
+namespace ProjectExplorer { class RunControl; }
+
+namespace Android {
+
+namespace Internal {
+
+class AndroidRunConfiguration;
+class AndroidRunner;
+
+class AndroidDebugSupport : public QObject
+{
+ Q_OBJECT
+public:
+ static ProjectExplorer::RunControl *createDebugRunControl(AndroidRunConfiguration *runConfig);
+
+ AndroidDebugSupport(AndroidRunConfiguration *runConfig,
+ Debugger::DebuggerRunControl *runControl);
+ ~AndroidDebugSupport();
+
+private slots:
+ void handleRemoteProcessStarted(int gdbServerPort = -1, int qmlPort = -1);
+ void handleRemoteProcessFinished(const QString &errorMsg);
+
+ void handleRemoteOutput(const QByteArray &output);
+ void handleRemoteErrorOutput(const QByteArray &output);
+
+private:
+ static QStringList qtSoPaths(QtSupport::BaseQtVersion *qtVersion);
+
+private:
+ Debugger::DebuggerRunControl* m_runControl;
+ AndroidRunner * const m_runner;
+ const AndroidRunConfiguration::DebuggingType m_debuggingType;
+ const QString m_dumperLib;
+
+ int m_gdbServerPort;
+ int m_qmlPort;
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDDEBUGSUPPORT_H
diff --git a/src/plugins/android/androiddeployconfiguration.cpp b/src/plugins/android/androiddeployconfiguration.cpp
new file mode 100644
index 00000000000..78c3f1ee5a8
--- /dev/null
+++ b/src/plugins/android/androiddeployconfiguration.cpp
@@ -0,0 +1,135 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androiddeploystep.h"
+#include "androidpackageinstallationstep.h"
+#include "androidpackagecreationstep.h"
+#include "androiddeployconfiguration.h"
+#include "androidtarget.h"
+
+#include
+#include
+
+#include
+#include
+
+using namespace Android::Internal;
+
+AndroidDeployConfiguration::AndroidDeployConfiguration(ProjectExplorer::Target *parent)
+ :DeployConfiguration(parent, QLatin1String(ANDROID_DEPLOYCONFIGURATION_ID))
+{
+ setDisplayName(tr("Deploy to Android device"));
+ setDefaultDisplayName(displayName());
+}
+
+AndroidDeployConfiguration::~AndroidDeployConfiguration()
+{
+
+}
+
+AndroidDeployConfiguration::AndroidDeployConfiguration(ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *source)
+ :DeployConfiguration(parent, source)
+{
+
+}
+
+AndroidDeployConfigurationFactory::AndroidDeployConfigurationFactory(QObject *parent) :
+ ProjectExplorer::DeployConfigurationFactory(parent)
+{ }
+
+bool AndroidDeployConfigurationFactory::canCreate(ProjectExplorer::Target *parent, const QString &id) const
+{
+ AndroidTarget *t = qobject_cast(parent);
+ if (!t || t->id() != QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID)
+ || !id.startsWith(QLatin1String(ANDROID_DEPLOYCONFIGURATION_ID)))
+ return false;
+ return true;
+}
+
+ProjectExplorer::DeployConfiguration *AndroidDeployConfigurationFactory::create(ProjectExplorer::Target *parent, const QString &/*id*/)
+{
+ AndroidDeployConfiguration *dc = new AndroidDeployConfiguration(parent);
+ 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()));
+ return dc;
+}
+
+bool AndroidDeployConfigurationFactory::canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const
+{
+ return canCreate(parent, ProjectExplorer::idFromMap(map));
+}
+
+ProjectExplorer::DeployConfiguration *AndroidDeployConfigurationFactory::restore(ProjectExplorer::Target *parent, const QVariantMap &map)
+{
+ if (!canRestore(parent, map))
+ return 0;
+ AndroidTarget *t = static_cast(parent);
+ AndroidDeployConfiguration *dc = new AndroidDeployConfiguration(t);
+ if (dc->fromMap(map))
+ return dc;
+
+ delete dc;
+ return 0;
+}
+
+bool AndroidDeployConfigurationFactory::canClone(ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *source) const
+{
+ if (!qobject_cast(parent))
+ return false;
+ return source->id() == QLatin1String(ANDROID_DEPLOYCONFIGURATION_ID);
+}
+
+ProjectExplorer::DeployConfiguration *AndroidDeployConfigurationFactory::clone(ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *source)
+{
+ if (!canClone(parent, source))
+ return 0;
+ AndroidTarget *t = static_cast(parent);
+ return new AndroidDeployConfiguration(t, source);
+}
+
+QStringList AndroidDeployConfigurationFactory::availableCreationIds(ProjectExplorer::Target *parent) const
+{
+ AndroidTarget *target = qobject_cast(parent);
+ if (!target ||
+ target->id() != QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID))
+ return QStringList();
+
+ return target->qt4Project()->applicationProFilePathes(QLatin1String(ANDROID_DC_PREFIX));
+}
+
+QString AndroidDeployConfigurationFactory::displayNameForId(const QString &/*id*/) const
+{
+ return tr("Deploy on Android");
+}
diff --git a/src/plugins/android/androiddeployconfiguration.h b/src/plugins/android/androiddeployconfiguration.h
new file mode 100644
index 00000000000..e6550e421f4
--- /dev/null
+++ b/src/plugins/android/androiddeployconfiguration.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef QT4PROJECTMANAGER_QT4ANDROIDDEPLOYCONFIGURATION_H
+#define QT4PROJECTMANAGER_QT4ANDROIDDEPLOYCONFIGURATION_H
+
+#include
+
+namespace Android {
+namespace Internal {
+
+class Target;
+const char ANDROID_DEPLOYCONFIGURATION_ID[] = "Qt4ProjectManager.AndroidDeployConfiguration";
+const char ANDROID_DC_PREFIX[] = "Qt4ProjectManager.AndroidDeployConfiguration.";
+
+class AndroidDeployConfiguration : public ProjectExplorer::DeployConfiguration
+{
+ Q_OBJECT
+ friend class AndroidDeployConfigurationFactory;
+
+public:
+ AndroidDeployConfiguration(ProjectExplorer::Target *parent);
+ virtual ~AndroidDeployConfiguration();
+protected:
+ AndroidDeployConfiguration(ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *source);
+
+};
+
+class AndroidDeployConfigurationFactory : public ProjectExplorer::DeployConfigurationFactory
+{
+ Q_OBJECT
+
+public:
+ explicit AndroidDeployConfigurationFactory(QObject *parent = 0);
+
+ bool canCreate(ProjectExplorer::Target *parent, const QString &id) const;
+ ProjectExplorer::DeployConfiguration *create(ProjectExplorer::Target *parent, const QString &id);
+ bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const;
+ ProjectExplorer::DeployConfiguration *restore(ProjectExplorer::Target *parent, const QVariantMap &map);
+ bool canClone(ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *source) const;
+ ProjectExplorer::DeployConfiguration *clone(ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *source);
+
+ QStringList availableCreationIds(ProjectExplorer::Target *parent) const;
+ // used to translate the ids to names to display to the user
+ QString displayNameForId(const QString &id) const;
+
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // QT4PROJECTMANAGER_QT4ANDROIDDEPLOYCONFIGURATION_H
diff --git a/src/plugins/android/androiddeploystep.cpp b/src/plugins/android/androiddeploystep.cpp
new file mode 100644
index 00000000000..64c024add3c
--- /dev/null
+++ b/src/plugins/android/androiddeploystep.cpp
@@ -0,0 +1,324 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androiddeploystep.h"
+
+#include "androidconstants.h"
+#include "androiddeploystepwidget.h"
+#include "androidglobal.h"
+#include "androidpackagecreationstep.h"
+#include "androidrunconfiguration.h"
+#include "androidtarget.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
+
+using namespace ProjectExplorer;
+using namespace Qt4ProjectManager;
+
+namespace Android {
+namespace Internal {
+
+const QLatin1String AndroidDeployStep::Id("Qt4ProjectManager.AndroidDeployStep");
+
+AndroidDeployStep::AndroidDeployStep(ProjectExplorer::BuildStepList *parent)
+ : BuildStep(parent, Id)
+{
+ ctor();
+}
+
+AndroidDeployStep::AndroidDeployStep(ProjectExplorer::BuildStepList *parent,
+ AndroidDeployStep *other)
+ : BuildStep(parent, other)
+{
+ ctor();
+}
+
+AndroidDeployStep::~AndroidDeployStep() { }
+
+void AndroidDeployStep::ctor()
+{
+ //: AndroidDeployStep default display name
+ setDefaultDisplayName(tr("Deploy to Android device"));
+ m_deployAction = NoDeploy;
+ m_useLocalQtLibs = false;
+}
+
+bool AndroidDeployStep::init()
+{
+ AndroidTarget *androidTarget = qobject_cast(target());
+ if (!androidTarget) {
+ raiseError(tr("Cannot deploy: current target is not android."));
+ return false;
+ }
+ const Qt4BuildConfiguration *const bc = androidTarget->activeQt4BuildConfiguration();
+ m_packageName = androidTarget->packageName();
+ const QString targetSDK = androidTarget->targetSDK();
+
+ writeOutput(tr("Please wait, searching for a suitable device for target:%1.").arg(targetSDK));
+ m_deviceAPILevel = targetSDK.mid(targetSDK.indexOf(QLatin1Char('-')) + 1).toInt();
+ m_deviceSerialNumber = AndroidConfigurations::instance().getDeployDeviceSerialNumber(&m_deviceAPILevel);
+ if (!m_deviceSerialNumber.length()) {
+ m_deviceSerialNumber.clear();
+ raiseError(tr("Cannot deploy: no devices or emulators found for your package."));
+ return false;
+ }
+
+ if (!bc->qtVersion())
+ return false;
+ m_qtVersionSourcePath = bc->qtVersion()->sourcePath().toString();
+ m_qtVersionQMakeBuildConfig = bc->qtVersion()->defaultBuildConfig();
+ m_androidDirPath = androidTarget->androidDirPath();
+ m_apkPathDebug = androidTarget->apkPath(AndroidTarget::DebugBuild);
+ m_apkPathRelease = androidTarget->apkPath(AndroidTarget::ReleaseBuildSigned);
+ m_buildDirectory = androidTarget->qt4Project()->rootQt4ProjectNode()->buildDir();
+ m_runQASIPackagePath = m_QASIPackagePath;
+ m_runDeployAction = m_deployAction;
+ return true;
+}
+
+void AndroidDeployStep::run(QFutureInterface &fi)
+{
+ fi.reportResult(deployPackage());
+}
+
+BuildStepConfigWidget *AndroidDeployStep::createConfigWidget()
+{
+ return new AndroidDeployStepWidget(this);
+}
+
+AndroidDeployStep::AndroidDeployAction AndroidDeployStep::deployAction()
+{
+ return m_deployAction;
+}
+
+bool AndroidDeployStep::useLocalQtLibs()
+{
+ return m_useLocalQtLibs;
+}
+
+void AndroidDeployStep::setDeployAction(AndroidDeployStep::AndroidDeployAction deploy)
+{
+ m_deployAction = deploy;
+}
+
+void AndroidDeployStep::setDeployQASIPackagePath(const QString &package)
+{
+ m_QASIPackagePath = package;
+ m_deployAction = InstallQASI;
+}
+
+void AndroidDeployStep::setUseLocalQtLibs(bool useLocal)
+{
+ m_useLocalQtLibs = useLocal;
+}
+
+bool AndroidDeployStep::runCommand(QProcess *buildProc,
+ const QString &program, const QStringList &arguments)
+{
+ writeOutput(tr("Package deploy: Running command '%1 %2'.").arg(program).arg(arguments.join(QLatin1String(" "))), BuildStep::MessageOutput);
+ buildProc->start(program, arguments);
+ if (!buildProc->waitForStarted()) {
+ writeOutput(tr("Packaging error: Could not start command '%1 %2'. Reason: %3")
+ .arg(program).arg(arguments.join(QLatin1String(" "))).arg(buildProc->errorString()), BuildStep::ErrorMessageOutput);
+ return false;
+ }
+ buildProc->waitForFinished(-1);
+ if (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());
+ writeOutput(mainMessage, BuildStep::ErrorMessageOutput);
+ return false;
+ }
+ return true;
+}
+
+void AndroidDeployStep::handleBuildOutput()
+{
+ QProcess *const buildProc = qobject_cast(sender());
+ if (!buildProc)
+ return;
+ emit addOutput(QString::fromLocal8Bit(buildProc->readAllStandardOutput())
+ , BuildStep::NormalOutput);
+}
+
+void AndroidDeployStep::handleBuildError()
+{
+ QProcess *const buildProc = qobject_cast(sender());
+ if (!buildProc)
+ return;
+ emit addOutput(QString::fromLocal8Bit(buildProc->readAllStandardError())
+ , BuildStep::ErrorOutput);
+}
+
+QString AndroidDeployStep::deviceSerialNumber()
+{
+ return m_deviceSerialNumber;
+}
+
+int AndroidDeployStep::deviceAPILevel()
+{
+ return m_deviceAPILevel;
+}
+
+QString AndroidDeployStep::localLibsRulesFilePath()
+{
+ AndroidTarget *androidTarget = qobject_cast(target());
+ if (!androidTarget)
+ return QString();
+ return androidTarget->localLibsRulesFilePath();
+}
+
+void AndroidDeployStep::copyLibs(const QString &srcPath, const QString &destPath, QStringList &copiedLibs, const QStringList &filter)
+{
+ QDir dir;
+ dir.mkpath(destPath);
+ QDirIterator libsIt(srcPath, filter, QDir::NoFilter, QDirIterator::Subdirectories);
+ int pos = srcPath.size();
+ while (libsIt.hasNext()) {
+ libsIt.next();
+ const QString destFile(destPath + libsIt.filePath().mid(pos));
+ if (libsIt.fileInfo().isDir()) {
+ dir.mkpath(destFile);
+ } else {
+ QFile::copy(libsIt.filePath(), destFile);
+ copiedLibs.append(destFile);
+ }
+ }
+}
+
+bool AndroidDeployStep::deployPackage()
+{
+ QProcess *const deployProc = new QProcess;
+ connect(deployProc, SIGNAL(readyReadStandardOutput()), this,
+ SLOT(handleBuildOutput()));
+ connect(deployProc, SIGNAL(readyReadStandardError()), this,
+ SLOT(handleBuildError()));
+
+ if (m_runDeployAction == DeployLocal) {
+ writeOutput(tr("Clean old qt libs"));
+ runCommand(deployProc, AndroidConfigurations::instance().adbToolPath(),
+ QStringList() << QLatin1String("-s") << m_deviceSerialNumber
+ << QLatin1String("shell") << QLatin1String("rm") << QLatin1String("-r") << QLatin1String("/data/local/qt"));
+
+ writeOutput(tr("Deploy qt libs ... this may take some time, please wait"));
+ const QString tempPath = QDir::tempPath() + QLatin1String("/android_qt_libs_") + m_packageName;
+ AndroidPackageCreationStep::removeDirectory(tempPath);
+ QStringList stripFiles;
+ copyLibs(m_qtVersionSourcePath + QLatin1String("/lib"),
+ tempPath + QLatin1String("/lib"), stripFiles, QStringList() << QLatin1String("*.so"));
+ copyLibs(m_qtVersionSourcePath + QLatin1String("/plugins"),
+ tempPath + QLatin1String("/plugins"), stripFiles);
+ copyLibs(m_qtVersionSourcePath + QLatin1String("/imports"),
+ tempPath + QLatin1String("/imports"), stripFiles);
+ copyLibs(m_qtVersionSourcePath + QLatin1String("/jar"),
+ tempPath + QLatin1String("/jar"), stripFiles);
+ AndroidPackageCreationStep::stripAndroidLibs(stripFiles, target()->activeRunConfiguration()->abi().architecture());
+ runCommand(deployProc, AndroidConfigurations::instance().adbToolPath(),
+ QStringList() << QLatin1String("-s") << m_deviceSerialNumber
+ << QLatin1String("push") << tempPath << QLatin1String("/data/local/qt"));
+ AndroidPackageCreationStep::removeDirectory(tempPath);
+ emit (resetDelopyAction());
+ }
+
+ if (m_runDeployAction == InstallQASI) {
+ if (!runCommand(deployProc, AndroidConfigurations::instance().adbToolPath(),
+ QStringList() << QLatin1String("-s") << m_deviceSerialNumber
+ << QLatin1String("install") << QLatin1String("-r ") << m_runQASIPackagePath)) {
+ raiseError(tr("Qt Android smart installer instalation failed"));
+ disconnect(deployProc, 0, this, 0);
+ deployProc->deleteLater();
+ return false;
+ }
+ emit resetDelopyAction();
+ }
+ deployProc->setWorkingDirectory(m_androidDirPath);
+
+ writeOutput(tr("Installing package onto %1.").arg(m_deviceSerialNumber));
+ runCommand(deployProc, AndroidConfigurations::instance().adbToolPath(),
+ QStringList() << QLatin1String("-s") << m_deviceSerialNumber << QLatin1String("uninstall") << m_packageName);
+ QString package = m_apkPathDebug;
+
+ if (!(m_qtVersionQMakeBuildConfig & QtSupport::BaseQtVersion::DebugBuild)
+ && QFile::exists(m_apkPathRelease))
+ package = m_apkPathRelease;
+
+ if (!runCommand(deployProc, AndroidConfigurations::instance().adbToolPath(),
+ QStringList() << QLatin1String("-s") << m_deviceSerialNumber << QLatin1String("install") << package)) {
+ raiseError(tr("Package instalation failed"));
+ disconnect(deployProc, 0, this, 0);
+ deployProc->deleteLater();
+ return false;
+ }
+
+ writeOutput(tr("Pulling files necessary for debugging"));
+ runCommand(deployProc, AndroidConfigurations::instance().adbToolPath(),
+ QStringList() << QLatin1String("-s") << m_deviceSerialNumber
+ << QLatin1String("pull") << QLatin1String("/system/bin/app_process")
+ << QString::fromLatin1("%1/app_process").arg(m_buildDirectory));
+ runCommand(deployProc, AndroidConfigurations::instance().adbToolPath(),
+ QStringList() << QLatin1String("-s") << m_deviceSerialNumber << QLatin1String("pull")
+ << QLatin1String("/system/lib/libc.so")
+ << QString::fromLatin1("%1/libc.so").arg(m_buildDirectory));
+ disconnect(deployProc, 0, this, 0);
+ deployProc->deleteLater();
+ return true;
+}
+
+void AndroidDeployStep::raiseError(const QString &errorString)
+{
+ emit addTask(Task(Task::Error, errorString, Utils::FileName::fromString(QString()), -1,
+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
+}
+
+void AndroidDeployStep::writeOutput(const QString &text, OutputFormat format)
+{
+ emit addOutput(text, format);
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/android/androiddeploystep.h b/src/plugins/android/androiddeploystep.h
new file mode 100644
index 00000000000..a7627e927b0
--- /dev/null
+++ b/src/plugins/android/androiddeploystep.h
@@ -0,0 +1,132 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDDEPLOYSTEP_H
+#define ANDROIDDEPLOYSTEP_H
+
+#include "androidconfigurations.h"
+
+#include
+#include
+
+#include
+
+QT_BEGIN_NAMESPACE
+class QEventLoop;
+class QTimer;
+QT_END_NAMESPACE
+
+namespace Android {
+namespace Internal {
+class AndroidDeviceConfigListModel;
+class AndroidPackageCreationStep;
+
+class AndroidDeployStep : public ProjectExplorer::BuildStep
+{
+ Q_OBJECT
+ friend class AndroidDeployStepFactory;
+
+public:
+ enum AndroidDeployAction
+ {
+ NoDeploy,
+ DeployLocal,
+ InstallQASI
+ };
+
+public:
+ AndroidDeployStep(ProjectExplorer::BuildStepList *bc);
+
+ virtual ~AndroidDeployStep();
+
+ QString deviceSerialNumber();
+ int deviceAPILevel();
+ QString localLibsRulesFilePath();
+
+ AndroidDeployAction deployAction();
+ bool useLocalQtLibs();
+
+public slots:
+ void setDeployAction(AndroidDeployAction deploy);
+ void setDeployQASIPackagePath(const QString &package);
+ void setUseLocalQtLibs(bool useLocal);
+
+signals:
+ void done();
+ void error();
+ void resetDelopyAction();
+
+private slots:
+ bool deployPackage();
+ void handleBuildOutput();
+ void handleBuildError();
+
+private:
+ AndroidDeployStep(ProjectExplorer::BuildStepList *bc,
+ AndroidDeployStep *other);
+ virtual bool init();
+ virtual void run(QFutureInterface &fi);
+ virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
+ virtual bool immutable() const { return true; }
+
+ void copyLibs(const QString &srcPath, const QString &destPath, QStringList &copiedLibs, const QStringList &filter = QStringList());
+ void ctor();
+ void raiseError(const QString &error);
+ void writeOutput(const QString &text, OutputFormat = MessageOutput);
+ bool runCommand(QProcess *buildProc, const QString &program, const QStringList &arguments);
+
+private:
+ QString m_deviceSerialNumber;
+ int m_deviceAPILevel;
+
+ QString m_QASIPackagePath;
+ AndroidDeployAction m_deployAction;
+ bool m_useLocalQtLibs;
+
+ // members to transfer data from init() to run
+ QString m_packageName;
+ QString m_qtVersionSourcePath;
+ QtSupport::BaseQtVersion::QmakeBuildConfigs m_qtVersionQMakeBuildConfig;
+ QString m_androidDirPath;
+ QString m_apkPathDebug;
+ QString m_apkPathRelease;
+ QString m_buildDirectory;
+ QString m_runQASIPackagePath;
+ AndroidDeployAction m_runDeployAction;
+
+ static const QLatin1String Id;
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDDEPLOYSTEP_H
diff --git a/src/plugins/android/androiddeploystepfactory.cpp b/src/plugins/android/androiddeploystepfactory.cpp
new file mode 100644
index 00000000000..289b4f18b19
--- /dev/null
+++ b/src/plugins/android/androiddeploystepfactory.cpp
@@ -0,0 +1,113 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androiddeploystepfactory.h"
+
+#include "androiddeploystep.h"
+
+#include
+#include
+#include
+#include
+
+#include
+
+using namespace ProjectExplorer;
+
+namespace Android {
+namespace Internal {
+
+AndroidDeployStepFactory::AndroidDeployStepFactory(QObject *parent)
+ : IBuildStepFactory(parent)
+{
+}
+
+QStringList AndroidDeployStepFactory::availableCreationIds(BuildStepList *parent) const
+{
+ if (parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
+ && parent->target()->id() == QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID)
+ && !parent->contains(AndroidDeployStep::Id))
+ return QStringList() << AndroidDeployStep::Id;
+ return QStringList();
+}
+
+QString AndroidDeployStepFactory::displayNameForId(const QString &id) const
+{
+ if (id == AndroidDeployStep::Id)
+ return QCoreApplication::translate("Qt4ProjectManager::Internal::AndroidDeployStepFactory",
+ "Deploy to Android device/emulator");
+ return QString();
+}
+
+bool AndroidDeployStepFactory::canCreate(BuildStepList *parent, const QString &id) const
+{
+ return parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
+ && id == QLatin1String(AndroidDeployStep::Id)
+ && parent->target()->id() == QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID)
+ && !parent->contains(AndroidDeployStep::Id);
+}
+
+BuildStep *AndroidDeployStepFactory::create(BuildStepList *parent, const QString &id)
+{
+ Q_ASSERT(canCreate(parent, id));
+ return new AndroidDeployStep(parent);
+}
+
+bool AndroidDeployStepFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const
+{
+ return canCreate(parent, idFromMap(map));
+}
+
+BuildStep *AndroidDeployStepFactory::restore(BuildStepList *parent, const QVariantMap &map)
+{
+ Q_ASSERT(canRestore(parent, map));
+ AndroidDeployStep * const step = new AndroidDeployStep(parent);
+ if (!step->fromMap(map)) {
+ delete step;
+ return 0;
+ }
+ return step;
+}
+
+bool AndroidDeployStepFactory::canClone(BuildStepList *parent, BuildStep *product) const
+{
+ return canCreate(parent, product->id());
+}
+
+BuildStep *AndroidDeployStepFactory::clone(BuildStepList *parent, BuildStep *product)
+{
+ Q_ASSERT(canClone(parent, product));
+ return new AndroidDeployStep(parent, static_cast(product));
+}
+
+} // namespace Internal
+} // namespace Android
diff --git a/src/plugins/android/androiddeploystepfactory.h b/src/plugins/android/androiddeploystepfactory.h
new file mode 100644
index 00000000000..c2361acb3f7
--- /dev/null
+++ b/src/plugins/android/androiddeploystepfactory.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDDEPLOYSTEPFACTORY_H
+#define ANDROIDDEPLOYSTEPFACTORY_H
+
+#include
+
+namespace Android {
+namespace Internal {
+
+class AndroidDeployStepFactory : public ProjectExplorer::IBuildStepFactory
+{
+ Q_OBJECT
+public:
+ explicit AndroidDeployStepFactory(QObject *parent = 0);
+
+ virtual QStringList availableCreationIds(ProjectExplorer::BuildStepList *parent) const;
+ virtual QString displayNameForId(const QString &id) const;
+
+ virtual bool canCreate(ProjectExplorer::BuildStepList *parent,
+ const QString &id) const;
+ virtual ProjectExplorer::BuildStep *
+ create(ProjectExplorer::BuildStepList *parent, const QString &id);
+
+ virtual bool canRestore(ProjectExplorer::BuildStepList *parent,
+ const QVariantMap &map) const;
+ virtual ProjectExplorer::BuildStep *
+ restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map);
+
+ virtual bool canClone(ProjectExplorer::BuildStepList *parent,
+ ProjectExplorer::BuildStep *product) const;
+ virtual ProjectExplorer::BuildStep *
+ clone(ProjectExplorer::BuildStepList *parent,
+ ProjectExplorer::BuildStep *product);
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDDEPLOYSTEPFACTORY_H
diff --git a/src/plugins/android/androiddeploystepwidget.cpp b/src/plugins/android/androiddeploystepwidget.cpp
new file mode 100644
index 00000000000..3eafae6e540
--- /dev/null
+++ b/src/plugins/android/androiddeploystepwidget.cpp
@@ -0,0 +1,115 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androiddeploystepwidget.h"
+#include "ui_androiddeploystepwidget.h"
+
+#include "androiddeploystep.h"
+#include "androidrunconfiguration.h"
+
+#include
+
+#include
+
+namespace Android {
+namespace Internal {
+
+AndroidDeployStepWidget::AndroidDeployStepWidget(AndroidDeployStep *step) :
+ ProjectExplorer::BuildStepConfigWidget(),
+ ui(new Ui::AndroidDeployStepWidget),
+ m_step(step)
+{
+ ui->setupUi(this);
+
+ ui->useLocalQtLibs->setChecked(m_step->useLocalQtLibs());
+ switch (m_step->deployAction()) {
+ case AndroidDeployStep::DeployLocal:
+ ui->deployQtLibs->setChecked(true);
+ break;
+ default:
+ ui->devicesQtLibs->setChecked(true);
+ break;
+ }
+
+ connect(m_step, SIGNAL(resetDelopyAction()), SLOT(resetAction()));
+ connect(ui->devicesQtLibs, SIGNAL(clicked()), SLOT(resetAction()));
+ connect(ui->deployQtLibs, SIGNAL(clicked()), SLOT(setDeployLocalQtLibs()));
+ connect(ui->chooseButton, SIGNAL(clicked()), SLOT(setQASIPackagePath()));
+ connect(ui->useLocalQtLibs, SIGNAL(stateChanged(int)), SLOT(useLocalQtLibsStateChanged(int)));
+ connect(ui->editRulesFilePushButton, SIGNAL(clicked()), SLOT(editRulesFile()));
+}
+
+AndroidDeployStepWidget::~AndroidDeployStepWidget()
+{
+ delete ui;
+}
+
+QString AndroidDeployStepWidget::displayName() const
+{
+ return tr("Deploy configurations");
+}
+
+QString AndroidDeployStepWidget::summaryText() const
+{
+ return displayName();
+}
+
+void AndroidDeployStepWidget::resetAction()
+{
+ ui->devicesQtLibs->setChecked(true);
+ m_step->setDeployAction(AndroidDeployStep::NoDeploy);
+}
+
+void AndroidDeployStepWidget::setDeployLocalQtLibs()
+{
+ m_step->setDeployAction(AndroidDeployStep::DeployLocal);
+}
+
+void AndroidDeployStepWidget::setQASIPackagePath()
+{
+ QString packagePath = QFileDialog::getOpenFileName(this, tr("Qt Android smart installer"), QDir::homePath(), tr("Android package (*.apk)"));
+ if (packagePath.length())
+ m_step->setDeployQASIPackagePath(packagePath);
+}
+
+void AndroidDeployStepWidget::useLocalQtLibsStateChanged(int state)
+{
+ m_step->setUseLocalQtLibs(state == Qt::Checked);
+}
+
+void AndroidDeployStepWidget::editRulesFile()
+{
+ Core::ICore::instance()->openFiles(QStringList() << m_step->localLibsRulesFilePath(), Core::ICore::SwitchMode);
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/android/androiddeploystepwidget.h b/src/plugins/android/androiddeploystepwidget.h
new file mode 100644
index 00000000000..3623662b75f
--- /dev/null
+++ b/src/plugins/android/androiddeploystepwidget.h
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDDEPLOYSTEPWIDGET_H
+#define ANDROIDDEPLOYSTEPWIDGET_H
+
+#include
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class AndroidDeployStepWidget;
+}
+QT_END_NAMESPACE
+
+namespace Android {
+namespace Internal {
+class AndroidDeployStep;
+
+class AndroidDeployStepWidget : public ProjectExplorer::BuildStepConfigWidget
+{
+ Q_OBJECT
+
+public:
+ AndroidDeployStepWidget(AndroidDeployStep *step);
+ ~AndroidDeployStepWidget();
+
+private slots:
+ void resetAction();
+ void setDeployLocalQtLibs();
+ void setQASIPackagePath();
+ void useLocalQtLibsStateChanged(int);
+ void editRulesFile();
+
+private:
+ virtual QString summaryText() const;
+ virtual QString displayName() const;
+
+ Ui::AndroidDeployStepWidget *ui;
+ AndroidDeployStep *m_step;
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDDEPLOYSTEPWIDGET_H
diff --git a/src/plugins/android/androiddeploystepwidget.ui b/src/plugins/android/androiddeploystepwidget.ui
new file mode 100644
index 00000000000..5a348df0d6e
--- /dev/null
+++ b/src/plugins/android/androiddeploystepwidget.ui
@@ -0,0 +1,156 @@
+
+
+ AndroidDeployStepWidget
+
+
+
+ 0
+ 0
+ 560
+ 136
+
+
+
+
+ 0
+ 0
+
+
+
+ Form
+
+
+ -
+
+
+ Use devices qt libs
+
+
+ Use devices qt libs
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ Push local qt libs to device.
+You must have Qt libs compiled for that platform
+
+
+ Deploy local qt libs
+
+
+
+ -
+
+
+ Check this option to force the application to use local qt libs instead of system libs.
+
+
+ Use local qt libs
+
+
+
+ -
+
+
+ Edit rules file
+
+
+
+
+
+ -
+
+
-
+
+
+ Choose and install Ministro system wide qt shared libraries.
+This option is useful when you want to try your application on devices which don't have Android Market (e.g. Android Emulator).
+
+
+ Install Ministro system wide qt shared libraries installer
+
+
+
+ -
+
+
+ false
+
+
+ Choose apk
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 41
+
+
+
+
+
+
+
+
+
+ installQASI
+ toggled(bool)
+ chooseButton
+ setEnabled(bool)
+
+
+ 119
+ 68
+
+
+ 272
+ 64
+
+
+
+
+ deployQtLibs
+ clicked(bool)
+ useLocalQtLibs
+ setChecked(bool)
+
+
+ 138
+ 43
+
+
+ 343
+ 44
+
+
+
+
+
diff --git a/src/plugins/android/androidglobal.h b/src/plugins/android/androidglobal.h
new file mode 100644
index 00000000000..836546d91d5
--- /dev/null
+++ b/src/plugins/android/androidglobal.h
@@ -0,0 +1,87 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDGLOBAL_H
+#define ANDROIDGLOBAL_H
+
+#include
+
+#include
+#include
+
+#define ASSERT_STATE_GENERIC(State, expected, actual) \
+ AndroidGlobal::assertState(expected, actual, Q_FUNC_INFO)
+
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
+
+namespace Android {
+namespace Internal {
+
+class AndroidGlobal
+{
+public:
+
+ template static T *buildStep(const ProjectExplorer::DeployConfiguration *dc)
+ {
+ ProjectExplorer::BuildStepList *bsl = dc->stepList();
+ if (!bsl)
+ return 0;
+ const QList &buildSteps = bsl->steps();
+ for (int i = buildSteps.count() - 1; i >= 0; --i) {
+ if (T * const step = qobject_cast(buildSteps.at(i)))
+ return step;
+ }
+ return 0;
+ }
+
+ template static void assertState(State expected,
+ State actual, const char *func)
+ {
+ assertState(QList() << expected, actual, func);
+ }
+
+ template static void assertState(const QList &expected,
+ State actual, const char *func)
+ {
+ if (!expected.contains(actual)) {
+ qWarning("Warning: Unexpected state %d in function %s.",
+ actual, func);
+ }
+ }
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDGLOBAL_H
diff --git a/src/plugins/android/androidpackagecreationfactory.cpp b/src/plugins/android/androidpackagecreationfactory.cpp
new file mode 100644
index 00000000000..b33c16c012d
--- /dev/null
+++ b/src/plugins/android/androidpackagecreationfactory.cpp
@@ -0,0 +1,119 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidpackagecreationfactory.h"
+
+#include "androidpackagecreationstep.h"
+
+#include
+#include
+#include
+#include
+
+#include
+
+using ProjectExplorer::BuildStepList;
+using ProjectExplorer::BuildStep;
+
+namespace Android {
+namespace Internal {
+
+AndroidPackageCreationFactory::AndroidPackageCreationFactory(QObject *parent)
+ : ProjectExplorer::IBuildStepFactory(parent)
+{
+}
+
+QStringList AndroidPackageCreationFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
+{
+ if (parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
+ && parent->target()->id() == QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID)
+ && !parent->contains(AndroidPackageCreationStep::CreatePackageId))
+ return QStringList() << AndroidPackageCreationStep::CreatePackageId;
+ return QStringList();
+}
+
+QString AndroidPackageCreationFactory::displayNameForId(const QString &id) const
+{
+ if (id == AndroidPackageCreationStep::CreatePackageId)
+ return QCoreApplication::translate("Qt4ProjectManager::Internal::AndroidPackageCreationFactory",
+ "Create Android (.apk) Package");
+ return QString();
+}
+
+bool AndroidPackageCreationFactory::canCreate(ProjectExplorer::BuildStepList *parent, const QString &id) const
+{
+ return parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
+ && id == QLatin1String(AndroidPackageCreationStep::CreatePackageId)
+ && parent->target()->id() == QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID)
+ && !parent->contains(AndroidPackageCreationStep::CreatePackageId);
+}
+
+BuildStep *AndroidPackageCreationFactory::create(ProjectExplorer::BuildStepList *parent, const QString &id)
+{
+ Q_ASSERT(canCreate(parent, id));
+ return new AndroidPackageCreationStep(parent);
+}
+
+bool AndroidPackageCreationFactory::canRestore(ProjectExplorer::BuildStepList *parent,
+ const QVariantMap &map) const
+{
+ return canCreate(parent, ProjectExplorer::idFromMap(map));
+}
+
+BuildStep *AndroidPackageCreationFactory::restore(ProjectExplorer::BuildStepList *parent,
+ const QVariantMap &map)
+{
+ Q_ASSERT(canRestore(parent, map));
+ AndroidPackageCreationStep *const step
+ = new AndroidPackageCreationStep(parent);
+ if (!step->fromMap(map)) {
+ delete step;
+ return 0;
+ }
+ return step;
+}
+
+bool AndroidPackageCreationFactory::canClone(ProjectExplorer::BuildStepList *parent,
+ ProjectExplorer::BuildStep *product) const
+{
+ return canCreate(parent, product->id());
+}
+
+BuildStep *AndroidPackageCreationFactory::clone(ProjectExplorer::BuildStepList *parent,
+ ProjectExplorer::BuildStep *product)
+{
+ Q_ASSERT(canClone(parent, product));
+ return new AndroidPackageCreationStep(parent, static_cast(product));
+}
+
+} // namespace Internal
+} // namespace Android
diff --git a/src/plugins/android/androidpackagecreationfactory.h b/src/plugins/android/androidpackagecreationfactory.h
new file mode 100644
index 00000000000..81f1bd9d487
--- /dev/null
+++ b/src/plugins/android/androidpackagecreationfactory.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDPACKAGECREATIONFACTORY_H
+#define ANDROIDPACKAGECREATIONFACTORY_H
+
+#include
+
+namespace Android {
+namespace Internal {
+
+class AndroidPackageCreationFactory : public ProjectExplorer::IBuildStepFactory
+{
+public:
+ explicit AndroidPackageCreationFactory(QObject *parent = 0);
+
+ virtual QStringList availableCreationIds(ProjectExplorer::BuildStepList *parent) const;
+ virtual QString displayNameForId(const QString &id) const;
+
+ virtual bool canCreate(ProjectExplorer::BuildStepList *parent,
+ const QString &id) const;
+ virtual ProjectExplorer::BuildStep *
+ create(ProjectExplorer::BuildStepList *parent, const QString &id);
+
+ virtual bool canRestore(ProjectExplorer::BuildStepList *parent,
+ const QVariantMap &map) const;
+ virtual ProjectExplorer::BuildStep *
+ restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map);
+
+ virtual bool canClone(ProjectExplorer::BuildStepList *parent,
+ ProjectExplorer::BuildStep *product) const;
+ virtual ProjectExplorer::BuildStep *
+ clone(ProjectExplorer::BuildStepList *parent,
+ ProjectExplorer::BuildStep *product);
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDPACKAGECREATIONFACTORY_H
diff --git a/src/plugins/android/androidpackagecreationstep.cpp b/src/plugins/android/androidpackagecreationstep.cpp
new file mode 100644
index 00000000000..df4ed403b5b
--- /dev/null
+++ b/src/plugins/android/androidpackagecreationstep.cpp
@@ -0,0 +1,589 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidpackagecreationstep.h"
+
+#include "androidconstants.h"
+#include "androiddeploystep.h"
+#include "androidglobal.h"
+#include "androidpackagecreationwidget.h"
+#include "androidtarget.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace ProjectExplorer;
+using namespace ProjectExplorer::Constants;
+using ProjectExplorer::BuildStepList;
+using ProjectExplorer::BuildStepConfigWidget;
+using ProjectExplorer::Task;
+
+namespace Android {
+namespace Internal {
+
+namespace {
+ const QLatin1String KeystoreLocationKey("KeystoreLocation");
+ const QLatin1String AliasString("Alias name:");
+ const QLatin1String CertificateSeparator("*******************************************");
+}
+
+using namespace Qt4ProjectManager;
+
+class CertificatesModel: public QAbstractListModel
+{
+public:
+ CertificatesModel(const QString &rowCertificates, QObject *parent)
+ : QAbstractListModel(parent)
+ {
+ int from = rowCertificates.indexOf(AliasString);
+ QPair item;
+ while (from > -1) {
+ from += 11;// strlen(AliasString);
+ const int eol = rowCertificates.indexOf(QLatin1String("\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 > m_certs;
+};
+
+
+AndroidPackageCreationStep::AndroidPackageCreationStep(BuildStepList *bsl)
+ : BuildStep(bsl, CreatePackageId)
+{
+ ctor();
+}
+
+AndroidPackageCreationStep::AndroidPackageCreationStep(BuildStepList *bsl,
+ AndroidPackageCreationStep *other)
+ : BuildStep(bsl, other)
+{
+ ctor();
+}
+
+AndroidPackageCreationStep::~AndroidPackageCreationStep()
+{
+}
+
+void AndroidPackageCreationStep::ctor()
+{
+ setDefaultDisplayName(tr("Packaging for Android"));
+ m_openPackageLocation = true;
+ connect(&m_outputParser, SIGNAL(addTask(ProjectExplorer::Task)), this, SIGNAL(addTask(ProjectExplorer::Task)));
+}
+
+bool AndroidPackageCreationStep::init()
+{
+ AndroidTarget *target = androidTarget();
+ const Qt4BuildConfiguration *bc = target->activeQt4BuildConfiguration();
+ if (!target) {
+ raiseError(tr("Cannot create android package: current target is not android."));
+ return false;
+ }
+ m_outputParser.setProjectFileList(target->qt4Project()->files(Project::AllFiles));
+
+ // Copying
+ m_androidDir = target->androidDirPath();
+ QString androidLibPath;
+ if (target->qt4Project()->rootQt4ProjectNode()->variableValue(Qt4ProjectManager::ConfigVar).contains(QLatin1String("x86")))
+ androidLibPath = m_androidDir + QLatin1String("/libs/x86");
+ else if (target->qt4Project()->rootQt4ProjectNode()
+ ->variableValue(Qt4ProjectManager::ConfigVar).contains(QLatin1String("armeabi-v7a")))
+ androidLibPath = m_androidDir + QLatin1String("/libs/armeabi-v7a");
+ else
+ androidLibPath = m_androidDir + QLatin1String("/libs/armeabi");
+ m_gdbServerDestination = androidLibPath + QLatin1String("/gdbserver");
+ m_gdbServerSource = AndroidConfigurations::instance().gdbServerPath(target->activeRunConfiguration()->abi().architecture());
+ m_debugBuild = bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild;
+
+ if (!target->createAndroidTemplatesIfNecessary())
+ return false;
+
+ target->updateProject(target->targetSDK(), target->applicationName());
+ m_antToolPath = AndroidConfigurations::instance().antToolPath();
+ m_apkPathUnsigned = target->apkPath(AndroidTarget::ReleaseBuildUnsigned);
+ m_apkPathSigned = target->apkPath(AndroidTarget::ReleaseBuildSigned);
+ m_keystorePathForRun = m_keystorePath;
+ m_certificatePasswdForRun = m_certificatePasswd;
+ m_jarSigner = AndroidConfigurations::instance().jarsignerPath();
+ initCheckRequiredLibrariesForRun();
+ return true;
+}
+
+void AndroidPackageCreationStep::run(QFutureInterface &fi)
+{
+ fi.reportResult(createPackage());
+}
+
+BuildStepConfigWidget *AndroidPackageCreationStep::createConfigWidget()
+{
+ return new AndroidPackageCreationWidget(this);
+}
+
+AndroidTarget *AndroidPackageCreationStep::androidTarget() const
+{
+ return qobject_cast(target());
+}
+
+void AndroidPackageCreationStep::checkRequiredLibraries()
+{
+ QProcess readelfProc;
+ QString appPath = androidTarget()->targetApplicationPath();
+ if (!QFile::exists(appPath)) {
+ raiseError(tr("Can't find read elf information"),
+ tr("Can't find '%1'.\n"
+ "Please make sure your application is "
+ "built successfully and is selected in Application tab ('Run option') ").arg(appPath));
+ return;
+ }
+ readelfProc.start(AndroidConfigurations::instance().readelfPath(androidTarget()->activeRunConfiguration()->abi().architecture()),
+ QStringList() << QLatin1String("-d") << QLatin1String("-W") << appPath);
+ if (!readelfProc.waitForFinished(-1)) {
+ readelfProc.terminate();
+ return;
+ }
+ QStringList libs;
+ QList lines = readelfProc.readAll().trimmed().split('\n');
+ foreach (const QByteArray &line, lines) {
+ if (line.contains("(NEEDED)") && line.contains("Shared library:") ) {
+ const int pos = line.lastIndexOf('[') + 1;
+ libs << QString::fromLatin1(line.mid(pos, line.length() - pos - 1));
+ }
+ }
+ QStringList checkedLibs = androidTarget()->qtLibs();
+ QStringList requiredLibraries;
+ foreach (const QString &qtLib, androidTarget()->availableQtLibs()) {
+ if (libs.contains(QLatin1String("lib") + qtLib + QLatin1String(".so")) || checkedLibs.contains(qtLib))
+ requiredLibraries << qtLib;
+ }
+ androidTarget()->setQtLibs(requiredLibraries);
+
+ checkedLibs = androidTarget()->prebundledLibs();
+ requiredLibraries.clear();
+ foreach (const QString &qtLib, androidTarget()->availableQtLibs()) {
+ if (libs.contains(qtLib) || checkedLibs.contains(qtLib))
+ requiredLibraries << qtLib;
+ }
+ androidTarget()->setPrebundledLibs(requiredLibraries);
+ emit updateRequiredLibrariesModels();
+}
+
+void AndroidPackageCreationStep::initCheckRequiredLibrariesForRun()
+{
+ m_appPath = androidTarget()->targetApplicationPath();
+ m_readElf = AndroidConfigurations::instance().readelfPath(androidTarget()->activeRunConfiguration()->abi().architecture());
+ m_qtLibs = androidTarget()->qtLibs();
+ m_availableQtLibs = androidTarget()->availableQtLibs();
+ m_prebundledLibs = androidTarget()->prebundledLibs();
+}
+
+void AndroidPackageCreationStep::checkRequiredLibrariesForRun()
+{
+ QProcess readelfProc;
+ if (!QFile::exists(m_appPath)) {
+ raiseError(tr("Can't find read elf information"),
+ tr("Can't find '%1'.\n"
+ "Please make sure your application is "
+ "built successfully and is selected in Application tab ('Run option') ").arg(m_appPath));
+ return;
+ }
+ readelfProc.start(m_readElf, QStringList() << QLatin1String("-d") << QLatin1String("-W") << m_appPath);
+ if (!readelfProc.waitForFinished(-1)) {
+ readelfProc.terminate();
+ return;
+ }
+ QStringList libs;
+ QList lines = readelfProc.readAll().trimmed().split('\n');
+ foreach (const QByteArray &line, lines) {
+ if (line.contains("(NEEDED)") && line.contains("Shared library:") ) {
+ const int pos = line.lastIndexOf('[') + 1;
+ libs << QString::fromLatin1(line.mid(pos, line.length() - pos - 1));
+ }
+ }
+
+ QStringList requiredLibraries;
+ foreach (const QString &qtLib, m_availableQtLibs) {
+ if (libs.contains(QLatin1String("lib") + qtLib + QLatin1String(".so")) || m_qtLibs.contains(qtLib))
+ requiredLibraries << qtLib;
+ }
+ QMetaObject::invokeMethod(this, "setQtLibs",Qt::BlockingQueuedConnection,
+ Q_ARG(QStringList, requiredLibraries));
+
+ requiredLibraries.clear();
+ foreach (const QString &qtLib, m_availableQtLibs) {
+ if (libs.contains(qtLib) || m_prebundledLibs.contains(qtLib))
+ requiredLibraries << qtLib;
+ }
+
+ QMetaObject::invokeMethod(this, "setPrebundledLibs", Qt::BlockingQueuedConnection,
+ Q_ARG(QStringList, requiredLibraries));
+ emit updateRequiredLibrariesModels();
+}
+
+void AndroidPackageCreationStep::setQtLibs(const QStringList &qtLibs)
+{
+ androidTarget()->setQtLibs(qtLibs);
+}
+
+void AndroidPackageCreationStep::setPrebundledLibs(const QStringList &prebundledLibs)
+{
+ androidTarget()->setPrebundledLibs(prebundledLibs);
+}
+
+QString AndroidPackageCreationStep::keystorePath()
+{
+ return m_keystorePath;
+}
+
+void AndroidPackageCreationStep::setKeystorePath(const QString &path)
+{
+ m_keystorePath = path;
+ m_certificatePasswd.clear();
+ m_keystorePasswd.clear();
+}
+
+void AndroidPackageCreationStep::setKeystorePassword(const QString &pwd)
+{
+ m_keystorePasswd = pwd;
+}
+
+void AndroidPackageCreationStep::setCertificateAlias(const QString &alias)
+{
+ m_certificateAlias = alias;
+}
+
+void AndroidPackageCreationStep::setCertificatePassword(const QString &pwd)
+{
+ m_certificatePasswd = pwd;
+}
+
+void AndroidPackageCreationStep::setOpenPackageLocation(bool open)
+{
+ m_openPackageLocation = open;
+}
+
+QAbstractItemModel *AndroidPackageCreationStep::keystoreCertificates()
+{
+ QString rawCerts;
+ QProcess keytoolProc;
+ while (!rawCerts.length() || !m_keystorePasswd.length()) {
+ QStringList params;
+ params << QLatin1String("-list") << QLatin1String("-v") << QLatin1String("-keystore") << m_keystorePathForRun << QLatin1String("-storepass");
+ if (!m_keystorePasswd.length())
+ keystorePassword();
+ if (!m_keystorePasswd.length())
+ return 0;
+ params << m_keystorePasswd;
+ keytoolProc.start(AndroidConfigurations::instance().keytoolPath(), 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 AndroidPackageCreationStep::fromMap(const QVariantMap &map)
+{
+ if (!BuildStep::fromMap(map))
+ return false;
+ m_keystorePath = map.value(KeystoreLocationKey).toString();
+ return true;
+}
+
+QVariantMap AndroidPackageCreationStep::toMap() const
+{
+ QVariantMap map(BuildStep::toMap());
+ map.insert(KeystoreLocationKey, m_keystorePath);
+ return map;
+}
+
+bool AndroidPackageCreationStep::createPackage()
+{
+ checkRequiredLibrariesForRun();
+
+ emit addOutput(tr("Copy Qt app & libs to Android package ..."), MessageOutput);
+
+ QStringList build;
+ build << QLatin1String("clean");
+ QFile::remove(m_gdbServerDestination);
+ if (m_debugBuild || !m_certificateAlias.length()) {
+ build << QLatin1String("debug");
+ if (!QFile::copy(m_gdbServerSource, m_gdbServerDestination)) {
+ raiseError(tr("Can't copy gdbserver from '%1' to '%2'").arg(m_gdbServerSource)
+ .arg(m_gdbServerDestination));
+ return false;
+ }
+ } else {
+ build << QLatin1String("release");
+ }
+
+ emit addOutput(tr("Creating package file ..."), MessageOutput);
+
+ QProcess *const buildProc = new QProcess;
+
+ connect(buildProc, SIGNAL(readyReadStandardOutput()), this,
+ SLOT(handleBuildStdOutOutput()));
+ connect(buildProc, SIGNAL(readyReadStandardError()), this,
+ SLOT(handleBuildStdErrOutput()));
+
+ buildProc->setWorkingDirectory(m_androidDir);
+
+ if (!runCommand(buildProc, m_antToolPath, build)) {
+ disconnect(buildProc, 0, this, 0);
+ buildProc->deleteLater();
+ return false;
+ }
+
+ if (!(m_debugBuild) && m_certificateAlias.length()) {
+ emit addOutput(tr("Signing package ..."), MessageOutput);
+ while (true) {
+ if (m_certificatePasswdForRun.isEmpty())
+ QMetaObject::invokeMethod(this, "certificatePassword", Qt::BlockingQueuedConnection);
+
+ if (m_certificatePasswdForRun.isEmpty()) {
+ disconnect(buildProc, 0, this, 0);
+ buildProc->deleteLater();
+ return false;
+ }
+
+ QByteArray keyPass = m_certificatePasswdForRun.toUtf8();
+ build.clear();
+ build << QLatin1String("-verbose") << QLatin1String("-keystore") << m_keystorePathForRun
+ << QLatin1String("-storepass") << m_keystorePasswd
+ << m_apkPathUnsigned
+ << m_certificateAlias;
+ buildProc->start(m_jarSigner, build); //TODO
+ if (!buildProc->waitForStarted()) {
+ disconnect(buildProc, 0, this, 0);
+ buildProc->deleteLater();
+ return false;
+ }
+
+ keyPass += "\n";
+ buildProc->write(keyPass);
+ buildProc->waitForBytesWritten();
+ buildProc->waitForFinished();
+
+ if (!buildProc->exitCode())
+ break;
+ emit addOutput(tr("Failed, try again"), ErrorMessageOutput);
+ m_certificatePasswdForRun.clear();
+ }
+ if (QFile::rename(m_apkPathUnsigned, m_apkPathSigned)) {
+ emit addOutput(tr("Release signed package created to %1")
+ .arg(m_apkPathSigned)
+ , MessageOutput);
+
+ if (m_openPackageLocation)
+ QMetaObject::invokeMethod(this, "showInGraphicalShell", Qt::QueuedConnection);
+ }
+ }
+ emit addOutput(tr("Package created."), BuildStep::MessageOutput);
+ disconnect(buildProc, 0, this, 0);
+ buildProc->deleteLater();
+ return true;
+}
+
+void AndroidPackageCreationStep::stripAndroidLibs(const QStringList & files, Abi::Architecture architecture)
+{
+ QProcess stripProcess;
+ foreach (const QString &file, files) {
+ stripProcess.start(AndroidConfigurations::instance().stripPath(architecture) + QLatin1String(" --strip-unneeded ") + file);
+ if (!stripProcess.waitForFinished(-1))
+ stripProcess.terminate();
+ }
+}
+
+bool AndroidPackageCreationStep::removeDirectory(const QString &dirPath)
+{
+ QDir dir(dirPath);
+ if (!dir.exists())
+ return true;
+
+ const QStringList &files
+ = dir.entryList(QDir::Files | QDir::Hidden | QDir::System);
+ foreach (const QString &fileName, files) {
+ if (!dir.remove(fileName))
+ return false;
+ }
+
+ const QStringList &subDirs
+ = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach (const QString &subDirName, subDirs) {
+ if (!removeDirectory(dirPath + QLatin1Char('/') + subDirName))
+ return false;
+ }
+
+ return dir.rmdir(dirPath);
+}
+
+bool AndroidPackageCreationStep::runCommand(QProcess *buildProc
+ , const QString &program, const QStringList &arguments)
+{
+ emit addOutput(tr("Package deploy: Running command '%1 %2'.").arg(program).arg(arguments.join(QLatin1String(" "))), BuildStep::MessageOutput);
+ buildProc->start(program, arguments);
+ if (!buildProc->waitForStarted()) {
+ raiseError(tr("Packaging failed."),
+ tr("Packaging error: Could not start command '%1 %2'. Reason: %3")
+ .arg(program).arg(arguments.join(QLatin1String(" "))).arg(buildProc->errorString()));
+ return false;
+ }
+ buildProc->waitForFinished(-1);
+ if (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());
+ raiseError(mainMessage);
+ return false;
+ }
+ return true;
+}
+
+void AndroidPackageCreationStep::handleBuildStdOutOutput()
+{
+ QProcess *const process = qobject_cast(sender());
+ if (!process)
+ return;
+
+ process->setReadChannel(QProcess::StandardOutput);
+ while (process->canReadLine()) {
+ QString line = QString::fromLocal8Bit(process->readLine());
+ m_outputParser.stdOutput(line);
+ emit addOutput(line, BuildStep::NormalOutput, BuildStep::DontAppendNewline);
+ }
+}
+
+void AndroidPackageCreationStep::handleBuildStdErrOutput()
+{
+ QProcess *const process = qobject_cast(sender());
+ if (!process)
+ return;
+
+ process->setReadChannel(QProcess::StandardError);
+ while (process->canReadLine()) {
+ QString line = QString::fromLocal8Bit(process->readLine());
+ m_outputParser.stdError(line);
+ emit addOutput(line, BuildStep::ErrorOutput, BuildStep::DontAppendNewline);
+ }
+}
+
+void AndroidPackageCreationStep::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;
+}
+
+void AndroidPackageCreationStep::certificatePassword()
+{
+ m_certificatePasswdForRun.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_certificatePasswdForRun = text;
+}
+
+void AndroidPackageCreationStep::showInGraphicalShell()
+{
+ Core::FileUtils::showInGraphicalShell(Core::ICore::instance()->mainWindow(), m_apkPathSigned);
+}
+
+void AndroidPackageCreationStep::raiseError(const QString &shortMsg,
+ const QString &detailedMsg)
+{
+ emit addOutput(detailedMsg.isNull() ? shortMsg : detailedMsg, BuildStep::ErrorOutput);
+ emit addTask(Task(Task::Error, shortMsg, Utils::FileName::fromString(QString()), -1,
+ TASK_CATEGORY_BUILDSYSTEM));
+}
+
+const QLatin1String AndroidPackageCreationStep::CreatePackageId("Qt4ProjectManager.AndroidPackageCreationStep");
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/android/androidpackagecreationstep.h b/src/plugins/android/androidpackagecreationstep.h
new file mode 100644
index 00000000000..85ed43414b4
--- /dev/null
+++ b/src/plugins/android/androidpackagecreationstep.h
@@ -0,0 +1,144 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDPACKAGECREATIONSTEP_H
+#define ANDROIDPACKAGECREATIONSTEP_H
+
+#include
+#include
+#include
+#include "javaparser.h"
+
+QT_BEGIN_NAMESPACE
+class QDateTime;
+class QFile;
+class QProcess;
+QT_END_NAMESPACE
+
+namespace Qt4ProjectManager {
+class Qt4BuildConfiguration;
+}
+
+namespace Android {
+namespace Internal {
+class AndroidTarget;
+
+class AndroidPackageCreationStep : public ProjectExplorer::BuildStep
+{
+ Q_OBJECT
+ friend class AndroidPackageCreationFactory;
+public:
+ AndroidPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
+ ~AndroidPackageCreationStep();
+
+ static bool removeDirectory(const QString &dirPath);
+
+ static void stripAndroidLibs(const QStringList &files, ProjectExplorer::Abi::Architecture architecture);
+
+ static const QLatin1String DefaultVersionNumber;
+
+ AndroidTarget *androidTarget() const;
+
+ void checkRequiredLibraries();
+ void initCheckRequiredLibrariesForRun();
+ void checkRequiredLibrariesForRun();
+
+ QString keystorePath();
+ void setKeystorePath(const QString &path);
+ void setKeystorePassword(const QString &pwd);
+ void setCertificateAlias(const QString &alias);
+ void setCertificatePassword(const QString &pwd);
+ void setOpenPackageLocation(bool open);
+ QAbstractItemModel *keystoreCertificates();
+
+protected:
+ virtual bool fromMap(const QVariantMap &map);
+ virtual QVariantMap toMap() const;
+
+private slots:
+ void handleBuildStdOutOutput();
+ void handleBuildStdErrOutput();
+ void keystorePassword();
+ void certificatePassword();
+ void showInGraphicalShell();
+ void setQtLibs(const QStringList &qtLibs);
+ void setPrebundledLibs(const QStringList &prebundledLibs);
+
+private:
+ AndroidPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
+ AndroidPackageCreationStep *other);
+
+ void ctor();
+ virtual bool init();
+ virtual void run(QFutureInterface &fi);
+ virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
+ virtual bool immutable() const { return true; }
+ bool createPackage();
+ bool runCommand(QProcess *buildProc, const QString &program, const QStringList &arguments);
+ void raiseError(const QString &shortMsg,
+ const QString &detailedMsg = QString());
+
+ static const QLatin1String CreatePackageId;
+
+private:
+ QString m_keystorePath;
+ QString m_keystorePasswd;
+ QString m_certificateAlias;
+ QString m_certificatePasswd;
+ bool m_openPackageLocation;
+ JavaParser m_outputParser;
+
+ // members to pass data from init() to run()
+ QString m_androidDir;
+ QString m_gdbServerSource;
+ QString m_gdbServerDestination;
+ bool m_debugBuild;
+ QString m_antToolPath;
+ QString m_apkPathUnsigned;
+ QString m_apkPathSigned;
+ QString m_keystorePathForRun;
+ QString m_certificatePasswdForRun;
+ QString m_jarSigner;
+ // more for checkLibraries
+ QString m_appPath;
+ QString m_readElf;
+ QStringList m_qtLibs;
+ QStringList m_availableQtLibs;
+ QStringList m_prebundledLibs;
+signals:
+ void updateRequiredLibrariesModels();
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDPACKAGECREATIONSTEP_H
diff --git a/src/plugins/android/androidpackagecreationwidget.cpp b/src/plugins/android/androidpackagecreationwidget.cpp
new file mode 100644
index 00000000000..3ccc08c8d2f
--- /dev/null
+++ b/src/plugins/android/androidpackagecreationwidget.cpp
@@ -0,0 +1,556 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidpackagecreationwidget.h"
+#include "androidpackagecreationstep.h"
+#include "androidconfigurations.h"
+#include "androidcreatekeystorecertificate.h"
+#include "androidtarget.h"
+#include "ui_androidpackagecreationwidget.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+namespace Android {
+namespace Internal {
+
+using namespace Qt4ProjectManager;
+
+const QLatin1String packageNameRegExp("^([a-z_]{1}[a-z0-9_]+(\\.[a-zA-Z_]{1}[a-zA-Z0-9_]*)*)$");
+
+bool checkPackageName(const QString &packageName)
+{
+ return QRegExp(packageNameRegExp).exactMatch(packageName);
+}
+
+///////////////////////////// CheckModel /////////////////////////////
+CheckModel::CheckModel(QObject *parent) : QAbstractListModel(parent)
+{
+
+}
+
+void CheckModel::setAvailableItems(const QStringList &items)
+{
+ beginResetModel();
+ m_availableItems = items;
+ endResetModel();
+}
+
+void CheckModel::setCheckedItems(const QStringList &items)
+{
+ m_checkedItems = items;
+ if (rowCount())
+ emit dataChanged(index(0), index(rowCount()-1));
+}
+
+const QStringList &CheckModel::checkedItems()
+{
+ return m_checkedItems;
+}
+
+QVariant CheckModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+ switch (role) {
+ case Qt::CheckStateRole:
+ return m_checkedItems.contains(m_availableItems.at(index.row())) ? Qt::Checked : Qt::Unchecked;
+ case Qt::DisplayRole:
+ return m_availableItems.at(index.row());
+ }
+ return QVariant();
+}
+
+void CheckModel::moveUp(int index)
+{
+ beginMoveRows(QModelIndex(), index, index, QModelIndex(), index - 1);
+ const QString &item1 = m_availableItems[index];
+ const QString &item2 = m_availableItems[index - 1];
+ m_availableItems.swap(index, index - 1);
+ index = m_checkedItems.indexOf(item1);
+ int index2 = m_checkedItems.indexOf(item2);
+ if (index > -1 && index2 > -1)
+ m_checkedItems.swap(index, index2);
+ endMoveRows();
+}
+
+bool CheckModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (role != Qt::CheckStateRole || !index.isValid())
+ return false;
+ if (value.toInt() == Qt::Checked)
+ m_checkedItems.append(m_availableItems.at(index.row()));
+ else
+ m_checkedItems.removeAll(m_availableItems.at(index.row()));
+ emit dataChanged(index, index);
+ return true;
+}
+
+int CheckModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+ return m_availableItems.count();
+}
+
+Qt::ItemFlags CheckModel::flags(const QModelIndex &/*index*/) const
+{
+ return Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled;
+}
+///////////////////////////// CheckModel /////////////////////////////
+
+
+///////////////////////////// PermissionsModel /////////////////////////////
+PermissionsModel::PermissionsModel(QObject *parent):QAbstractListModel(parent)
+{
+}
+
+void PermissionsModel::setPermissions(const QStringList &permissions)
+{
+ m_permissions = permissions;
+ reset();
+}
+const QStringList &PermissionsModel::permissions()
+{
+ return m_permissions;
+}
+
+QModelIndex PermissionsModel::addPermission(const QString &permission)
+{
+ const int idx = m_permissions.count();
+ beginInsertRows(QModelIndex(), idx, idx);
+ m_permissions.push_back(permission);
+ endInsertRows();
+ return index(idx);
+}
+
+bool PermissionsModel::updatePermission(QModelIndex index, const QString &permission)
+{
+ if (!index.isValid())
+ return false;
+ if (m_permissions[index.row()] == permission)
+ return false;
+ m_permissions[index.row()] = permission;
+ emit dataChanged(index, index);
+ return true;
+}
+
+void PermissionsModel::removePermission(int index)
+{
+ if (index >= m_permissions.size())
+ return;
+ beginRemoveRows(QModelIndex(), index, index);
+ m_permissions.removeAt(index);
+ endRemoveRows();
+}
+
+QVariant PermissionsModel::data(const QModelIndex &index, int role) const
+{
+ if (role != Qt::DisplayRole || !index.isValid())
+ return QVariant();
+ return m_permissions[index.row()];
+}
+
+int PermissionsModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+ return m_permissions.count();
+}
+///////////////////////////// PermissionsModel /////////////////////////////
+
+
+///////////////////////////// AndroidPackageCreationWidget /////////////////////////////
+AndroidPackageCreationWidget::AndroidPackageCreationWidget(AndroidPackageCreationStep *step)
+ : ProjectExplorer::BuildStepConfigWidget(),
+ m_step(step),
+ m_ui(new Ui::AndroidPackageCreationWidget)
+{
+ m_qtLibsModel = new CheckModel(this);
+ m_prebundledLibs = new CheckModel(this);
+ m_permissionsModel = new PermissionsModel(this);
+
+ m_ui->setupUi(this);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ QTimer::singleShot(50, this, SLOT(initGui()));
+ connect(m_step, SIGNAL(updateRequiredLibrariesModels()), SLOT(updateRequiredLibrariesModels()));
+}
+
+
+void AndroidPackageCreationWidget::initGui()
+{
+ updateAndroidProjectInfo();
+ AndroidTarget *target = m_step->androidTarget();
+ connect(target,
+ SIGNAL(androidDirContentsChanged()),
+ this, SLOT(updateAndroidProjectInfo()));
+ m_ui->packageNameLineEdit->setValidator(new QRegExpValidator(QRegExp(packageNameRegExp), this));
+ connect(m_ui->packageNameLineEdit, SIGNAL(editingFinished()), SLOT(setPackageName()));
+ connect(m_ui->appNameLineEdit, SIGNAL(editingFinished()), SLOT(setApplicationName()));
+ connect(m_ui->versionCode, SIGNAL(editingFinished()), SLOT(setVersionCode()));
+ connect(m_ui->versionNameLinedit, SIGNAL(editingFinished()), SLOT(setVersionName()));
+ connect(m_ui->targetSDKComboBox, SIGNAL(activated(QString)), SLOT(setTargetSDK(QString)));
+ connect(m_ui->permissionsListView, SIGNAL(activated(QModelIndex)), SLOT(permissionActivated(QModelIndex)));
+ connect(m_ui->addPermissionButton, SIGNAL(clicked()), SLOT(addPermission()));
+ connect(m_ui->removePermissionButton, SIGNAL(clicked()), SLOT(removePermission()));
+ connect(m_ui->permissionsComboBox->lineEdit(), SIGNAL(editingFinished()), SLOT(updatePermission()));
+ connect(m_ui->savePermissionsButton, SIGNAL(clicked()), SLOT(savePermissionsButton()));
+ connect(m_ui->discardPermissionsButton, SIGNAL(clicked()), SLOT(discardPermissionsButton()));
+ connect(m_ui->targetComboBox, SIGNAL(activated(QString)), SLOT(setTarget(QString)));
+ connect(m_qtLibsModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(setQtLibs(QModelIndex,QModelIndex)));
+ connect(m_prebundledLibs, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(setPrebundledLibs(QModelIndex,QModelIndex)));
+ connect(m_ui->prebundledLibsListView, SIGNAL(activated(QModelIndex)), SLOT(prebundledLibSelected(QModelIndex)));
+ connect(m_ui->prebundledLibsListView, SIGNAL(clicked(QModelIndex)), SLOT(prebundledLibSelected(QModelIndex)));
+ connect(m_ui->upPushButton, SIGNAL(clicked()), SLOT(prebundledLibMoveUp()));
+ connect(m_ui->downPushButton, SIGNAL(clicked()), SLOT(prebundledLibMoveDown()));
+ connect(m_ui->readInfoPushButton, SIGNAL(clicked()), SLOT(readElfInfo()));
+
+ connect(m_ui->hIconButton, SIGNAL(clicked()), SLOT(setHDPIIcon()));
+ connect(m_ui->mIconButton, SIGNAL(clicked()), SLOT(setMDPIIcon()));
+ connect(m_ui->lIconButton, SIGNAL(clicked()), SLOT(setLDPIIcon()));
+
+ m_ui->qtLibsListView->setModel(m_qtLibsModel);
+ m_ui->prebundledLibsListView->setModel(m_prebundledLibs);
+ m_ui->permissionsListView->setModel(m_permissionsModel);
+ m_ui->KeystoreLocationLineEdit->setText(m_step->keystorePath());
+}
+
+void AndroidPackageCreationWidget::updateAndroidProjectInfo()
+{
+ AndroidTarget *target = m_step->androidTarget();
+ m_ui->targetSDKComboBox->clear();
+ QStringList targets = AndroidConfigurations::instance().sdkTargets();
+ m_ui->targetSDKComboBox->addItems(targets);
+ m_ui->targetSDKComboBox->setCurrentIndex(targets.indexOf(target->targetSDK()));
+ m_ui->packageNameLineEdit->setText(target->packageName());
+ m_ui->appNameLineEdit->setText(target->applicationName());
+ if (!m_ui->appNameLineEdit->text().length()) {
+ QString applicationName = target->project()->displayName();
+ target->setPackageName(target->packageName() + QLatin1Char('.') + applicationName);
+ m_ui->packageNameLineEdit->setText(target->packageName());
+ if (applicationName.length())
+ applicationName[0] = applicationName[0].toUpper();
+ m_ui->appNameLineEdit->setText(applicationName);
+ target->setApplicationName(applicationName);
+ }
+ m_ui->versionCode->setValue(target->versionCode());
+ m_ui->versionNameLinedit->setText(target->versionName());
+
+ m_qtLibsModel->setAvailableItems(target->availableQtLibs());
+ m_qtLibsModel->setCheckedItems(target->qtLibs());
+ m_prebundledLibs->setAvailableItems(target->availablePrebundledLibs());
+ m_prebundledLibs->setCheckedItems(target->prebundledLibs());
+
+ m_permissionsModel->setPermissions(target->permissions());
+ m_ui->removePermissionButton->setEnabled(m_permissionsModel->permissions().size());
+
+ targets = target->availableTargetApplications();
+ m_ui->targetComboBox->clear();
+ m_ui->targetComboBox->addItems(targets);
+ m_ui->targetComboBox->setCurrentIndex(targets.indexOf(target->targetApplication()));
+ if (m_ui->targetComboBox->currentIndex() == -1 && targets.count()) {
+ m_ui->targetComboBox->setCurrentIndex(0);
+ target->setTargetApplication(m_ui->targetComboBox->currentText());
+ }
+ m_ui->hIconButton->setIcon(target->highDpiIcon());
+ m_ui->mIconButton->setIcon(target->mediumDpiIcon());
+ m_ui->lIconButton->setIcon(target->lowDpiIcon());
+}
+
+void AndroidPackageCreationWidget::setPackageName()
+{
+ const QString packageName= m_ui->packageNameLineEdit->text();
+ if (!checkPackageName(packageName)) {
+ QMessageBox::critical(this, tr("Invalid package name") ,
+ tr("The package name '%1' is not valid.\n"
+ "Please choose a valid package name for your application (e.g. \"org.example.myapplication\").")
+ .arg(packageName));
+ m_ui->packageNameLineEdit->selectAll();
+ m_ui->packageNameLineEdit->setFocus();
+ return;
+ }
+ m_step->androidTarget()->setPackageName(packageName);
+}
+
+void AndroidPackageCreationWidget::setApplicationName()
+{
+ m_step->androidTarget()->setApplicationName(m_ui->appNameLineEdit->text());
+}
+
+void AndroidPackageCreationWidget::setTargetSDK(const QString &target)
+{
+ m_step->androidTarget()->setTargetSDK(target);
+ Qt4BuildConfiguration *bc = m_step->androidTarget()->activeQt4BuildConfiguration();
+ ProjectExplorer::BuildManager *bm = ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager();
+ QMakeStep *qs = bc->qmakeStep();
+
+ if (!qs)
+ return;
+
+ qs->setForced(true);
+
+ bm->buildList(bc->stepList(QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_CLEAN)),
+ ProjectExplorer::ProjectExplorerPlugin::displayNameForStepId(QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_CLEAN)));
+ bm->appendStep(qs, ProjectExplorer::ProjectExplorerPlugin::displayNameForStepId(QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_CLEAN)));
+ bc->setSubNodeBuild(0);
+ // Make the buildconfiguration emit a evironmentChanged() signal
+ // TODO find a better way
+ bool use = bc->useSystemEnvironment();
+ bc->setUseSystemEnvironment(!use);
+ bc->setUseSystemEnvironment(use);
+}
+
+void AndroidPackageCreationWidget::setVersionCode()
+{
+ m_step->androidTarget()->setVersionCode(m_ui->versionCode->value());
+}
+
+void AndroidPackageCreationWidget::setVersionName()
+{
+ m_step->androidTarget()->setVersionName(m_ui->versionNameLinedit->text());
+}
+
+void AndroidPackageCreationWidget::setTarget(const QString &target)
+{
+ m_step->androidTarget()->setTargetApplication(target);
+}
+
+void AndroidPackageCreationWidget::setQtLibs(QModelIndex, QModelIndex)
+{
+ m_step->androidTarget()->setQtLibs(m_qtLibsModel->checkedItems());
+}
+
+void AndroidPackageCreationWidget::setPrebundledLibs(QModelIndex, QModelIndex)
+{
+ m_step->androidTarget()->setPrebundledLibs(m_prebundledLibs->checkedItems());
+}
+
+void AndroidPackageCreationWidget::prebundledLibSelected(const QModelIndex &index)
+{
+ m_ui->upPushButton->setEnabled(false);
+ m_ui->downPushButton->setEnabled(false);
+ if (!index.isValid())
+ return;
+ if (index.row() > 0)
+ m_ui->upPushButton->setEnabled(true);
+ if (index.row() < m_prebundledLibs->rowCount(QModelIndex()) - 1)
+ m_ui->downPushButton->setEnabled(true);
+}
+
+void AndroidPackageCreationWidget::prebundledLibMoveUp()
+{
+ const QModelIndex &index = m_ui->prebundledLibsListView->currentIndex();
+ if (index.isValid())
+ m_prebundledLibs->moveUp(index.row());
+}
+
+void AndroidPackageCreationWidget::prebundledLibMoveDown()
+{
+ const QModelIndex &index = m_ui->prebundledLibsListView->currentIndex();
+ if (index.isValid())
+ m_prebundledLibs->moveUp(index.row() + 1);
+}
+
+void AndroidPackageCreationWidget::setHDPIIcon()
+{
+ QString file = QFileDialog::getOpenFileName(this, tr("Choose High DPI Icon"), QDir::homePath(), tr("png images (*.png)"));
+ if (!file.length())
+ return;
+ m_step->androidTarget()->setHighDpiIcon(file);
+ m_ui->hIconButton->setIcon(m_step->androidTarget()->highDpiIcon());
+}
+
+void AndroidPackageCreationWidget::setMDPIIcon()
+{
+ QString file = QFileDialog::getOpenFileName(this, tr("Choose Medium DPI Icon"), QDir::homePath(), tr("png images (*.png)"));
+ if (!file.length())
+ return;
+ m_step->androidTarget()->setMediumDpiIcon(file);
+ m_ui->mIconButton->setIcon(m_step->androidTarget()->mediumDpiIcon());
+}
+
+void AndroidPackageCreationWidget::setLDPIIcon()
+{
+ QString file = QFileDialog::getOpenFileName(this, tr("Choose Low DPI Icon"), QDir::homePath(), tr("png images (*.png)"));
+ if (!file.length())
+ return;
+ m_step->androidTarget()->setLowDpiIcon(file);
+ m_ui->lIconButton->setIcon(m_step->androidTarget()->lowDpiIcon());
+}
+
+void AndroidPackageCreationWidget::permissionActivated(QModelIndex index)
+{
+ m_ui->permissionsComboBox->setCurrentIndex(
+ m_ui->permissionsComboBox->findText(m_permissionsModel->data(index, Qt::DisplayRole).toString()));
+ m_ui->permissionsComboBox->lineEdit()->setText(m_permissionsModel->data(index, Qt::DisplayRole).toString());
+}
+
+void AndroidPackageCreationWidget::addPermission()
+{
+ setEnabledSaveDiscardButtons(true);
+ m_ui->permissionsListView->setCurrentIndex(m_permissionsModel->addPermission(tr("< type or choose a permission >")));
+ m_ui->permissionsComboBox->lineEdit()->setText(tr("< type or choose a permission >"));
+ m_ui->permissionsComboBox->setFocus();
+ m_ui->removePermissionButton->setEnabled(m_permissionsModel->permissions().size());
+}
+
+void AndroidPackageCreationWidget::updatePermission()
+{
+ if (m_permissionsModel->updatePermission(m_ui->permissionsListView->currentIndex(),
+ m_ui->permissionsComboBox->lineEdit()->text()))
+ setEnabledSaveDiscardButtons(true);
+}
+
+void AndroidPackageCreationWidget::removePermission()
+{
+ setEnabledSaveDiscardButtons(true);
+ if (m_ui->permissionsListView->currentIndex().isValid())
+ m_permissionsModel->removePermission(m_ui->permissionsListView->currentIndex().row());
+ m_ui->removePermissionButton->setEnabled(m_permissionsModel->permissions().size());
+}
+
+void AndroidPackageCreationWidget::savePermissionsButton()
+{
+ setEnabledSaveDiscardButtons(false);
+ m_step->androidTarget()->setPermissions(m_permissionsModel->permissions());
+}
+
+void AndroidPackageCreationWidget::discardPermissionsButton()
+{
+ setEnabledSaveDiscardButtons(false);
+ m_permissionsModel->setPermissions(m_step->androidTarget()->permissions());
+ m_ui->permissionsComboBox->setCurrentIndex(-1);
+ m_ui->removePermissionButton->setEnabled(m_permissionsModel->permissions().size());
+}
+
+void AndroidPackageCreationWidget::updateRequiredLibrariesModels()
+{
+ m_qtLibsModel->setCheckedItems(m_step->androidTarget()->qtLibs());
+ m_prebundledLibs->setCheckedItems(m_step->androidTarget()->prebundledLibs());
+}
+
+void AndroidPackageCreationWidget::readElfInfo()
+{
+ m_step->checkRequiredLibraries();
+}
+
+void AndroidPackageCreationWidget::setEnabledSaveDiscardButtons(bool enabled)
+{
+ if (!enabled)
+ m_ui->permissionsListView->setFocus();
+ m_ui->savePermissionsButton->setEnabled(enabled);
+ m_ui->discardPermissionsButton->setEnabled(enabled);
+}
+
+QString AndroidPackageCreationWidget::summaryText() const
+{
+ return tr("Package configurations");
+}
+
+QString AndroidPackageCreationWidget::displayName() const
+{
+ return m_step->displayName();
+}
+
+void AndroidPackageCreationWidget::setCertificates()
+{
+ QAbstractItemModel *certificates = m_step->keystoreCertificates();
+ m_ui->signPackageCheckBox->setChecked(certificates);
+ m_ui->certificatesAliasComboBox->setModel(certificates);
+}
+
+void AndroidPackageCreationWidget::on_signPackageCheckBox_toggled(bool checked)
+{
+ if (!checked)
+ return;
+ if (m_step->keystorePath().length())
+ setCertificates();
+}
+
+void AndroidPackageCreationWidget::on_KeystoreCreatePushButton_clicked()
+{
+ AndroidCreateKeystoreCertificate d;
+ if (d.exec() != QDialog::Accepted)
+ return;
+ m_ui->KeystoreLocationLineEdit->setText(d.keystoreFilePath());
+ m_step->setKeystorePath(d.keystoreFilePath());
+ m_step->setKeystorePassword(d.keystorePassword());
+ m_step->setCertificateAlias(d.certificateAlias());
+ m_step->setCertificatePassword(d.certificatePassword());
+ setCertificates();
+}
+
+void AndroidPackageCreationWidget::on_KeystoreLocationPushButton_clicked()
+{
+ QString keystorePath = m_step->keystorePath();
+ if (!keystorePath.length())
+ keystorePath = QDir::homePath();
+ QString file = QFileDialog::getOpenFileName(this, tr("Select keystore file"), keystorePath, tr("Keystore files (*.keystore *.jks)"));
+ if (!file.length())
+ return;
+ m_ui->KeystoreLocationLineEdit->setText(file);
+ m_step->setKeystorePath(file);
+ m_ui->signPackageCheckBox->setChecked(false);
+}
+
+void AndroidPackageCreationWidget::on_certificatesAliasComboBox_activated(const QString &alias)
+{
+ if (alias.length())
+ m_step->setCertificateAlias(alias);
+}
+
+void AndroidPackageCreationWidget::on_certificatesAliasComboBox_currentIndexChanged(const QString &alias)
+{
+ if (alias.length())
+ m_step->setCertificateAlias(alias);
+}
+
+void AndroidPackageCreationWidget::on_openPackageLocationCheckBox_toggled(bool checked)
+{
+ m_step->setOpenPackageLocation(checked);
+}
+
+} // namespace Internal
+} // namespace Android
+
+
+
diff --git a/src/plugins/android/androidpackagecreationwidget.h b/src/plugins/android/androidpackagecreationwidget.h
new file mode 100644
index 00000000000..59ca55ce86d
--- /dev/null
+++ b/src/plugins/android/androidpackagecreationwidget.h
@@ -0,0 +1,150 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDPACKAGECREATIONWIDGET_H
+#define ANDROIDPACKAGECREATIONWIDGET_H
+
+#include
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class AndroidPackageCreationWidget; }
+QT_END_NAMESPACE
+
+namespace Android {
+namespace Internal {
+class AndroidPackageCreationStep;
+
+class CheckModel: public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ CheckModel(QObject *parent = 0);
+ void setAvailableItems(const QStringList &items);
+ void setCheckedItems(const QStringList &items);
+ const QStringList &checkedItems();
+ QVariant data(const QModelIndex &index, int role) const;
+ void moveUp(int index);
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+
+protected:
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+private:
+ QStringList m_availableItems;
+ QStringList m_checkedItems;
+};
+
+class PermissionsModel: public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ PermissionsModel(QObject *parent = 0 );
+ void setPermissions(const QStringList &permissions);
+ const QStringList &permissions();
+ QModelIndex addPermission(const QString &permission);
+ bool updatePermission(QModelIndex index, const QString &permission);
+ void removePermission(int index);
+ QVariant data(const QModelIndex &index, int role) const;
+
+protected:
+ int rowCount(const QModelIndex &parent) const;
+
+private:
+ QStringList m_permissions;
+};
+
+class AndroidPackageCreationWidget : public ProjectExplorer::BuildStepConfigWidget
+{
+ Q_OBJECT
+public:
+ AndroidPackageCreationWidget(AndroidPackageCreationStep *step);
+
+ virtual QString summaryText() const;
+ virtual QString displayName() const;
+
+public slots:
+ void readElfInfo();
+
+private:
+ void setEnabledSaveDiscardButtons(bool enabled);
+ void setCertificates();
+
+private slots:
+ void initGui();
+ void updateAndroidProjectInfo();
+
+ void setPackageName();
+ void setApplicationName();
+ void setTargetSDK(const QString &target);
+ void setVersionCode();
+ void setVersionName();
+ void setTarget(const QString &target);
+
+ void setQtLibs(QModelIndex, QModelIndex);
+ void setPrebundledLibs(QModelIndex, QModelIndex);
+ void prebundledLibSelected(const QModelIndex &index);
+ void prebundledLibMoveUp();
+ void prebundledLibMoveDown();
+
+ void setHDPIIcon();
+ void setMDPIIcon();
+ void setLDPIIcon();
+
+ void permissionActivated(QModelIndex index);
+ void addPermission();
+ void updatePermission();
+ void removePermission();
+ void savePermissionsButton();
+ void discardPermissionsButton();
+ void updateRequiredLibrariesModels();
+ void on_signPackageCheckBox_toggled(bool checked);
+ void on_KeystoreCreatePushButton_clicked();
+ void on_KeystoreLocationPushButton_clicked();
+ void on_certificatesAliasComboBox_activated(const QString &alias);
+ void on_certificatesAliasComboBox_currentIndexChanged(const QString &alias);
+
+ void on_openPackageLocationCheckBox_toggled(bool checked);
+
+private:
+ AndroidPackageCreationStep *const m_step;
+ Ui::AndroidPackageCreationWidget *const m_ui;
+ CheckModel *m_qtLibsModel;
+ CheckModel *m_prebundledLibs;
+ PermissionsModel *m_permissionsModel;
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDPACKAGECREATIONWIDGET_H
diff --git a/src/plugins/android/androidpackagecreationwidget.ui b/src/plugins/android/androidpackagecreationwidget.ui
new file mode 100644
index 00000000000..ef0f66b79db
--- /dev/null
+++ b/src/plugins/android/androidpackagecreationwidget.ui
@@ -0,0 +1,1262 @@
+
+
+ AndroidPackageCreationWidget
+
+
+
+ 0
+ 0
+ 649
+ 384
+
+
+
+
+ 1
+ 1
+
+
+
+ -
+
+
+ QTabWidget::South
+
+
+ 0
+
+
+
+ Manifest
+
+
+
+ QFormLayout::ExpandingFieldsGrow
+
+
-
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;">
+<tr>
+<td style="border: none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Android target SDK:</span></p></td></tr></table></body></html>
+
+
+
+ -
+
+
+ -
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<table style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;">
+<tr>
+<td style="border: none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Package name:</span></p></td></tr></table></body></html>
+
+
+
+ -
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<table style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;">
+<tr>
+<td style="border: none;">
+<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Please choose a valid package name for your application (e.g. "org.example.myapplication"). </p>
+<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
+<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Packages are usually defined using a hierarchical naming pattern, with levels in the hierarchy separated by periods (.) (pronounced "dot").</p>
+<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">In general, a package name begins with the top level domain name of the organization and then the organization's domain and then any subdomains listed in reverse order. The organization can then choose a specific name for their package. Package names should be all lowercase characters whenever possible.</p>
+<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
+<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Complete conventions for disambiguating package names and rules for naming packages when the Internet domain name cannot be directly used as a package name are described in section 7.7 of the Java Language Specification.</p>
+<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></td></tr></table></body></html>
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ true
+
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:600; font-style:normal;">
+<table style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;">
+<tr>
+<td style="border: none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Version code:</p></td></tr></table></body></html>
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 99
+
+
+ 1
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ true
+
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:600; font-style:normal;">
+<table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;">
+<tr>
+<td style="border: none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Version name:</p></td></tr></table></body></html>
+
+
+
+ -
+
+
+ 1.0.0
+
+
+
+
+
+
+
+ Application
+
+
+ -
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;">
+<tr>
+<td style="border: none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Application name:</span></p></td></tr></table></body></html>
+
+
+
+ -
+
+
+ -
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;">
+<tr>
+<td style="border: none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Run:</span></p></td></tr></table></body></html>
+
+
+ Qt::AutoText
+
+
+
+ -
+
+
+ -
+
+
+
+ 0
+ 48
+
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<table style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;">
+<tr>
+<td style="border: none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Application icon:</span></p></td></tr></table></body></html>
+
+
+
+ -
+
+
-
+
+
+
+ 48
+ 48
+
+
+
+
+ 48
+ 48
+
+
+
+ Select low dpi icon
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 28
+ 20
+
+
+
+
+ -
+
+
+
+ 48
+ 48
+
+
+
+
+ 48
+ 48
+
+
+
+ Select medium dpi icon
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 28
+ 20
+
+
+
+
+ -
+
+
+
+ 48
+ 48
+
+
+
+
+ 48
+ 48
+
+
+
+ Select high dpi icon
+
+
+
+
+
+
+
+
+
+
+
+
+ Permissions
+
+
+ -
+
+
-
+
+
+
+ 0
+ 200
+
+
+
+
+ -
+
+
-
+
+
+ Add
+
+
+
+ -
+
+
+ Remove
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ false
+
+
+ Save
+
+
+
+ -
+
+
+ false
+
+
+ Discard
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Name:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ true
+
+
+ 0
+
+
-
+
+ android.permission.ACCESS_CHECKIN_PROPERTIES
+
+
+ -
+
+ android.permission.ACCESS_COARSE_LOCATION
+
+
+ -
+
+ android.permission.ACCESS_FINE_LOCATION
+
+
+ -
+
+ android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
+
+
+ -
+
+ android.permission.ACCESS_MOCK_LOCATION
+
+
+ -
+
+ android.permission.ACCESS_NETWORK_STATE
+
+
+ -
+
+ android.permission.ACCESS_SURFACE_FLINGER
+
+
+ -
+
+ android.permission.ACCESS_WIFI_STATE
+
+
+ -
+
+ android.permission.ACCOUNT_MANAGER
+
+
+ -
+
+ android.permission.AUTHENTICATE_ACCOUNTS
+
+
+ -
+
+ android.permission.BATTERY_STATS
+
+
+ -
+
+ android.permission.BIND_APPWIDGET
+
+
+ -
+
+ android.permission.BIND_DEVICE_ADMIN
+
+
+ -
+
+ android.permission.BIND_INPUT_METHOD
+
+
+ -
+
+ android.permission.BIND_REMOTEVIEWS
+
+
+ -
+
+ android.permission.BIND_WALLPAPER
+
+
+ -
+
+ android.permission.BLUETOOTH
+
+
+ -
+
+ android.permission.BLUETOOTH_ADMIN
+
+
+ -
+
+ android.permission.BRICK
+
+
+ -
+
+ android.permission.BROADCAST_PACKAGE_REMOVED
+
+
+ -
+
+ android.permission.BROADCAST_SMS
+
+
+ -
+
+ android.permission.BROADCAST_STICKY
+
+
+ -
+
+ android.permission.BROADCAST_WAP_PUSH
+
+
+ -
+
+ android.permission.CALL_PHONE
+
+
+ -
+
+ android.permission.CALL_PRIVILEGED
+
+
+ -
+
+ android.permission.CAMERA
+
+
+ -
+
+ android.permission.CHANGE_COMPONENT_ENABLED_STATE
+
+
+ -
+
+ android.permission.CHANGE_CONFIGURATION
+
+
+ -
+
+ android.permission.CHANGE_NETWORK_STATE
+
+
+ -
+
+ android.permission.CHANGE_WIFI_MULTICAST_STATE
+
+
+ -
+
+ android.permission.CHANGE_WIFI_STATE
+
+
+ -
+
+ android.permission.CLEAR_APP_CACHE
+
+
+ -
+
+ android.permission.CLEAR_APP_USER_DATA
+
+
+ -
+
+ android.permission.CONTROL_LOCATION_UPDATES
+
+
+ -
+
+ android.permission.DELETE_CACHE_FILES
+
+
+ -
+
+ android.permission.DELETE_PACKAGES
+
+
+ -
+
+ android.permission.DEVICE_POWER
+
+
+ -
+
+ android.permission.DIAGNOSTIC
+
+
+ -
+
+ android.permission.DISABLE_KEYGUARD
+
+
+ -
+
+ android.permission.DUMP
+
+
+ -
+
+ android.permission.EXPAND_STATUS_BAR
+
+
+ -
+
+ android.permission.FACTORY_TEST
+
+
+ -
+
+ android.permission.FLASHLIGHT
+
+
+ -
+
+ android.permission.FORCE_BACK
+
+
+ -
+
+ android.permission.GET_ACCOUNTS
+
+
+ -
+
+ android.permission.GET_PACKAGE_SIZE
+
+
+ -
+
+ android.permission.GET_TASKS
+
+
+ -
+
+ android.permission.GLOBAL_SEARCH
+
+
+ -
+
+ android.permission.HARDWARE_TEST
+
+
+ -
+
+ android.permission.INJECT_EVENTS
+
+
+ -
+
+ android.permission.INSTALL_LOCATION_PROVIDER
+
+
+ -
+
+ android.permission.INSTALL_PACKAGES
+
+
+ -
+
+ android.permission.INTERNAL_SYSTEM_WINDOW
+
+
+ -
+
+ android.permission.INTERNET
+
+
+ -
+
+ android.permission.KILL_BACKGROUND_PROCESSES
+
+
+ -
+
+ android.permission.MANAGE_ACCOUNTS
+
+
+ -
+
+ android.permission.MANAGE_APP_TOKENS
+
+
+ -
+
+ android.permission.MASTER_CLEAR
+
+
+ -
+
+ android.permission.MODIFY_AUDIO_SETTINGS
+
+
+ -
+
+ android.permission.MODIFY_PHONE_STATE
+
+
+ -
+
+ android.permission.MOUNT_FORMAT_FILESYSTEMS
+
+
+ -
+
+ android.permission.MOUNT_UNMOUNT_FILESYSTEMS
+
+
+ -
+
+ android.permission.NFC
+
+
+ -
+
+ android.permission.PERSISTENT_ACTIVITY
+
+
+ -
+
+ android.permission.PROCESS_OUTGOING_CALLS
+
+
+ -
+
+ android.permission.READ_CALENDAR
+
+
+ -
+
+ android.permission.READ_CONTACTS
+
+
+ -
+
+ android.permission.READ_FRAME_BUFFER
+
+
+ -
+
+ com.android.browser.permission.READ_HISTORY_BOOKMARKS
+
+
+ -
+
+ android.permission.READ_INPUT_STATE
+
+
+ -
+
+ android.permission.READ_LOGS
+
+
+ -
+
+ android.permission.READ_OWNER_DATA
+
+
+ -
+
+ android.permission.READ_PHONE_STATE
+
+
+ -
+
+ android.permission.READ_SMS
+
+
+ -
+
+ android.permission.READ_SYNC_SETTINGS
+
+
+ -
+
+ android.permission.READ_SYNC_STATS
+
+
+ -
+
+ android.permission.REBOOT
+
+
+ -
+
+ android.permission.RECEIVE_BOOT_COMPLETED
+
+
+ -
+
+ android.permission.RECEIVE_MMS
+
+
+ -
+
+ android.permission.RECEIVE_SMS
+
+
+ -
+
+ android.permission.RECEIVE_WAP_PUSH
+
+
+ -
+
+ android.permission.RECORD_AUDIO
+
+
+ -
+
+ android.permission.REORDER_TASKS
+
+
+ -
+
+ android.permission.RESTART_PACKAGES
+
+
+ -
+
+ android.permission.SEND_SMS
+
+
+ -
+
+ android.permission.SET_ACTIVITY_WATCHER
+
+
+ -
+
+ com.android.alarm.permission.SET_ALARM
+
+
+ -
+
+ android.permission.SET_ALWAYS_FINISH
+
+
+ -
+
+ android.permission.SET_ANIMATION_SCALE
+
+
+ -
+
+ android.permission.SET_DEBUG_APP
+
+
+ -
+
+ android.permission.SET_ORIENTATION
+
+
+ -
+
+ android.permission.SET_PREFERRED_APPLICATIONS
+
+
+ -
+
+ android.permission.SET_PROCESS_LIMIT
+
+
+ -
+
+ android.permission.SET_TIME
+
+
+ -
+
+ android.permission.SET_TIME_ZONE
+
+
+ -
+
+ android.permission.SET_WALLPAPER
+
+
+ -
+
+ android.permission.SET_WALLPAPER_HINTS
+
+
+ -
+
+ android.permission.SIGNAL_PERSISTENT_PROCESSES
+
+
+ -
+
+ android.permission.STATUS_BAR
+
+
+ -
+
+ android.permission.SUBSCRIBED_FEEDS_READ
+
+
+ -
+
+ android.permission.SUBSCRIBED_FEEDS_WRITE
+
+
+ -
+
+ android.permission.SYSTEM_ALERT_WINDOW
+
+
+ -
+
+ android.permission.UPDATE_DEVICE_STATS
+
+
+ -
+
+ android.permission.USE_CREDENTIALS
+
+
+ -
+
+ android.permission.USE_SIP
+
+
+ -
+
+ android.permission.VIBRATE
+
+
+ -
+
+ android.permission.WAKE_LOCK
+
+
+ -
+
+ android.permission.WRITE_APN_SETTINGS
+
+
+ -
+
+ android.permission.WRITE_CALENDAR
+
+
+ -
+
+ android.permission.WRITE_CONTACTS
+
+
+ -
+
+ android.permission.WRITE_EXTERNAL_STORAGE
+
+
+ -
+
+ android.permission.WRITE_GSERVICES
+
+
+ -
+
+ com.android.browser.permission.WRITE_HISTORY_BOOKMARKS
+
+
+ -
+
+ android.permission.WRITE_OWNER_DATA
+
+
+ -
+
+ android.permission.WRITE_SECURE_SETTINGS
+
+
+ -
+
+ android.permission.WRITE_SETTINGS
+
+
+ -
+
+ android.permission.WRITE_SMS
+
+
+ -
+
+ android.permission.WRITE_SYNC_SETTINGS
+
+
+
+
+
+
+
+
+
+
+ Libraries
+
+
+ -
+
+
+ Automatically check required Qt libraries from compiled application
+
+
+ Read information from application (must be compiled)
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ Required Qt libraries
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;">
+<tr>
+<td style="border: none;">
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Prebundled libraries</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Be aware, the order is very important: if library A depends on library B, B MUST be come before A!</p></td></tr></table></body></html>
+
+
+ true
+
+
+
+ -
+
+
+ -
+
+
-
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ false
+
+
+ Up
+
+
+
+ -
+
+
+ false
+
+
+ Down
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sign package
+
+
+ -
+
+
-
+
+
-
+
+
+ Keystore:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ Create
+
+
+
+ -
+
+
+ Browse
+
+
+
+
+
+ -
+
+
+ Sign package
+
+
+
+ -
+
+
+ Open package location after is complete
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ Certificate alias:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ signPackageCheckBox
+ toggled(bool)
+ certificatesAliasComboBox
+ setEnabled(bool)
+
+
+ 138
+ 93
+
+
+ 184
+ 139
+
+
+
+
+
+ addFile()
+ removeFile()
+ handleSkipButtonToggled(bool)
+ versionInfoChanged()
+ editDebianFile()
+ setPackageManagerIcon()
+
+
diff --git a/src/plugins/android/androidpackageinstallationfactory.cpp b/src/plugins/android/androidpackageinstallationfactory.cpp
new file mode 100644
index 00000000000..f6b9ff9fc71
--- /dev/null
+++ b/src/plugins/android/androidpackageinstallationfactory.cpp
@@ -0,0 +1,113 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidpackageinstallationfactory.h"
+
+#include "androidpackageinstallationstep.h"
+
+#include
+#include
+#include
+#include
+
+#include
+
+using namespace ProjectExplorer;
+
+namespace Android {
+namespace Internal {
+
+AndroidPackageInstallationFactory::AndroidPackageInstallationFactory(QObject *parent)
+ : IBuildStepFactory(parent)
+{
+}
+
+QStringList AndroidPackageInstallationFactory::availableCreationIds(BuildStepList *parent) const
+{
+ if (parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
+ && parent->target()->id() == QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID)
+ && !parent->contains(AndroidPackageInstallationStep::Id))
+ return QStringList() << AndroidPackageInstallationStep::Id;
+ return QStringList();
+}
+
+QString AndroidPackageInstallationFactory::displayNameForId(const QString &id) const
+{
+ if (id == AndroidPackageInstallationStep::Id)
+ return QCoreApplication::translate("Qt4ProjectManager::Internal::AndroidPackageInstallationFactory",
+ "Deploy to device");
+ return QString();
+}
+
+bool AndroidPackageInstallationFactory::canCreate(BuildStepList *parent, const QString &id) const
+{
+ return parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
+ && id == QLatin1String(AndroidPackageInstallationStep::Id)
+ && parent->target()->id() == QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID)
+ && !parent->contains(AndroidPackageInstallationStep::Id);
+}
+
+BuildStep *AndroidPackageInstallationFactory::create(BuildStepList *parent, const QString &id)
+{
+ Q_ASSERT(canCreate(parent, id));
+ return new AndroidPackageInstallationStep(parent);
+}
+
+bool AndroidPackageInstallationFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const
+{
+ return canCreate(parent, idFromMap(map));
+}
+
+BuildStep *AndroidPackageInstallationFactory::restore(BuildStepList *parent, const QVariantMap &map)
+{
+ Q_ASSERT(canRestore(parent, map));
+ AndroidPackageInstallationStep * const step = new AndroidPackageInstallationStep(parent);
+ if (!step->fromMap(map)) {
+ delete step;
+ return 0;
+ }
+ return step;
+}
+
+bool AndroidPackageInstallationFactory::canClone(BuildStepList *parent, BuildStep *product) const
+{
+ return canCreate(parent, product->id());
+}
+
+BuildStep *AndroidPackageInstallationFactory::clone(BuildStepList *parent, BuildStep *product)
+{
+ Q_ASSERT(canClone(parent, product));
+ return new AndroidPackageInstallationStep(parent, static_cast(product));
+}
+
+} // namespace Internal
+} // namespace Android
diff --git a/src/plugins/android/androidpackageinstallationfactory.h b/src/plugins/android/androidpackageinstallationfactory.h
new file mode 100644
index 00000000000..b6619f99e8a
--- /dev/null
+++ b/src/plugins/android/androidpackageinstallationfactory.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDPACKAGEINSTALLATIONFACTORY_H
+#define ANDROIDPACKAGEINSTALLATIONFACTORY_H
+#include
+
+namespace Android {
+namespace Internal {
+
+class AndroidPackageInstallationFactory: public ProjectExplorer::IBuildStepFactory
+{
+ Q_OBJECT
+public:
+ explicit AndroidPackageInstallationFactory(QObject *parent = 0);
+
+ virtual QStringList availableCreationIds(ProjectExplorer::BuildStepList *parent) const;
+ virtual QString displayNameForId(const QString &id) const;
+
+ virtual bool canCreate(ProjectExplorer::BuildStepList *parent,
+ const QString &id) const;
+ virtual ProjectExplorer::BuildStep *
+ create(ProjectExplorer::BuildStepList *parent, const QString &id);
+
+ virtual bool canRestore(ProjectExplorer::BuildStepList *parent,
+ const QVariantMap &map) const;
+ virtual ProjectExplorer::BuildStep *
+ restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map);
+
+ virtual bool canClone(ProjectExplorer::BuildStepList *parent,
+ ProjectExplorer::BuildStep *product) const;
+ virtual ProjectExplorer::BuildStep *
+ clone(ProjectExplorer::BuildStepList *parent,
+ ProjectExplorer::BuildStep *product);
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDPACKAGEINSTALLATIONFACTORY_H
diff --git a/src/plugins/android/androidpackageinstallationstep.cpp b/src/plugins/android/androidpackageinstallationstep.cpp
new file mode 100644
index 00000000000..d5b0cf19ee1
--- /dev/null
+++ b/src/plugins/android/androidpackageinstallationstep.cpp
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidpackageinstallationstep.h"
+#include "androidtarget.h"
+
+#include
+#include
+#include
+
+using namespace Android::Internal;
+
+const QLatin1String AndroidPackageInstallationStep::Id("Qt4ProjectManager.AndroidPackageInstallationStep");
+
+AndroidPackageInstallationStep::AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bsl) : MakeStep(bsl, Id)
+{
+ setDefaultDisplayName(tr("Copy application data"));
+ setDisplayName(tr("Copy application data"));
+}
+
+AndroidPackageInstallationStep::AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bc, AndroidPackageInstallationStep *other): MakeStep(bc, other)
+{
+ setDefaultDisplayName(tr("Copy application data"));
+ setDisplayName(tr("Copy application data"));
+}
+
+AndroidPackageInstallationStep::~AndroidPackageInstallationStep()
+{
+}
+
+bool AndroidPackageInstallationStep::init()
+{
+ AndroidTarget *androidTarget = qobject_cast(target());
+ if (!androidTarget) {
+ emit addOutput(tr("Current target is not an android target"), BuildStep::MessageOutput);
+ return false;
+ }
+
+ setUserArguments(QString::fromLatin1("INSTALL_ROOT=\"%1\" install").arg(QDir::toNativeSeparators(androidTarget->androidDirPath())));
+
+ return MakeStep::init();
+}
diff --git a/src/plugins/android/androidpackageinstallationstep.h b/src/plugins/android/androidpackageinstallationstep.h
new file mode 100644
index 00000000000..1fdf1486780
--- /dev/null
+++ b/src/plugins/android/androidpackageinstallationstep.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDPACKAGEINSTALLATIONSTEP_H
+#define ANDROIDPACKAGEINSTALLATIONSTEP_H
+
+#include
+
+namespace Android {
+namespace Internal {
+
+class AndroidPackageInstallationStep : public Qt4ProjectManager::MakeStep
+{
+ friend class AndroidPackageInstallationFactory;
+public:
+ explicit AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bsl);
+ virtual ~AndroidPackageInstallationStep();
+ virtual bool init();
+private:
+ AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bc,
+ AndroidPackageInstallationStep *other);
+
+private:
+ static const QLatin1String Id;
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDPACKAGEINSTALLATIONSTEP_H
diff --git a/src/plugins/android/androidplugin.cpp b/src/plugins/android/androidplugin.cpp
new file mode 100644
index 00000000000..6f27c8c8cff
--- /dev/null
+++ b/src/plugins/android/androidplugin.cpp
@@ -0,0 +1,86 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidplugin.h"
+
+#include "androidconstants.h"
+#include "androidconfigurations.h"
+#include "androiddeploystepfactory.h"
+#include "androidconfigurations.h"
+#include "androidpackagecreationfactory.h"
+#include "androidpackageinstallationfactory.h"
+#include "androidrunfactories.h"
+#include "androidsettingspage.h"
+#include "androidtoolchain.h"
+#include "androidqtversionfactory.h"
+#include "androidtargetfactory.h"
+#include "androiddeployconfiguration.h"
+
+#include
+
+using namespace Android;
+using namespace Android::Internal;
+
+AndroidPlugin::AndroidPlugin()
+{
+}
+
+AndroidPlugin::~AndroidPlugin()
+{
+}
+
+bool AndroidPlugin::initialize(const QStringList &arguments,
+ QString *error_message)
+{
+ Q_UNUSED(arguments)
+ Q_UNUSED(error_message)
+
+ AndroidConfigurations::instance(this);
+
+ addAutoReleasedObject(new AndroidRunControlFactory);
+ addAutoReleasedObject(new AndroidRunConfigurationFactory);
+ addAutoReleasedObject(new AndroidPackageInstallationFactory);
+ addAutoReleasedObject(new AndroidPackageCreationFactory);
+ addAutoReleasedObject(new AndroidDeployStepFactory);
+ addAutoReleasedObject(new AndroidSettingsPage);
+ addAutoReleasedObject(new AndroidTargetFactory);
+ addAutoReleasedObject(new AndroidQtVersionFactory);
+ addAutoReleasedObject(new AndroidToolChainFactory);
+ addAutoReleasedObject(new AndroidDeployConfigurationFactory);
+ return true;
+}
+
+void AndroidPlugin::extensionsInitialized()
+{
+}
+
+Q_EXPORT_PLUGIN(Android::AndroidPlugin)
diff --git a/src/plugins/android/androidplugin.h b/src/plugins/android/androidplugin.h
new file mode 100644
index 00000000000..c8ad7c4a9cf
--- /dev/null
+++ b/src/plugins/android/androidplugin.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDMANAGER_H
+#define ANDROIDMANAGER_H
+
+#include
+
+namespace Android {
+
+class AndroidPlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+
+public:
+ AndroidPlugin();
+ ~AndroidPlugin();
+
+ bool initialize(const QStringList &arguments, QString *error_message);
+ void extensionsInitialized();
+
+};
+} // namespace Qt4ProjectManager
+
+#endif // ANDROIDMANAGER_H
diff --git a/src/plugins/android/androidqtversion.cpp b/src/plugins/android/androidqtversion.cpp
new file mode 100644
index 00000000000..aeae9afeee8
--- /dev/null
+++ b/src/plugins/android/androidqtversion.cpp
@@ -0,0 +1,123 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidqtversion.h"
+#include "androidconstants.h"
+#include "qt4projectmanager/qt4projectmanagerconstants.h"
+
+#include
+
+#include
+
+using namespace Android::Internal;
+
+AndroidQtVersion::AndroidQtVersion()
+ : QtSupport::BaseQtVersion()
+{
+
+}
+
+AndroidQtVersion::AndroidQtVersion(const Utils::FileName &path, bool isAutodetected, const QString &autodetectionSource)
+ : QtSupport::BaseQtVersion(path, isAutodetected, autodetectionSource)
+{
+}
+
+AndroidQtVersion::~AndroidQtVersion()
+{
+
+}
+
+AndroidQtVersion *AndroidQtVersion::clone() const
+{
+ return new AndroidQtVersion(*this);
+}
+
+QString AndroidQtVersion::type() const
+{
+ return QLatin1String(Constants::ANDROIDQT);
+}
+
+bool AndroidQtVersion::isValid() const
+{
+ if (!BaseQtVersion::isValid())
+ return false;
+ if (qtAbis().isEmpty())
+ return false;
+ return true;
+}
+
+QString AndroidQtVersion::invalidReason() const
+{
+ QString tmp = BaseQtVersion::invalidReason();
+ if (tmp.isEmpty() && qtAbis().isEmpty())
+ return QCoreApplication::translate("QtVersion", "Failed to detect the ABI(s) used by the Qt version.");
+ return tmp;
+}
+
+QList AndroidQtVersion::detectQtAbis() const
+{
+ return QList() << ProjectExplorer::Abi(ProjectExplorer::Abi::ArmArchitecture, ProjectExplorer::Abi::LinuxOS,
+ ProjectExplorer::Abi::AndroidLinuxFlavor, ProjectExplorer::Abi::ElfFormat,
+ 32);
+}
+
+bool AndroidQtVersion::supportsTargetId(const QString &id) const
+{
+ return id == QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID);
+}
+
+QSet AndroidQtVersion::supportedTargetIds() const
+{
+ return QSet() << QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID);
+}
+
+QString AndroidQtVersion::description() const
+{
+ return QCoreApplication::translate("QtVersion", "Android", "Qt Version is meant for Android");
+}
+
+Core::FeatureSet AndroidQtVersion::availableFeatures() const
+{
+ Core::FeatureSet features = QtSupport::BaseQtVersion::availableFeatures();
+ features |= Core::FeatureSet(QtSupport::Constants::FEATURE_MOBILE);
+ return features;
+}
+
+QString AndroidQtVersion::platformName() const
+{
+ return QLatin1String(Constants::ANDROID_PLATFORM);
+}
+
+QString AndroidQtVersion::platformDisplayName() const
+{
+ return QLatin1String(Constants::ANDROID_PLATFORM_TR);
+}
diff --git a/src/plugins/android/androidqtversion.h b/src/plugins/android/androidqtversion.h
new file mode 100644
index 00000000000..b57432cb0bd
--- /dev/null
+++ b/src/plugins/android/androidqtversion.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDQTVERSION_H
+#define ANDROIDQTVERSION_H
+#include
+
+namespace Android {
+namespace Internal {
+
+class AndroidQtVersion : public QtSupport::BaseQtVersion
+{
+public:
+ AndroidQtVersion();
+ AndroidQtVersion(const Utils::FileName &path, bool isAutodetected = false, const QString &autodetectionSource = QString());
+ ~AndroidQtVersion ();
+ AndroidQtVersion *clone() const;
+
+ virtual QString type() const;
+
+ virtual bool isValid() const;
+ virtual QString invalidReason() const;
+
+ virtual QList detectQtAbis() const;
+
+ virtual bool supportsTargetId(const QString &id) const;
+ virtual QSet supportedTargetIds() const;
+
+ virtual Core::FeatureSet availableFeatures() const;
+ virtual QString platformName() const;
+ virtual QString platformDisplayName() const;
+
+ QString description() const;
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDQTVERSION_H
diff --git a/src/plugins/android/androidqtversionfactory.cpp b/src/plugins/android/androidqtversionfactory.cpp
new file mode 100644
index 00000000000..2f133c03041
--- /dev/null
+++ b/src/plugins/android/androidqtversionfactory.cpp
@@ -0,0 +1,86 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidqtversionfactory.h"
+#include "androidqtversion.h"
+#include "androidconstants.h"
+#include
+#include
+#include
+
+#include
+
+namespace Android {
+namespace Internal {
+
+AndroidQtVersionFactory::AndroidQtVersionFactory(QObject *parent)
+ : QtSupport::QtVersionFactory(parent)
+{
+
+}
+
+AndroidQtVersionFactory::~AndroidQtVersionFactory()
+{
+
+}
+
+bool AndroidQtVersionFactory::canRestore(const QString &type)
+{
+ return type == QLatin1String(Constants::ANDROIDQT);
+}
+
+QtSupport::BaseQtVersion *AndroidQtVersionFactory::restore(const QString &type,
+ const QVariantMap &data)
+{
+ QTC_ASSERT(canRestore(type), return 0);
+ AndroidQtVersion *v = new AndroidQtVersion;
+ v->fromMap(data);
+ return v;
+}
+
+int AndroidQtVersionFactory::priority() const
+{
+ return 90;
+}
+
+QtSupport::BaseQtVersion *AndroidQtVersionFactory::create(const Utils::FileName &qmakePath, ProFileEvaluator *evaluator, bool isAutoDetected, const QString &autoDetectionSource)
+{
+ QFileInfo fi(qmakePath.toString());
+ if (!fi.exists() || !fi.isExecutable() || !fi.isFile())
+ return 0;
+ if (!evaluator->values(QLatin1String("CONFIG")).contains(QLatin1String("android")))
+ return 0;
+ return new AndroidQtVersion(qmakePath, isAutoDetected, autoDetectionSource);
+}
+
+} // Internal
+} // Android
diff --git a/src/plugins/android/androidqtversionfactory.h b/src/plugins/android/androidqtversionfactory.h
new file mode 100644
index 00000000000..b1aa94b1e9f
--- /dev/null
+++ b/src/plugins/android/androidqtversionfactory.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDQTVERSIONFACTORY_H
+#define ANDROIDQTVERSIONFACTORY_H
+#include
+
+namespace Android {
+namespace Internal {
+
+class AndroidQtVersionFactory : public QtSupport::QtVersionFactory
+{
+public:
+ explicit AndroidQtVersionFactory(QObject *parent = 0);
+ ~AndroidQtVersionFactory();
+
+ virtual bool canRestore(const QString &type);
+ virtual QtSupport::BaseQtVersion *restore(const QString &type, const QVariantMap &data);
+
+ virtual int priority() const;
+ virtual QtSupport::BaseQtVersion *create(const Utils::FileName &qmakePath, ProFileEvaluator *evaluator,
+ bool isAutoDetected = false, const QString &autoDetectionSource = QString());
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDQTVERSIONFACTORY_H
diff --git a/src/plugins/android/androidrunconfiguration.cpp b/src/plugins/android/androidrunconfiguration.cpp
new file mode 100644
index 00000000000..370725381ba
--- /dev/null
+++ b/src/plugins/android/androidrunconfiguration.cpp
@@ -0,0 +1,147 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidrunconfiguration.h"
+#include "androiddeploystep.h"
+#include "androidglobal.h"
+#include "androidtoolchain.h"
+#include "androidtarget.h"
+
+#include
+#include
+
+#include
+
+#include
+
+using namespace Qt4ProjectManager;
+
+namespace Android {
+namespace Internal {
+
+using namespace ProjectExplorer;
+
+AndroidRunConfiguration::AndroidRunConfiguration(AndroidTarget *parent,
+ const QString &proFilePath)
+ : RunConfiguration(parent, QLatin1String(ANDROID_RC_ID))
+ , m_proFilePath(proFilePath)
+{
+ init();
+}
+
+AndroidRunConfiguration::AndroidRunConfiguration(AndroidTarget *parent,
+ AndroidRunConfiguration *source)
+ : RunConfiguration(parent, source)
+ , m_proFilePath(source->m_proFilePath)
+{
+ init();
+}
+
+void AndroidRunConfiguration::init()
+{
+ setDefaultDisplayName(defaultDisplayName());
+}
+
+AndroidRunConfiguration::~AndroidRunConfiguration()
+{
+}
+
+AndroidTarget *AndroidRunConfiguration::androidTarget() const
+{
+ return static_cast(target());
+}
+
+Qt4BuildConfiguration *AndroidRunConfiguration::activeQt4BuildConfiguration() const
+{
+ return static_cast(activeBuildConfiguration());
+}
+
+QWidget *AndroidRunConfiguration::createConfigurationWidget()
+{
+ return 0;// no special running configurations
+}
+
+Utils::OutputFormatter *AndroidRunConfiguration::createOutputFormatter() const
+{
+ return new QtSupport::QtOutputFormatter(androidTarget()->qt4Project());
+}
+
+QString AndroidRunConfiguration::defaultDisplayName()
+{
+ return tr("Run on Android device");
+}
+
+AndroidConfig AndroidRunConfiguration::config() const
+{
+ return AndroidConfigurations::instance().config();
+}
+
+const QString AndroidRunConfiguration::gdbCmd() const
+{
+ return AndroidConfigurations::instance().gdbPath(activeQt4BuildConfiguration()->toolChain()->targetAbi().architecture());
+}
+
+AndroidDeployStep *AndroidRunConfiguration::deployStep() const
+{
+ AndroidDeployStep * const step
+ = AndroidGlobal::buildStep(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");
+}
+
+const QString AndroidRunConfiguration::dumperLib() const
+{
+ Qt4BuildConfiguration *qt4bc(activeQt4BuildConfiguration());
+ return qt4bc->qtVersion()->gdbDebuggingHelperLibrary();
+}
+
+QString AndroidRunConfiguration::proFilePath() const
+{
+ return m_proFilePath;
+}
+
+AndroidRunConfiguration::DebuggingType AndroidRunConfiguration::debuggingType() const
+{
+ return DebugCppAndQml;
+}
+
+
+
+} // namespace Internal
+} // namespace Android
diff --git a/src/plugins/android/androidrunconfiguration.h b/src/plugins/android/androidrunconfiguration.h
new file mode 100644
index 00000000000..1e34fac4577
--- /dev/null
+++ b/src/plugins/android/androidrunconfiguration.h
@@ -0,0 +1,108 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDRUNCONFIGURATION_H
+#define ANDROIDRUNCONFIGURATION_H
+
+#include "androidconstants.h"
+#include "androidconfigurations.h"
+
+#include
+
+#include
+
+QT_FORWARD_DECLARE_CLASS(QWidget)
+
+namespace Qt4ProjectManager {
+
+class Qt4BuildConfiguration;
+class Qt4Project;
+class Qt4ProFileNode;
+}
+
+namespace Android {
+namespace Internal {
+
+class AndroidDeviceConfigListModel;
+class AndroidDeployStep;
+class AndroidRunConfigurationFactory;
+class AndroidToolChain;
+class AndroidTarget;
+
+class AndroidRunConfiguration : public ProjectExplorer::RunConfiguration
+{
+ Q_OBJECT
+ friend class AndroidRunConfigurationFactory;
+
+public:
+ enum BaseEnvironmentBase {
+ CleanEnvironmentBase = 0,
+ SystemEnvironmentBase = 1
+ };
+
+ enum DebuggingType { DebugCppOnly, DebugQmlOnly, DebugCppAndQml };
+
+ AndroidRunConfiguration(AndroidTarget *parent, const QString &proFilePath);
+ virtual ~AndroidRunConfiguration();
+
+ QWidget *createConfigurationWidget();
+ Utils::OutputFormatter *createOutputFormatter() const;
+ AndroidTarget *androidTarget() const;
+ Qt4ProjectManager::Qt4BuildConfiguration *activeQt4BuildConfiguration() const;
+
+ AndroidDeployStep *deployStep() const;
+
+ void setArguments(const QString &args);
+ AndroidConfig config() const;
+ QString proFilePath() const;
+
+ DebuggingType debuggingType() const;
+
+ const QString gdbCmd() const;
+ const QString remoteChannel() const;
+ const QString dumperLib() const;
+
+protected:
+ AndroidRunConfiguration(AndroidTarget *parent, AndroidRunConfiguration *source);
+ QString defaultDisplayName();
+
+private:
+ void init();
+
+ QString m_proFilePath;
+
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDRUNCONFIGURATION_H
diff --git a/src/plugins/android/androidruncontrol.cpp b/src/plugins/android/androidruncontrol.cpp
new file mode 100644
index 00000000000..ad8dbe5d7bb
--- /dev/null
+++ b/src/plugins/android/androidruncontrol.cpp
@@ -0,0 +1,119 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidruncontrol.h"
+
+#include "androiddeploystep.h"
+#include "androidglobal.h"
+#include "androidrunconfiguration.h"
+#include "androidrunner.h"
+
+#include
+#include
+
+#include
+
+namespace Android {
+namespace Internal {
+
+using ProjectExplorer::RunConfiguration;
+using namespace ProjectExplorer;
+
+AndroidRunControl::AndroidRunControl(AndroidRunConfiguration *rc)
+ : RunControl(rc, ProjectExplorer::NormalRunMode)
+ , m_runner(new AndroidRunner(this, rc, false))
+ , m_running(false)
+{
+}
+
+AndroidRunControl::~AndroidRunControl()
+{
+ stop();
+}
+
+void AndroidRunControl::start()
+{
+ m_running = true;
+ emit started();
+ disconnect(m_runner, 0, this, 0);
+
+ connect(m_runner, SIGNAL(remoteErrorOutput(QByteArray)),
+ SLOT(handleRemoteErrorOutput(QByteArray)));
+ connect(m_runner, SIGNAL(remoteOutput(QByteArray)),
+ SLOT(handleRemoteOutput(QByteArray)));
+ connect(m_runner, SIGNAL(remoteProcessFinished(const QString &)),
+ SLOT(handleRemoteProcessFinished(const QString &)));
+ appendMessage(tr("Starting remote process ..."), Utils::NormalMessageFormat);
+ m_runner->start();
+}
+
+ProjectExplorer::RunControl::StopResult AndroidRunControl::stop()
+{
+ m_runner->stop();
+ return StoppedSynchronously;
+}
+
+void AndroidRunControl::handleRemoteProcessFinished(const QString &error)
+{
+ appendMessage(error, Utils::ErrorMessageFormat);
+ disconnect(m_runner, 0, this, 0);
+ m_running = false;
+ emit finished();
+}
+
+void AndroidRunControl::handleRemoteOutput(const QByteArray &output)
+{
+ appendMessage(QString::fromUtf8(output), Utils::StdOutFormatSameLine);
+}
+
+void AndroidRunControl::handleRemoteErrorOutput(const QByteArray &output)
+{
+ appendMessage(QString::fromUtf8(output), Utils::StdErrFormatSameLine);
+}
+
+bool AndroidRunControl::isRunning() const
+{
+ return m_running;
+}
+
+QString AndroidRunControl::displayName() const
+{
+ return m_runner->displayName();
+}
+
+QIcon AndroidRunControl::icon() const
+{
+ return QIcon(QLatin1String(ProjectExplorer::Constants::ICON_DEBUG_SMALL));
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/android/androidruncontrol.h b/src/plugins/android/androidruncontrol.h
new file mode 100644
index 00000000000..7e5df82a9c7
--- /dev/null
+++ b/src/plugins/android/androidruncontrol.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDRUNCONTROL_H
+#define ANDROIDRUNCONTROL_H
+
+#include
+
+#include
+
+namespace Android {
+namespace Internal {
+class AndroidRunConfiguration;
+class AndroidRunner;
+
+class AndroidRunControl : public ProjectExplorer::RunControl
+{
+ Q_OBJECT
+public:
+ explicit AndroidRunControl(AndroidRunConfiguration *runConfig);
+ virtual ~AndroidRunControl();
+
+ virtual void start();
+ virtual StopResult stop();
+ virtual bool isRunning() const;
+ virtual QString displayName() const;
+ virtual QIcon icon() const;
+
+private slots:
+ void handleRemoteProcessFinished(const QString &error);
+ void handleRemoteOutput(const QByteArray &output);
+ void handleRemoteErrorOutput(const QByteArray &output);
+
+private:
+
+ AndroidRunner * const m_runner;
+ bool m_running;
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDRUNCONTROL_H
diff --git a/src/plugins/android/androidrunfactories.cpp b/src/plugins/android/androidrunfactories.cpp
new file mode 100644
index 00000000000..253e6559b88
--- /dev/null
+++ b/src/plugins/android/androidrunfactories.cpp
@@ -0,0 +1,198 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidrunfactories.h"
+
+#include "androidconstants.h"
+#include "androiddebugsupport.h"
+#include "androidrunconfiguration.h"
+#include "androidruncontrol.h"
+#include "androidtarget.h"
+
+#include
+#include
+#include
+#include
+#include
+
+
+namespace Android {
+namespace Internal {
+
+using namespace ProjectExplorer;
+using namespace Qt4ProjectManager;
+
+namespace {
+
+QString pathFromId(const QString &id)
+{
+ if (!id.startsWith(ANDROID_RC_ID_PREFIX))
+ return QString();
+ return id.mid(QString(ANDROID_RC_ID_PREFIX).size());
+}
+
+} // namespace
+
+AndroidRunConfigurationFactory::AndroidRunConfigurationFactory(QObject *parent)
+ : IRunConfigurationFactory(parent)
+{
+}
+
+AndroidRunConfigurationFactory::~AndroidRunConfigurationFactory()
+{
+}
+
+bool AndroidRunConfigurationFactory::canCreate(Target *parent,
+ const QString &/*id*/) const
+{
+ AndroidTarget *target = qobject_cast(parent);
+ if (!target
+ || target->id() != QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID)) {
+ return false;
+ }
+ return true;
+}
+
+bool AndroidRunConfigurationFactory::canRestore(Target *parent,
+ const QVariantMap &map) const
+{
+ Q_UNUSED(parent)
+ Q_UNUSED(map)
+ if (!qobject_cast(parent))
+ return false;
+ return ProjectExplorer::idFromMap(map)
+ .startsWith(QLatin1String(ANDROID_RC_ID));
+}
+
+bool AndroidRunConfigurationFactory::canClone(Target *parent,
+ RunConfiguration *source) const
+{
+ return canCreate(parent, source->id());
+}
+
+QStringList AndroidRunConfigurationFactory::availableCreationIds(Target *parent) const
+{
+ QStringList ids;
+ if (AndroidTarget *t = qobject_cast(parent)) {
+ if (t->id() == QLatin1String(Qt4ProjectManager::Constants::ANDROID_DEVICE_TARGET_ID)) {
+ QList nodes = t->qt4Project()->allProFiles();
+ foreach (Qt4ProFileNode *node, nodes)
+ if (node->projectType() == ApplicationTemplate || node->projectType() == LibraryTemplate)
+ ids << node->targetInformation().target;
+ }
+ }
+ return ids;
+}
+
+QString AndroidRunConfigurationFactory::displayNameForId(const QString &id) const
+{
+ return QFileInfo(pathFromId(id)).completeBaseName();
+}
+
+RunConfiguration *AndroidRunConfigurationFactory::create(Target *parent,
+ const QString &id)
+{
+ if (!canCreate(parent, id))
+ return 0;
+ AndroidTarget *pqt4parent = static_cast(parent);
+ return new AndroidRunConfiguration(pqt4parent, pathFromId(id));
+
+}
+
+RunConfiguration *AndroidRunConfigurationFactory::restore(Target *parent,
+ const QVariantMap &map)
+{
+ if (!canRestore(parent, map))
+ return 0;
+ AndroidTarget *target = static_cast(parent);
+ AndroidRunConfiguration *rc = new AndroidRunConfiguration(target, QString());
+ if (rc->fromMap(map))
+ return rc;
+
+ delete rc;
+ return 0;
+}
+
+RunConfiguration *AndroidRunConfigurationFactory::clone(Target *parent,
+ RunConfiguration *source)
+{
+ if (!canClone(parent, source))
+ return 0;
+
+ AndroidRunConfiguration *old = static_cast(source);
+ return new AndroidRunConfiguration(static_cast(parent), old);
+}
+
+// #pragma mark -- AndroidRunControlFactory
+
+AndroidRunControlFactory::AndroidRunControlFactory(QObject *parent)
+ : IRunControlFactory(parent)
+{
+}
+
+AndroidRunControlFactory::~AndroidRunControlFactory()
+{
+}
+
+bool AndroidRunControlFactory::canRun(RunConfiguration *runConfiguration,
+ ProjectExplorer::RunMode mode) const
+{
+ if (mode != NormalRunMode && mode != DebugRunMode)
+ return false;
+ return qobject_cast(runConfiguration);
+}
+
+RunControl *AndroidRunControlFactory::create(RunConfiguration *runConfig,
+ ProjectExplorer::RunMode mode)
+{
+ Q_ASSERT(canRun(runConfig, mode));
+ AndroidRunConfiguration *rc = qobject_cast(runConfig);
+ Q_ASSERT(rc);
+ if (mode == NormalRunMode)
+ return new AndroidRunControl(rc);
+ else
+ return AndroidDebugSupport::createDebugRunControl(rc);
+}
+
+QString AndroidRunControlFactory::displayName() const
+{
+ return tr("Run on Android device/emulator");
+}
+
+RunConfigWidget *AndroidRunControlFactory::createConfigurationWidget(RunConfiguration *config)
+{
+ Q_UNUSED(config)
+ return 0;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/android/androidrunfactories.h b/src/plugins/android/androidrunfactories.h
new file mode 100644
index 00000000000..d9d0f1c6b42
--- /dev/null
+++ b/src/plugins/android/androidrunfactories.h
@@ -0,0 +1,94 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDRUNFACTORIES_H
+#define ANDROIDRUNFACTORIES_H
+
+#include
+
+namespace ProjectExplorer {
+ class RunConfiguration;
+ class RunControl;
+ class RunConfigWidget;
+ class Target;
+}
+using ProjectExplorer::IRunConfigurationFactory;
+using ProjectExplorer::IRunControlFactory;
+using ProjectExplorer::RunConfiguration;
+using ProjectExplorer::RunControl;
+using ProjectExplorer::RunConfigWidget;
+using ProjectExplorer::Target;
+
+namespace Android {
+namespace Internal {
+
+class AndroidRunConfigurationFactory : public IRunConfigurationFactory
+{
+ Q_OBJECT
+
+public:
+ explicit AndroidRunConfigurationFactory(QObject *parent = 0);
+ ~AndroidRunConfigurationFactory();
+
+ QString displayNameForId(const QString &id) const;
+ QStringList availableCreationIds(Target *parent) const;
+
+ bool canCreate(Target *parent, const QString &id) const;
+ RunConfiguration *create(Target *parent, const QString &id);
+
+ bool canRestore(Target *parent, const QVariantMap &map) const;
+ RunConfiguration *restore(Target *parent, const QVariantMap &map);
+
+ bool canClone(Target *parent, RunConfiguration *source) const;
+ RunConfiguration *clone(Target *parent, RunConfiguration *source);
+};
+
+class AndroidRunControlFactory : public IRunControlFactory
+{
+ Q_OBJECT
+public:
+ explicit AndroidRunControlFactory(QObject *parent = 0);
+ ~AndroidRunControlFactory();
+
+ QString displayName() const;
+ RunConfigWidget *createConfigurationWidget(RunConfiguration *runConfiguration);
+
+ bool canRun(RunConfiguration *runConfiguration,
+ ProjectExplorer::RunMode mode) const;
+ RunControl *create(RunConfiguration *runConfiguration,
+ ProjectExplorer::RunMode mode);
+};
+
+} // namespace Internal
+} // namespace Android
+
+#endif // ANDROIDRUNFACTORIES_H
diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp
new file mode 100644
index 00000000000..4b30bee1783
--- /dev/null
+++ b/src/plugins/android/androidrunner.cpp
@@ -0,0 +1,281 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "androidrunner.h"
+
+#include "androiddeploystep.h"
+#include "androidconfigurations.h"
+#include "androidglobal.h"
+#include "androidrunconfiguration.h"
+#include "androidtarget.h"
+
+#include
+#include
+
+namespace Android {
+namespace Internal {
+
+AndroidRunner::AndroidRunner(QObject *parent,
+ AndroidRunConfiguration *runConfig, bool debugging)
+ : QThread(parent)
+{
+ m_remoteChannel = runConfig->remoteChannel();
+ AndroidTarget * at = runConfig->androidTarget();
+ AndroidDeployStep * ds = runConfig->deployStep();
+ if ((m_useLocalQtLibs = ds->useLocalQtLibs())) {
+ m_localLibs = at->loadLocalLibs(ds->deviceAPILevel());
+ m_localJars = at->loadLocalJars(ds->deviceAPILevel());
+ }
+ m_intentName = at->intentName();
+ m_debugingMode = debugging;
+ m_packageName = m_intentName.left(m_intentName.indexOf(QLatin1Char('/')));
+ m_deviceSerialNumber = ds->deviceSerialNumber();
+ m_processPID = -1;
+ m_gdbserverPID = -1;
+ connect(&m_checkPIDTimer, SIGNAL(timeout()), SLOT(checkPID()));
+ connect(&m_adbLogcatProcess, SIGNAL(readyReadStandardOutput()), SLOT(logcatReadStandardOutput()));
+ connect(&m_adbLogcatProcess, SIGNAL(readyReadStandardError()) , SLOT(logcatReadStandardError()));
+}
+
+AndroidRunner::~AndroidRunner()
+{
+ stop();
+}
+
+void AndroidRunner::checkPID()
+{
+ QProcess psProc;
+ psProc.start(AndroidConfigurations::instance().adbToolPath(),
+ QStringList() << QLatin1String("-s") << m_deviceSerialNumber
+ << QLatin1String("shell") << QLatin1String("ps"));
+ if (!psProc.waitForFinished(-1)) {
+ psProc.terminate();
+ return;
+ }
+ qint64 pid = -1;
+ QList procs = psProc.readAll().split('\n');
+ foreach (const QByteArray &proc, procs) {
+ if (proc.trimmed().endsWith(m_packageName.toAscii())) {
+ QRegExp rx(QLatin1String("(\\d+)"));
+ if (rx.indexIn(QLatin1String(proc), proc.indexOf(' ')) > 0) {
+ pid = rx.cap(1).toLongLong();
+ break;
+ }
+ }
+ }
+
+ if (-1 != m_processPID && pid == -1) {
+ m_processPID = -1;
+ emit remoteProcessFinished(tr("\n\n'%1' died").arg(m_packageName));
+ return;
+ }
+ m_processPID = pid;
+ if (!m_debugingMode)
+ return;
+
+ m_gdbserverPID = -1;
+ foreach (const QByteArray &proc, procs) {
+ if (proc.trimmed().endsWith("gdbserver")) {
+ QRegExp rx(QLatin1String("(\\d+)"));
+ if (rx.indexIn(QLatin1String(proc), proc.indexOf(' ')) > 0) {
+ m_gdbserverPID = rx.cap(1).toLongLong();
+ break;
+ }
+ }
+ }
+}
+
+void AndroidRunner::killPID()
+{
+ checkPID(); //updates m_processPID and m_gdbserverPID
+ for (int tries = 0; tries < 10 && (m_processPID != -1 || m_gdbserverPID != -1); ++tries) {
+ if (m_processPID != -1) {
+ adbKill(m_processPID, m_deviceSerialNumber, 2000);
+ adbKill(m_processPID, m_deviceSerialNumber, 2000, m_packageName);
+ }
+
+ if (m_gdbserverPID != -1) {
+ adbKill(m_gdbserverPID, m_deviceSerialNumber, 2000);
+ adbKill(m_gdbserverPID, m_deviceSerialNumber, 2000, m_packageName);
+ }
+ checkPID();
+ }
+}
+
+void AndroidRunner::start()
+{
+ QtConcurrent::run(this,&AndroidRunner::asyncStart);
+}
+
+void AndroidRunner::asyncStart()
+{
+ QMutexLocker locker(&m_mutex);
+ m_processPID = -1;
+ killPID(); // kill any process with this name
+ QString extraParams;
+ QProcess adbStarProc;
+ if (m_debugingMode) {
+ QStringList arguments;
+ arguments << QLatin1String("-s") << m_deviceSerialNumber
+ << QLatin1String("forward") << QString::fromLatin1("tcp%1").arg(m_remoteChannel)
+ << QString::fromLatin1("localfilesystem:/data/data/%1/debug-socket").arg(m_packageName);
+ adbStarProc.start(AndroidConfigurations::instance().adbToolPath(), arguments);
+ if (!adbStarProc.waitForStarted()) {
+ emit remoteProcessFinished(tr("Failed to forward debugging ports. Reason: $1").arg(adbStarProc.errorString()));
+ return;
+ }
+ if (!adbStarProc.waitForFinished(-1)) {
+ emit remoteProcessFinished(tr("Failed to forward debugging ports"));
+ return;
+ }
+ extraParams = QLatin1String("-e native_debug true -e gdbserver_socket +debug-socket");
+ }
+
+ if (m_useLocalQtLibs) {
+ extraParams += QLatin1String(" -e use_local_qt_libs true");
+ extraParams += QLatin1String(" -e libs_prefix /data/local/qt/");
+ extraParams += QLatin1String(" -e load_local_libs ") + m_localLibs;
+ extraParams += QLatin1String(" -e load_local_jars ") + m_localJars;
+ }
+
+ extraParams = extraParams.trimmed();
+ QStringList arguments;
+ arguments << QLatin1String("-s") << m_deviceSerialNumber
+ << QLatin1String("shell") << QLatin1String("am")
+ << QLatin1String("start") << QLatin1String("-n") << m_intentName;
+
+ if (extraParams.length())
+ arguments << extraParams.split(QLatin1Char(' '));
+
+ adbStarProc.start(AndroidConfigurations::instance().adbToolPath(), arguments);
+ if (!adbStarProc.waitForStarted()) {
+ emit remoteProcessFinished(tr("Failed to start the activity. Reason: $1").arg(adbStarProc.errorString()));
+ return;
+ }
+ if (!adbStarProc.waitForFinished(-1)) {
+ adbStarProc.terminate();
+ emit remoteProcessFinished(tr("Unable to start '%1'").arg(m_packageName));
+ return;
+ }
+ QTime startTime = QTime::currentTime();
+ while (m_processPID == -1 && startTime.secsTo(QTime::currentTime()) < 10) { // wait up to 10 seconds for application to start
+ checkPID();
+ }
+ if (m_processPID == -1) {
+ emit remoteProcessFinished(tr("Can't find %1 process").arg(m_packageName));
+ return;
+ }
+
+ if (m_debugingMode) {
+ startTime = QTime::currentTime();
+ while (m_gdbserverPID == -1 && startTime.secsTo(QTime::currentTime()) < 25) { // wait up to 25 seconds to connect
+ checkPID();
+ }
+ msleep(200); // give gdbserver more time to start
+ }
+
+ QMetaObject::invokeMethod(this, "startLogcat", Qt::QueuedConnection);
+}
+
+void AndroidRunner::startLogcat()
+{
+ m_checkPIDTimer.start(1000); // check if the application is alive every 1 seconds
+ m_adbLogcatProcess.start(AndroidConfigurations::instance().adbToolPath(),
+ QStringList() << QLatin1String("-s") << m_deviceSerialNumber
+ << QLatin1String("logcat"));
+ emit remoteProcessStarted(5039);
+}
+
+void AndroidRunner::stop()
+{
+ QMutexLocker locker(&m_mutex);
+ m_adbLogcatProcess.terminate();
+ m_adbLogcatProcess.waitForFinished(-1);
+ m_checkPIDTimer.stop();
+ if (m_processPID == -1)
+ return; // don't emit another signal
+ QtConcurrent::run(this, &AndroidRunner::asyncStop);
+}
+void AndroidRunner::asyncStop()
+{
+ killPID();
+ emit remoteProcessFinished(tr("\n\n'%1' killed").arg(m_packageName));
+}
+
+void AndroidRunner::logcatReadStandardError()
+{
+ emit remoteErrorOutput(m_adbLogcatProcess.readAllStandardError());
+}
+
+void AndroidRunner::logcatReadStandardOutput()
+{
+ m_logcat += m_adbLogcatProcess.readAllStandardOutput();
+ bool keepLastLine = m_logcat.endsWith('\n');
+ QByteArray line;
+ QByteArray pid(QString::fromLatin1("%1):").arg(m_processPID).toAscii());
+ foreach (line, m_logcat.split('\n')) {
+ if (!line.contains(pid))
+ continue;
+ if (line.startsWith("E/"))
+ emit remoteErrorOutput(line);
+ else
+ emit remoteOutput(line);
+
+ }
+ if (keepLastLine)
+ m_logcat = line;
+}
+
+void AndroidRunner::adbKill(qint64 pid, const QString &device, int timeout, const QString &runAsPackageName)
+{
+ QProcess process;
+ QStringList arguments;
+
+ arguments << QLatin1String("-s") << device;
+ arguments << QLatin1String("shell");
+ if (runAsPackageName.size())
+ arguments << QLatin1String("run-as") << runAsPackageName;
+ arguments << QLatin1String("kill") << QLatin1String("-9");
+ arguments << QString::number(pid);
+
+ process.start(AndroidConfigurations::instance().adbToolPath(), arguments);
+ if (!process.waitForFinished(timeout))
+ process.terminate();
+}
+
+QString AndroidRunner::displayName() const
+{
+ return m_packageName;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/android/androidrunner.h b/src/plugins/android/androidrunner.h
new file mode 100644
index 00000000000..0e2cd4b9f9f
--- /dev/null
+++ b/src/plugins/android/androidrunner.h
@@ -0,0 +1,104 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 BogDan Vatra
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ANDROIDRUNNER_H
+#define ANDROIDRUNNER_H
+
+#include "androidconfigurations.h"
+
+#include
+#include
+#include
+#include
+#include
+#include