diff options
author | Jake Petroules <jake.petroules@qt.io> | 2017-09-29 09:18:58 -0700 |
---|---|---|
committer | Jake Petroules <jake.petroules@qt.io> | 2017-10-04 22:09:17 +0000 |
commit | 9d1a039f674417add84105dd75b58a1151ce450b (patch) | |
tree | ee726e86c3f41c736b5119ded4e9b01136110c6a /src/lib/corelib/api/runenvironment.cpp | |
parent | 4e811eada68dc26a425b7a7e4e9b0d367ad95c74 (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.cpp | 68 |
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() |