aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/corelib/api/runenvironment.cpp
diff options
context:
space:
mode:
authorJake Petroules <jake.petroules@qt.io>2017-09-29 09:18:58 -0700
committerJake Petroules <jake.petroules@qt.io>2017-10-04 22:09:17 +0000
commit9d1a039f674417add84105dd75b58a1151ce450b (patch)
treeee726e86c3f41c736b5119ded4e9b01136110c6a /src/lib/corelib/api/runenvironment.cpp
parent4e811eada68dc26a425b7a7e4e9b0d367ad95c74 (diff)
Add support for running Android apps on devices
Change-Id: I1a3a4afb9742f1c89e6396430d178277ea41c451 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'src/lib/corelib/api/runenvironment.cpp')
-rw-r--r--src/lib/corelib/api/runenvironment.cpp68
1 files changed, 67 insertions, 1 deletions
diff --git a/src/lib/corelib/api/runenvironment.cpp b/src/lib/corelib/api/runenvironment.cpp
index a2caea987..16c188442 100644
--- a/src/lib/corelib/api/runenvironment.cpp
+++ b/src/lib/corelib/api/runenvironment.cpp
@@ -60,6 +60,8 @@
#include <QtCore/qtemporaryfile.h>
#include <QtCore/qvariant.h>
+#include <QtXml/qdom.h>
+
#include <stdlib.h>
namespace qbs {
@@ -208,6 +210,34 @@ static QString findExecutable(const QStringList &fileNames)
return QString();
}
+static QString findMainIntent(const QString &aapt, const QString &apkFilePath)
+{
+ QString packageId;
+ QString activity;
+ QProcess aaptProcess;
+ aaptProcess.start(aapt, QStringList()
+ << QStringLiteral("dump")
+ << QStringLiteral("badging")
+ << apkFilePath);
+ if (aaptProcess.waitForFinished(-1)) {
+ for (auto line : aaptProcess.readAllStandardOutput().split('\n')) {
+ if (line.startsWith(QByteArrayLiteral("package:"))) {
+ QDomDocument doc;
+ doc.setContent(QByteArrayLiteral("<") + line + QByteArrayLiteral("/>"));
+ packageId = doc.firstChild().toElement().attribute(QStringLiteral("name"));
+ } else if (line.startsWith(QByteArrayLiteral("launchable-activity:"))) {
+ QDomDocument doc;
+ doc.setContent(QByteArrayLiteral("<") + line + QByteArrayLiteral("/>"));
+ activity = doc.firstChild().toElement().attribute(QStringLiteral("name"));
+ }
+ }
+ }
+
+ if (!packageId.isEmpty() && !activity.isEmpty())
+ return packageId + QStringLiteral("/") + activity;
+ return QString();
+}
+
int RunEnvironment::doRunTarget(const QString &targetBin, const QStringList &arguments)
{
const QStringList targetOS = d->resolvedProduct->moduleProperties->qbsPropertyValue(
@@ -219,7 +249,43 @@ int RunEnvironment::doRunTarget(const QString &targetBin, const QStringList &arg
QStringList targetArguments = arguments;
const QString completeSuffix = QFileInfo(targetBin).completeSuffix();
- if (targetOS.contains(QLatin1String("ios")) || targetOS.contains(QLatin1String("tvos"))) {
+ if (targetOS.contains(QLatin1String("android"))) {
+ const auto aapt = d->resolvedProduct->moduleProperties->moduleProperty(
+ QStringLiteral("Android.sdk"), QStringLiteral("aaptFilePath")).toString();
+ const auto intent = findMainIntent(aapt, targetBin);
+ const auto sdkDir = d->resolvedProduct->moduleProperties->moduleProperty(
+ QStringLiteral("Android.sdk"), QStringLiteral("sdkDir")).toString();
+ targetExecutable = sdkDir + QStringLiteral("/platform-tools/adb");
+
+ QProcess process;
+ process.setProcessChannelMode(QProcess::ForwardedChannels);
+ process.start(targetExecutable, QStringList()
+ << QStringLiteral("install")
+ << QStringLiteral("-r") // replace existing application
+ << QStringLiteral("-t") // allow test packages
+ << QStringLiteral("-d") // allow version code downgrade
+ << targetBin);
+ if (!process.waitForFinished()) {
+ if (process.error() == QProcess::FailedToStart) {
+ throw ErrorInfo(Tr::tr("The process '%1' could not be started: %2")
+ .arg(targetExecutable)
+ .arg(process.errorString()));
+ } else {
+ d->logger.qbsWarning()
+ << "QProcess error: " << process.errorString();
+ }
+
+ return EXIT_FAILURE;
+ }
+
+ targetArguments << QStringList()
+ << QStringLiteral("shell")
+ << QStringLiteral("am")
+ << QStringLiteral("start")
+ << QStringLiteral("-W") // wait for launch to complete
+ << QStringLiteral("-n")
+ << intent;
+ } else if (targetOS.contains(QLatin1String("ios")) || targetOS.contains(QLatin1String("tvos"))) {
const QString bundlePath = targetBin + QLatin1String("/..");
if (QFileInfo(targetExecutable = findExecutable(QStringList()