forked from qt-creator/qt-creator
Android: Remove obsolete AndroidQmlPreviewWorker
This change remove the AndroidQmlPreviewWorker which was only used in QDS and is now (QtC 15 development cycle) obsolete in that context. Fixes: QTCREATORBUG-31221 Change-Id: I2e361c8245f70178fb0f0e3e1c0a9499d783856d Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
committed by
Jarek Kobus
parent
2d480f45da
commit
d134b7b5ce
@@ -25,7 +25,6 @@ add_qtc_plugin(Android
|
|||||||
androidpackageinstallationstep.cpp androidpackageinstallationstep.h
|
androidpackageinstallationstep.cpp androidpackageinstallationstep.h
|
||||||
androidplugin.cpp
|
androidplugin.cpp
|
||||||
androidpotentialkit.cpp androidpotentialkit.h
|
androidpotentialkit.cpp androidpotentialkit.h
|
||||||
androidqmlpreviewworker.cpp androidqmlpreviewworker.h
|
|
||||||
androidqmltoolingsupport.cpp androidqmltoolingsupport.h
|
androidqmltoolingsupport.cpp androidqmltoolingsupport.h
|
||||||
androidqtversion.cpp androidqtversion.h
|
androidqtversion.cpp androidqtversion.h
|
||||||
androidrunconfiguration.cpp androidrunconfiguration.h
|
androidrunconfiguration.cpp androidrunconfiguration.h
|
||||||
|
@@ -55,8 +55,6 @@ QtcPlugin {
|
|||||||
"androidplugin.cpp",
|
"androidplugin.cpp",
|
||||||
"androidpotentialkit.cpp",
|
"androidpotentialkit.cpp",
|
||||||
"androidpotentialkit.h",
|
"androidpotentialkit.h",
|
||||||
"androidqmlpreviewworker.h",
|
|
||||||
"androidqmlpreviewworker.cpp",
|
|
||||||
"androidqmltoolingsupport.cpp",
|
"androidqmltoolingsupport.cpp",
|
||||||
"androidqmltoolingsupport.h",
|
"androidqmltoolingsupport.h",
|
||||||
"androidqtversion.cpp",
|
"androidqtversion.cpp",
|
||||||
|
@@ -10,7 +10,6 @@
|
|||||||
#include "androidmanifesteditorfactory.h"
|
#include "androidmanifesteditorfactory.h"
|
||||||
#include "androidpackageinstallationstep.h"
|
#include "androidpackageinstallationstep.h"
|
||||||
#include "androidpotentialkit.h"
|
#include "androidpotentialkit.h"
|
||||||
#include "androidqmlpreviewworker.h"
|
|
||||||
#include "androidqmltoolingsupport.h"
|
#include "androidqmltoolingsupport.h"
|
||||||
#include "androidqtversion.h"
|
#include "androidqtversion.h"
|
||||||
#include "androidrunconfiguration.h"
|
#include "androidrunconfiguration.h"
|
||||||
@@ -107,7 +106,6 @@ class AndroidPlugin final : public ExtensionSystem::IPlugin
|
|||||||
setupAndroidRunWorker();
|
setupAndroidRunWorker();
|
||||||
setupAndroidDebugWorker();
|
setupAndroidDebugWorker();
|
||||||
setupAndroidQmlToolingSupport();
|
setupAndroidQmlToolingSupport();
|
||||||
setupAndroidQmlPreviewWorker();
|
|
||||||
|
|
||||||
setupJavaEditor();
|
setupJavaEditor();
|
||||||
setupAndroidManifestEditor();
|
setupAndroidManifestEditor();
|
||||||
|
@@ -1,510 +0,0 @@
|
|||||||
// Copyright (C) 2021 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#include "androidqmlpreviewworker.h"
|
|
||||||
|
|
||||||
#include "androidavdmanager.h"
|
|
||||||
#include "androidconfigurations.h"
|
|
||||||
#include "androidconstants.h"
|
|
||||||
#include "androiddevice.h"
|
|
||||||
#include "androiddeviceinfo.h"
|
|
||||||
#include "androidmanager.h"
|
|
||||||
#include "androidtr.h"
|
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
|
|
||||||
#include <projectexplorer/buildsystem.h>
|
|
||||||
#include <projectexplorer/environmentaspect.h>
|
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
|
||||||
#include <projectexplorer/runcontrol.h>
|
|
||||||
#include <projectexplorer/target.h>
|
|
||||||
|
|
||||||
#include <solutions/tasking/tasktreerunner.h>
|
|
||||||
|
|
||||||
#include <qmlprojectmanager/qmlprojectconstants.h>
|
|
||||||
|
|
||||||
#include <qtsupport/qtkitaspect.h>
|
|
||||||
|
|
||||||
#include <utils/qtcprocess.h>
|
|
||||||
|
|
||||||
#include <QDateTime>
|
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
|
||||||
using namespace Tasking;
|
|
||||||
using namespace Utils;
|
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
|
||||||
|
|
||||||
namespace Android::Internal {
|
|
||||||
|
|
||||||
#define APP_ID "io.qt.qtdesignviewer"
|
|
||||||
|
|
||||||
class ApkInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ApkInfo()
|
|
||||||
: abis{ProjectExplorer::Constants::ANDROID_ABI_X86,
|
|
||||||
ProjectExplorer::Constants::ANDROID_ABI_X86_64,
|
|
||||||
ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A,
|
|
||||||
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A}
|
|
||||||
, appId(APP_ID)
|
|
||||||
, uploadDir("/data/local/tmp/" APP_ID "/")
|
|
||||||
// TODO Add possibility to run Qt5 built version of Qt Design Viewer
|
|
||||||
, activityId(APP_ID "/org.qtproject.qt.android.bindings.QtActivity")
|
|
||||||
, name("Qt Design Viewer")
|
|
||||||
{}
|
|
||||||
const QStringList abis;
|
|
||||||
const QString appId;
|
|
||||||
const QString uploadDir;
|
|
||||||
const QString activityId;
|
|
||||||
const QString name;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(ApkInfo, apkInfo)
|
|
||||||
|
|
||||||
class UploadInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FilePath uploadPackage;
|
|
||||||
FilePath projectFolder;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char packageSuffix[] = ".qmlrc";
|
|
||||||
|
|
||||||
class AndroidQmlPreviewWorker : public RunWorker
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
AndroidQmlPreviewWorker(RunControl *runControl);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void previewPidChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void start() override;
|
|
||||||
void stop() override;
|
|
||||||
|
|
||||||
bool ensureAvdIsRunning();
|
|
||||||
bool checkAndInstallPreviewApp();
|
|
||||||
bool preparePreviewArtefacts();
|
|
||||||
bool uploadPreviewArtefacts();
|
|
||||||
|
|
||||||
CommandLine adbCommand(const QStringList &arguments) const;
|
|
||||||
SdkToolResult runAdbCommand(const QStringList &arguments) const;
|
|
||||||
SdkToolResult runAdbShellCommand(const QStringList &arguments) const;
|
|
||||||
|
|
||||||
void startPidWatcher();
|
|
||||||
void startLogcat();
|
|
||||||
void filterLogcatAndAppendMessage(const QString &stdOut);
|
|
||||||
|
|
||||||
bool startPreviewApp();
|
|
||||||
bool stopPreviewApp();
|
|
||||||
|
|
||||||
FilePath designViewerApkPath(const QString &abi) const;
|
|
||||||
FilePath createQmlrcFile(const FilePath &workFolder, const QString &basename);
|
|
||||||
|
|
||||||
RunControl *m_rc = nullptr;
|
|
||||||
QString m_serialNumber;
|
|
||||||
QStringList m_avdAbis;
|
|
||||||
int m_viewerPid = -1;
|
|
||||||
TaskTreeRunner m_pidRunner;
|
|
||||||
Process m_logcatProcess;
|
|
||||||
QString m_logcatStartTimeStamp;
|
|
||||||
UploadInfo m_uploadInfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
FilePath AndroidQmlPreviewWorker::designViewerApkPath(const QString &abi) const
|
|
||||||
{
|
|
||||||
if (abi.isEmpty())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
if (apkInfo()->abis.contains(abi)) {
|
|
||||||
return Core::ICore::resourcePath(QString("android/qtdesignviewer/qtdesignviewer_%1.apk")
|
|
||||||
.arg(abi));
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandLine AndroidQmlPreviewWorker::adbCommand(const QStringList &arguments) const
|
|
||||||
{
|
|
||||||
CommandLine cmd{AndroidConfig::adbToolPath()};
|
|
||||||
if (!m_serialNumber.isEmpty())
|
|
||||||
cmd.addArgs(AndroidDeviceInfo::adbSelector(m_serialNumber));
|
|
||||||
cmd.addArg("shell");
|
|
||||||
cmd.addArgs(arguments);
|
|
||||||
return cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
SdkToolResult AndroidQmlPreviewWorker::runAdbCommand(const QStringList &arguments) const
|
|
||||||
{
|
|
||||||
QStringList args;
|
|
||||||
if (!m_serialNumber.isEmpty())
|
|
||||||
args << AndroidDeviceInfo::adbSelector(m_serialNumber);
|
|
||||||
args << arguments;
|
|
||||||
return AndroidManager::runAdbCommand(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
SdkToolResult AndroidQmlPreviewWorker::runAdbShellCommand(const QStringList &arguments) const
|
|
||||||
{
|
|
||||||
return runAdbCommand(QStringList() << "shell" << arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidQmlPreviewWorker::startPidWatcher()
|
|
||||||
{
|
|
||||||
const LoopUntil pidIterator([this](int) { return m_viewerPid <= 0; });
|
|
||||||
const LoopUntil alivePidIterator([this](int) { return m_viewerPid > 0; });
|
|
||||||
|
|
||||||
const auto onPidSetup = [this](Process &process) {
|
|
||||||
process.setCommand(adbCommand({"pidof", apkInfo()->appId}));
|
|
||||||
};
|
|
||||||
const auto onPidDone = [this](const Process &process) {
|
|
||||||
bool ok = false;
|
|
||||||
const int pid = process.cleanedStdOut().trimmed().toInt(&ok);
|
|
||||||
if (ok && pid > 0) {
|
|
||||||
m_viewerPid = pid;
|
|
||||||
// TODO: make a continuation task (logcat)
|
|
||||||
emit previewPidChanged();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto onAlivePidDone = [this](const Process &process) {
|
|
||||||
bool ok = false;
|
|
||||||
const int pid = process.cleanedStdOut().trimmed().toInt(&ok);
|
|
||||||
if (!ok || pid != m_viewerPid) {
|
|
||||||
m_viewerPid = -1;
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const TimeoutTask timeout([](std::chrono::milliseconds &timeout) { timeout = 2s; });
|
|
||||||
|
|
||||||
const Group recipe {
|
|
||||||
For {
|
|
||||||
pidIterator,
|
|
||||||
ProcessTask(onPidSetup, onPidDone, CallDoneIf::Success),
|
|
||||||
timeout
|
|
||||||
}.withTimeout(20s),
|
|
||||||
For {
|
|
||||||
alivePidIterator,
|
|
||||||
ProcessTask(onPidSetup, onAlivePidDone),
|
|
||||||
timeout
|
|
||||||
}
|
|
||||||
};
|
|
||||||
m_pidRunner.start(recipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidQmlPreviewWorker::startLogcat()
|
|
||||||
{
|
|
||||||
QString args = QString("logcat --pid=%1").arg(m_viewerPid);
|
|
||||||
if (!m_logcatStartTimeStamp.isEmpty())
|
|
||||||
args += QString(" -T '%1'").arg(m_logcatStartTimeStamp);
|
|
||||||
CommandLine cmd(AndroidConfig::adbToolPath());
|
|
||||||
cmd.setArguments(args);
|
|
||||||
m_logcatProcess.setCommand(cmd);
|
|
||||||
m_logcatProcess.setUseCtrlCStub(true);
|
|
||||||
m_logcatProcess.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidQmlPreviewWorker::filterLogcatAndAppendMessage(const QString &stdOut)
|
|
||||||
{
|
|
||||||
for (const QString &line : stdOut.split('\n')) {
|
|
||||||
QStringList splittedLine = line.split(QLatin1String("%1: ").arg(apkInfo()->name));
|
|
||||||
if (splittedLine.count() == 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const QString outLine = splittedLine.last();
|
|
||||||
const QString firstPart = splittedLine.first();
|
|
||||||
if (firstPart.contains(" I ") || firstPart.contains(" D "))
|
|
||||||
appendMessage(outLine, NormalMessageFormat);
|
|
||||||
else
|
|
||||||
appendMessage(outLine, ErrorMessageFormat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidQmlPreviewWorker::AndroidQmlPreviewWorker(RunControl *runControl)
|
|
||||||
: RunWorker(runControl),
|
|
||||||
m_rc(runControl)
|
|
||||||
{
|
|
||||||
connect(this, &RunWorker::started, this, &AndroidQmlPreviewWorker::startPidWatcher);
|
|
||||||
connect(this, &RunWorker::stopped, &m_pidRunner, &TaskTreeRunner::reset);
|
|
||||||
connect(this, &AndroidQmlPreviewWorker::previewPidChanged,
|
|
||||||
this, &AndroidQmlPreviewWorker::startLogcat);
|
|
||||||
|
|
||||||
connect(this, &RunWorker::stopped, &m_logcatProcess, &Process::stop);
|
|
||||||
m_logcatProcess.setStdOutCallback([this](const QString &stdOut) {
|
|
||||||
filterLogcatAndAppendMessage(stdOut);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidQmlPreviewWorker::start()
|
|
||||||
{
|
|
||||||
const SdkToolResult dateResult = runAdbCommand({"shell", "date", "+%s"});
|
|
||||||
if (dateResult.success()) {
|
|
||||||
m_logcatStartTimeStamp = QDateTime::fromSecsSinceEpoch(dateResult.stdOut().toInt())
|
|
||||||
.toString("MM-dd hh:mm:ss.mmm");
|
|
||||||
}
|
|
||||||
const bool previewStarted = ensureAvdIsRunning()
|
|
||||||
&& checkAndInstallPreviewApp()
|
|
||||||
&& preparePreviewArtefacts()
|
|
||||||
&& uploadPreviewArtefacts()
|
|
||||||
&& startPreviewApp();
|
|
||||||
|
|
||||||
previewStarted ? reportStarted() : reportStopped();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidQmlPreviewWorker::stop()
|
|
||||||
{
|
|
||||||
if (m_viewerPid <= 0 || stopPreviewApp())
|
|
||||||
appendMessage(Tr::tr("%1 has been stopped.").arg(apkInfo()->name), NormalMessageFormat);
|
|
||||||
m_viewerPid = -1;
|
|
||||||
reportStopped();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AndroidQmlPreviewWorker::ensureAvdIsRunning()
|
|
||||||
{
|
|
||||||
QString devSN = AndroidManager::deviceSerialNumber(m_rc->target());
|
|
||||||
|
|
||||||
if (devSN.isEmpty())
|
|
||||||
devSN = m_serialNumber;
|
|
||||||
|
|
||||||
if (!AndroidAvdManager::isAvdBooted(devSN)) {
|
|
||||||
const IDevice *dev = DeviceKitAspect::device(m_rc->target()->kit()).get();
|
|
||||||
if (!dev) {
|
|
||||||
appendMessage(Tr::tr("Selected device is invalid."), ErrorMessageFormat);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (dev->deviceState() == IDevice::DeviceDisconnected) {
|
|
||||||
appendMessage(Tr::tr("Selected device is disconnected."), ErrorMessageFormat);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
AndroidDeviceInfo devInfoLocal = AndroidDevice::androidDeviceInfoFromIDevice(dev);
|
|
||||||
|
|
||||||
if (devInfoLocal.isValid()) {
|
|
||||||
if (dev->machineType() == IDevice::Emulator) {
|
|
||||||
appendMessage(Tr::tr("Launching AVD."), NormalMessageFormat);
|
|
||||||
devInfoLocal.serialNumber = AndroidAvdManager::startAvd(devInfoLocal.avdName);
|
|
||||||
}
|
|
||||||
if (devInfoLocal.serialNumber.isEmpty()) {
|
|
||||||
appendMessage(Tr::tr("Could not start AVD."), ErrorMessageFormat);
|
|
||||||
} else {
|
|
||||||
m_serialNumber = devInfoLocal.serialNumber;
|
|
||||||
m_avdAbis = AndroidConfig::getAbis(m_serialNumber);
|
|
||||||
}
|
|
||||||
return !devInfoLocal.serialNumber.isEmpty();
|
|
||||||
} else {
|
|
||||||
appendMessage(Tr::tr("No valid AVD has been selected."), ErrorMessageFormat);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_avdAbis = AndroidConfig::getAbis(m_serialNumber);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AndroidQmlPreviewWorker::checkAndInstallPreviewApp()
|
|
||||||
{
|
|
||||||
const QStringList command {"pm", "list", "packages", apkInfo()->appId};
|
|
||||||
appendMessage(Tr::tr("Checking if %1 app is installed.").arg(apkInfo()->name), NormalMessageFormat);
|
|
||||||
const SdkToolResult res = runAdbShellCommand(command);
|
|
||||||
if (!res.success()) {
|
|
||||||
appendMessage(res.stdErr(), ErrorMessageFormat);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.stdOut().isEmpty()) {
|
|
||||||
if (m_avdAbis.isEmpty()) {
|
|
||||||
appendMessage(Tr::tr("ABI of the selected device is unknown. Cannot install APK."),
|
|
||||||
ErrorMessageFormat);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const FilePath apkPath = designViewerApkPath(m_avdAbis.first());
|
|
||||||
if (!apkPath.exists()) {
|
|
||||||
appendMessage(Tr::tr("Cannot install %1 app for %2 architecture. "
|
|
||||||
"The appropriate APK was not found in resources folders.").
|
|
||||||
arg(apkInfo()->name, m_avdAbis.first()), ErrorMessageFormat);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendMessage(Tr::tr("Installing %1 APK.").arg(apkInfo()->name), NormalMessageFormat);
|
|
||||||
|
|
||||||
const SdkToolResult res = runAdbCommand({"install", apkPath.toString()});
|
|
||||||
if (!res.success())
|
|
||||||
appendMessage(res.stdErr(), StdErrFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AndroidQmlPreviewWorker::preparePreviewArtefacts()
|
|
||||||
{
|
|
||||||
if (m_rc->project()->id() == QmlProjectManager::Constants::QML_PROJECT_ID) {
|
|
||||||
const auto bs = m_rc->target()->buildSystem();
|
|
||||||
if (bs) {
|
|
||||||
m_uploadInfo.uploadPackage = FilePath::fromString(
|
|
||||||
bs->additionalData(QmlProjectManager::Constants::mainFilePath).toString());
|
|
||||||
m_uploadInfo.projectFolder = bs->projectDirectory();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const FilePaths allFiles = m_rc->project()->files(m_rc->project()->SourceFiles);
|
|
||||||
const FilePaths filesToExport = filtered(allFiles, [](const FilePath &path) {
|
|
||||||
return path.suffix() == "qmlproject";
|
|
||||||
});
|
|
||||||
|
|
||||||
if (filesToExport.size() > 1) {
|
|
||||||
appendMessage(Tr::tr("Too many .qmlproject files in your project. Open directly the "
|
|
||||||
".qmlproject file you want to work with and then run the preview."),
|
|
||||||
ErrorMessageFormat);
|
|
||||||
} else if (filesToExport.size() < 1) {
|
|
||||||
appendMessage(Tr::tr("No .qmlproject file found among project files."), ErrorMessageFormat);
|
|
||||||
} else {
|
|
||||||
const FilePath qmlprojectFile = filesToExport.first();
|
|
||||||
m_uploadInfo.uploadPackage = m_uploadInfo.projectFolder.resolvePath(
|
|
||||||
qmlprojectFile.fileName());
|
|
||||||
m_uploadInfo.projectFolder = qmlprojectFile.parentDir();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
appendMessage(Tr::tr("Could not gather information on project files."), ErrorMessageFormat);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FilePath AndroidQmlPreviewWorker::createQmlrcFile(const FilePath &workFolder,
|
|
||||||
const QString &basename)
|
|
||||||
{
|
|
||||||
const QtSupport::QtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(m_rc->kit());
|
|
||||||
const FilePath rccBinary = qtVersion->rccFilePath();
|
|
||||||
Process rccProcess;
|
|
||||||
FilePath qrcPath = FilePath::fromString(basename + ".qrc4viewer");
|
|
||||||
const FilePath qmlrcPath = FilePath::fromString(QDir::tempPath()) / (basename + packageSuffix);
|
|
||||||
|
|
||||||
rccProcess.setWorkingDirectory(workFolder);
|
|
||||||
|
|
||||||
const QStringList arguments[2] = {{"--project", "--output", qrcPath.fileName()},
|
|
||||||
{"--binary", "--output", qmlrcPath.path(),
|
|
||||||
qrcPath.fileName()}};
|
|
||||||
for (const QStringList &args : arguments) {
|
|
||||||
rccProcess.setCommand({rccBinary, args});
|
|
||||||
rccProcess.start();
|
|
||||||
if (!rccProcess.waitForStarted()) {
|
|
||||||
appendMessage(Tr::tr("Could not create file for %1 \"%2\".").
|
|
||||||
arg(apkInfo()->name, rccProcess.commandLine().toUserOutput()),
|
|
||||||
StdErrFormat);
|
|
||||||
qrcPath.removeFile();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
QByteArray stdOut;
|
|
||||||
QByteArray stdErr;
|
|
||||||
if (!rccProcess.readDataFromProcess(&stdOut, &stdErr)) {
|
|
||||||
rccProcess.stop();
|
|
||||||
rccProcess.waitForFinished();
|
|
||||||
appendMessage(Tr::tr("A timeout occurred running \"%1\".").
|
|
||||||
arg(rccProcess.commandLine().toUserOutput()), StdErrFormat);
|
|
||||||
qrcPath.removeFile();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
if (!stdOut.trimmed().isEmpty())
|
|
||||||
appendMessage(QString::fromLocal8Bit(stdOut), StdErrFormat);
|
|
||||||
|
|
||||||
if (!stdErr.trimmed().isEmpty())
|
|
||||||
appendMessage(QString::fromLocal8Bit(stdErr), StdErrFormat);
|
|
||||||
|
|
||||||
if (rccProcess.exitStatus() != QProcess::NormalExit) {
|
|
||||||
appendMessage(Tr::tr("Crash while creating file for %1 \"%2\".").
|
|
||||||
arg(apkInfo()->name, rccProcess.commandLine().toUserOutput()),
|
|
||||||
StdErrFormat);
|
|
||||||
qrcPath.removeFile();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
if (rccProcess.exitCode() != 0) {
|
|
||||||
appendMessage(Tr::tr("Creating file for %1 failed. \"%2\" (exit code %3).").
|
|
||||||
arg(apkInfo()->name).
|
|
||||||
arg(rccProcess.commandLine().toUserOutput()).
|
|
||||||
arg(rccProcess.exitCode()),
|
|
||||||
|
|
||||||
StdErrFormat);
|
|
||||||
qrcPath.removeFile();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return qmlrcPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AndroidQmlPreviewWorker::uploadPreviewArtefacts()
|
|
||||||
{
|
|
||||||
appendMessage(Tr::tr("Uploading files."), NormalMessageFormat);
|
|
||||||
const FilePath qresPath = createQmlrcFile(m_uploadInfo.projectFolder,
|
|
||||||
m_uploadInfo.uploadPackage.baseName());
|
|
||||||
if (!qresPath.exists())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
runAdbShellCommand({"mkdir", "-p", apkInfo()->uploadDir});
|
|
||||||
const SdkToolResult res = runAdbCommand({"push", qresPath.resolvePath(QString()).toString(),
|
|
||||||
apkInfo()->uploadDir});
|
|
||||||
if (!res.success()) {
|
|
||||||
appendMessage(res.stdOut(), ErrorMessageFormat);
|
|
||||||
if (res.stdOut().contains("Permission denied")) {
|
|
||||||
appendMessage("'Permission denied' error detected. Try restarting your device "
|
|
||||||
"and then running the preview.", NormalMessageFormat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qresPath.removeFile();
|
|
||||||
return res.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AndroidQmlPreviewWorker::startPreviewApp()
|
|
||||||
{
|
|
||||||
stopPreviewApp();
|
|
||||||
appendMessage(Tr::tr("Starting %1.").arg(apkInfo()->name), NormalMessageFormat);
|
|
||||||
const QDir destDir(apkInfo()->uploadDir);
|
|
||||||
const QString qmlrcPath = destDir.filePath(m_uploadInfo.uploadPackage.baseName()
|
|
||||||
+ packageSuffix);
|
|
||||||
const QStringList envVars = m_rc->aspectData<EnvironmentAspect>()->environment.toStringList();
|
|
||||||
|
|
||||||
const QStringList command {
|
|
||||||
"am", "start",
|
|
||||||
"-n", apkInfo()->activityId,
|
|
||||||
"-e", "extraappparams", QLatin1String(qmlrcPath.toUtf8().toBase64()),
|
|
||||||
"-e", "extraenvvars", QLatin1String(envVars.join('\t').toUtf8().toBase64())
|
|
||||||
};
|
|
||||||
const SdkToolResult result = runAdbShellCommand(command);
|
|
||||||
if (result.success())
|
|
||||||
appendMessage(Tr::tr("%1 is running.").arg(apkInfo()->name), NormalMessageFormat);
|
|
||||||
else
|
|
||||||
appendMessage(result.stdErr(), ErrorMessageFormat);
|
|
||||||
|
|
||||||
return result.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AndroidQmlPreviewWorker::stopPreviewApp()
|
|
||||||
{
|
|
||||||
const QStringList command{"am", "force-stop", apkInfo()->appId};
|
|
||||||
const SdkToolResult res = runAdbShellCommand(command);
|
|
||||||
if (!res.success())
|
|
||||||
appendMessage(res.stdErr(), ErrorMessageFormat);
|
|
||||||
return res.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AndroidQmlPreviewWorkerFactory
|
|
||||||
|
|
||||||
class AndroidQmlPreviewWorkerFactory final : public RunWorkerFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AndroidQmlPreviewWorkerFactory()
|
|
||||||
{
|
|
||||||
setProduct<AndroidQmlPreviewWorker>();
|
|
||||||
addSupportedRunMode(ProjectExplorer::Constants::QML_PREVIEW_RUN_MODE);
|
|
||||||
addSupportedRunConfig("QmlProjectManager.QmlRunConfiguration.Qml");
|
|
||||||
addSupportedRunConfig(Constants::ANDROID_RUNCONFIG_ID);
|
|
||||||
addSupportedDeviceType(Android::Constants::ANDROID_DEVICE_TYPE);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void setupAndroidQmlPreviewWorker()
|
|
||||||
{
|
|
||||||
static AndroidQmlPreviewWorkerFactory theAndroidQmlPreviewWorkerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Android::Internal
|
|
||||||
|
|
||||||
#include "androidqmlpreviewworker.moc"
|
|
@@ -1,10 +0,0 @@
|
|||||||
// Copyright (C) 2021 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Android::Internal {
|
|
||||||
|
|
||||||
void setupAndroidQmlPreviewWorker();
|
|
||||||
|
|
||||||
} // Android::Internal
|
|
Reference in New Issue
Block a user