forked from qt-creator/qt-creator
Android virtual devices: Fix starting a avd
This cleans up various bits of the avd support in Creator. - Adds a abi combobox to the create avd dialog. - Moves the startAvd code into a separate thread, so that starting a avd while deploying doesn't block creator anymore. - Implements a better waitForAvd function that works even if a emulator is already running and accurately can detect that it has finished booting. Note: There are still many problems in the avd support in creator. - The "clean libs on device" and "install qasi" functionality block the gui thread if they are run on a avd. - If no avd exists and no suitable hardware is attached, the user gets a create Avd dialog, which doesn't tell him why he needs to create a avd. That information is hidden in the compile output. Still this fixes the main use case of hitting run on a newly created project with no actual device attached. Change-Id: I76b3fdb1bdf3eadac07f82ad7d145ce6af453326 Reviewed-by: BogDan Vatra <bogdan@kde.org>
This commit is contained in:
@@ -16,6 +16,16 @@
|
|||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Target Api:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -26,23 +36,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="3" column="0">
|
||||||
<widget class="QLineEdit" name="nameLineEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Target:</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QComboBox" name="targetComboBox"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>SD card size:</string>
|
<string>SD card size:</string>
|
||||||
@@ -52,7 +46,10 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="nameLineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
<widget class="QSpinBox" name="sizeSpinBox">
|
<widget class="QSpinBox" name="sizeSpinBox">
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
@@ -68,6 +65,22 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QComboBox" name="targetComboBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Abi:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QComboBox" name="abiComboBox"/>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -449,44 +449,57 @@ QVector<AndroidDeviceInfo> AndroidConfigurations::connectedDevices(QString *erro
|
|||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidConfigurations::createAVD(int minApiLevel) const
|
QString AndroidConfigurations::createAVD(int minApiLevel, QString targetArch) const
|
||||||
{
|
{
|
||||||
QDialog d;
|
QDialog d;
|
||||||
Ui::AddNewAVDDialog avdDialog;
|
Ui::AddNewAVDDialog avdDialog;
|
||||||
avdDialog.setupUi(&d);
|
avdDialog.setupUi(&d);
|
||||||
avdDialog.targetComboBox->addItems(sdkTargets(minApiLevel));
|
avdDialog.targetComboBox->addItems(sdkTargets(minApiLevel));
|
||||||
|
|
||||||
|
if (targetArch.isEmpty())
|
||||||
|
avdDialog.abiComboBox->addItems(QStringList()
|
||||||
|
<< QLatin1String("armeabi-v7a")
|
||||||
|
<< QLatin1String("armeabi")
|
||||||
|
<< QLatin1String("x86")
|
||||||
|
<< QLatin1String("mips"));
|
||||||
|
else
|
||||||
|
avdDialog.abiComboBox->addItems(QStringList(targetArch));
|
||||||
|
|
||||||
if (!avdDialog.targetComboBox->count()) {
|
if (!avdDialog.targetComboBox->count()) {
|
||||||
QMessageBox::critical(0, tr("Error Creating AVD"),
|
QMessageBox::critical(0, tr("Error Creating AVD"),
|
||||||
tr("Cannot create a new AVD. No sufficiently recent Android SDK available.\n"
|
tr("Cannot create a new AVD. No sufficiently recent Android SDK available.\n"
|
||||||
"Please install an SDK of at least API version %1.").
|
"Please install an SDK of at least API version %1.").
|
||||||
arg(minApiLevel));
|
arg(minApiLevel));
|
||||||
return false;
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QRegExp rx(QLatin1String("\\S+"));
|
QRegExp rx(QLatin1String("\\S+"));
|
||||||
QRegExpValidator v(rx, 0);
|
QRegExpValidator v(rx, 0);
|
||||||
avdDialog.nameLineEdit->setValidator(&v);
|
avdDialog.nameLineEdit->setValidator(&v);
|
||||||
if (d.exec() != QDialog::Accepted)
|
if (d.exec() != QDialog::Accepted)
|
||||||
return false;
|
return QString();
|
||||||
return createAVD(avdDialog.targetComboBox->currentText(), avdDialog.nameLineEdit->text(), avdDialog.sizeSpinBox->value());
|
return createAVD(avdDialog.targetComboBox->currentText(), avdDialog.nameLineEdit->text(), avdDialog.abiComboBox->currentText(), avdDialog.sizeSpinBox->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidConfigurations::createAVD(const QString &target, const QString &name, int sdcardSize ) const
|
QString AndroidConfigurations::createAVD(const QString &target, const QString &name, const QString &abi, int sdcardSize ) const
|
||||||
{
|
{
|
||||||
QProcess proc;
|
QProcess proc;
|
||||||
proc.start(androidToolPath().toString(),
|
proc.start(androidToolPath().toString(),
|
||||||
QStringList() << QLatin1String("create") << QLatin1String("avd")
|
QStringList() << QLatin1String("create") << QLatin1String("avd")
|
||||||
<< QLatin1String("-a") << QLatin1String("-t") << target
|
<< QLatin1String("-a") << QLatin1String("-t") << target
|
||||||
<< QLatin1String("-n") << name
|
<< QLatin1String("-n") << name
|
||||||
|
<< QLatin1String("-b") << abi
|
||||||
<< QLatin1String("-c") << QString::fromLatin1("%1M").arg(sdcardSize));
|
<< QLatin1String("-c") << QString::fromLatin1("%1M").arg(sdcardSize));
|
||||||
if (!proc.waitForStarted())
|
if (!proc.waitForStarted())
|
||||||
return false;
|
return QString();
|
||||||
proc.write(QByteArray("no\n"));
|
proc.write(QByteArray("no\n"));
|
||||||
if (!proc.waitForFinished(-1)) {
|
if (!proc.waitForFinished(-1)) {
|
||||||
proc.terminate();
|
proc.terminate();
|
||||||
return false;
|
return QString();
|
||||||
}
|
}
|
||||||
return !proc.exitCode();
|
if (proc.exitCode()) // error!
|
||||||
|
return QString();
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidConfigurations::removeAVD(const QString &name) const
|
bool AndroidConfigurations::removeAVD(const QString &name) const
|
||||||
@@ -531,6 +544,9 @@ QVector<AndroidDeviceInfo> AndroidConfigurations::androidVirtualDevices() const
|
|||||||
if (line.contains(QLatin1String("ABI:")))
|
if (line.contains(QLatin1String("ABI:")))
|
||||||
dev.cpuAbi = QStringList() << line.mid(line.lastIndexOf(QLatin1Char(' '))).trimmed();
|
dev.cpuAbi = QStringList() << line.mid(line.lastIndexOf(QLatin1Char(' '))).trimmed();
|
||||||
}
|
}
|
||||||
|
// armeabi-v7a devices can also run armeabi code
|
||||||
|
if (dev.cpuAbi == QStringList(QLatin1String("armeabi-v7a")))
|
||||||
|
dev.cpuAbi << QLatin1String("armeabi");
|
||||||
devices.push_back(dev);
|
devices.push_back(dev);
|
||||||
}
|
}
|
||||||
qSort(devices.begin(), devices.end(), androidDevicesLessThan);
|
qSort(devices.begin(), devices.end(), androidDevicesLessThan);
|
||||||
@@ -538,72 +554,70 @@ QVector<AndroidDeviceInfo> AndroidConfigurations::androidVirtualDevices() const
|
|||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AndroidConfigurations::startAVD(int *apiLevel, const QString &name) const
|
QString AndroidConfigurations::findAvd(int *apiLevel, const QString &cpuAbi)
|
||||||
|
{
|
||||||
|
QVector<AndroidDeviceInfo> devices = androidVirtualDevices();
|
||||||
|
foreach (const AndroidDeviceInfo &device, devices) {
|
||||||
|
// take first emulator how supports this package
|
||||||
|
if (device.sdk >= *apiLevel && device.cpuAbi.contains(cpuAbi)) {
|
||||||
|
*apiLevel = device.sdk;
|
||||||
|
return device.serialNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AndroidConfigurations::startAVD(const QString &name, int apiLevel, QString cpuAbi) const
|
||||||
|
{
|
||||||
|
if (startAVDAsync(name))
|
||||||
|
return waitForAvd(apiLevel, cpuAbi);
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AndroidConfigurations::startAVDAsync(const QString &avdName) const
|
||||||
{
|
{
|
||||||
QProcess *avdProcess = new QProcess();
|
QProcess *avdProcess = new QProcess();
|
||||||
connect(this, SIGNAL(destroyed()), avdProcess, SLOT(deleteLater()));
|
connect(this, SIGNAL(destroyed()), avdProcess, SLOT(deleteLater()));
|
||||||
connect(avdProcess, SIGNAL(finished(int)), avdProcess, SLOT(deleteLater()));
|
connect(avdProcess, SIGNAL(finished(int)), avdProcess, SLOT(deleteLater()));
|
||||||
|
|
||||||
QString avdName = name;
|
|
||||||
QVector<AndroidDeviceInfo> devices;
|
|
||||||
bool createAVDOnce = false;
|
|
||||||
while (true) {
|
|
||||||
if (avdName.isEmpty()) {
|
|
||||||
devices = androidVirtualDevices();
|
|
||||||
foreach (const AndroidDeviceInfo &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<QObject*>(static_cast<const QObject*>(this)), "createAVD", Qt::AutoConnection,
|
|
||||||
Q_ARG(int, *apiLevel));
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (avdName.isEmpty())// stop here if no emulators found
|
|
||||||
return avdName;
|
|
||||||
|
|
||||||
// start the emulator
|
// start the emulator
|
||||||
avdProcess->start(emulatorToolPath().toString(),
|
avdProcess->start(emulatorToolPath().toString(),
|
||||||
QStringList() << QLatin1String("-partition-size") << QString::number(config().partitionSize)
|
QStringList() << QLatin1String("-partition-size") << QString::number(config().partitionSize)
|
||||||
<< QLatin1String("-avd") << avdName);
|
<< QLatin1String("-avd") << avdName);
|
||||||
if (!avdProcess->waitForStarted(-1)) {
|
if (!avdProcess->waitForStarted(-1)) {
|
||||||
delete avdProcess;
|
delete avdProcess;
|
||||||
return QString();
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// wait until the emulator is online
|
QString AndroidConfigurations::waitForAvd(int apiLevel, const QString &cpuAbi) const
|
||||||
QProcess proc;
|
{
|
||||||
proc.start(adbToolPath().toString(), QStringList() << QLatin1String("-e") << QLatin1String("wait-for-device"));
|
// we cannot use adb -e wait-for-device, since that doesn't work if a emulator is already running
|
||||||
while (!proc.waitForFinished(500)) {
|
|
||||||
if (avdProcess->waitForFinished(0)) {
|
// 15 rounds of 8s sleeping, a minute for the avd to start
|
||||||
proc.kill();
|
QString serialNumber;
|
||||||
proc.waitForFinished(-1);
|
for (int i = 0; i < 15; ++i) {
|
||||||
|
QVector<AndroidDeviceInfo> devices = connectedDevices();
|
||||||
|
foreach (AndroidDeviceInfo device, devices) {
|
||||||
|
if (!device.serialNumber.startsWith(QLatin1String("emulator")))
|
||||||
|
continue;
|
||||||
|
if (!device.cpuAbi.contains(cpuAbi))
|
||||||
|
continue;
|
||||||
|
if (!device.sdk == apiLevel)
|
||||||
|
continue;
|
||||||
|
serialNumber = device.serialNumber;
|
||||||
|
// found a serial number, now wait until it's done booting...
|
||||||
|
for (int i = 0; i < 15; ++i) {
|
||||||
|
if (hasFinishedBooting(serialNumber))
|
||||||
|
return serialNumber;
|
||||||
|
else
|
||||||
|
sleep(8);
|
||||||
|
}
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
sleep(8);
|
||||||
}
|
}
|
||||||
sleep(5);// wait for pm to start
|
|
||||||
|
|
||||||
// workaround for stupid adb bug
|
|
||||||
proc.start(adbToolPath().toString(), QStringList() << QLatin1String("devices"));
|
|
||||||
if (!proc.waitForFinished(-1)) {
|
|
||||||
proc.kill();
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// get connected devices
|
|
||||||
devices = connectedDevices();
|
|
||||||
foreach (AndroidDeviceInfo device, devices)
|
|
||||||
if (device.sdk == *apiLevel)
|
|
||||||
return device.serialNumber;
|
|
||||||
// this should not happen, but ...
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,6 +661,24 @@ QString AndroidConfigurations::getProductModel(const QString &device) const
|
|||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AndroidConfigurations::hasFinishedBooting(const QString &device) const
|
||||||
|
{
|
||||||
|
QStringList arguments = AndroidDeviceInfo::adbSelector(device);
|
||||||
|
arguments << QLatin1String("shell") << QLatin1String("getprop")
|
||||||
|
<< QLatin1String("init.svc.bootanim");
|
||||||
|
|
||||||
|
QProcess adbProc;
|
||||||
|
adbProc.start(adbToolPath().toString(), arguments);
|
||||||
|
if (!adbProc.waitForFinished(-1)) {
|
||||||
|
adbProc.kill();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QString value = QString::fromLocal8Bit(adbProc.readAll().trimmed());
|
||||||
|
if (value == QLatin1String("stopped"))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QStringList AndroidConfigurations::getAbis(const QString &device) const
|
QStringList AndroidConfigurations::getAbis(const QString &device) const
|
||||||
{
|
{
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
|||||||
@@ -93,11 +93,15 @@ public:
|
|||||||
Utils::FileName stripPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const;
|
Utils::FileName stripPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const;
|
||||||
Utils::FileName readelfPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const;
|
Utils::FileName readelfPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const;
|
||||||
QString getDeployDeviceSerialNumber(int *apiLevel, const QString &abi, QString *error = 0) const;
|
QString getDeployDeviceSerialNumber(int *apiLevel, const QString &abi, QString *error = 0) const;
|
||||||
bool createAVD(const QString &target, const QString &name, int sdcardSize) const;
|
QString createAVD(int minApiLevel = 0, QString targetArch = QString()) const;
|
||||||
|
QString createAVD(const QString &target, const QString &name, const QString &abi, int sdcardSize) const;
|
||||||
bool removeAVD(const QString &name) const;
|
bool removeAVD(const QString &name) const;
|
||||||
QVector<AndroidDeviceInfo> connectedDevices(QString *error = 0) const;
|
QVector<AndroidDeviceInfo> connectedDevices(QString *error = 0) const;
|
||||||
QVector<AndroidDeviceInfo> androidVirtualDevices() const;
|
QVector<AndroidDeviceInfo> androidVirtualDevices() const;
|
||||||
QString startAVD(int *apiLevel, const QString &name = QString()) const;
|
QString findAvd(int *apiLevel, const QString &cpuAbi);
|
||||||
|
QString startAVD(const QString &name, int apiLevel, QString cpuAbi) const;
|
||||||
|
bool startAVDAsync(const QString &avdName) const;
|
||||||
|
QString waitForAvd(int apiLevel, const QString &cpuAbi) const;
|
||||||
QString bestMatch(const QString &targetAPI) const;
|
QString bestMatch(const QString &targetAPI) const;
|
||||||
|
|
||||||
QStringList makeExtraSearchDirectories() const;
|
QStringList makeExtraSearchDirectories() const;
|
||||||
@@ -110,12 +114,12 @@ public:
|
|||||||
void updateAndroidDevice();
|
void updateAndroidDevice();
|
||||||
|
|
||||||
QString getProductModel(const QString &device) const;
|
QString getProductModel(const QString &device) const;
|
||||||
|
bool hasFinishedBooting(const QString &device) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void updated();
|
void updated();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool createAVD(int minApiLevel = 0) const;
|
|
||||||
void updateAutomaticKitList();
|
void updateAutomaticKitList();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -97,21 +97,26 @@ bool AndroidDeployStep::init()
|
|||||||
{
|
{
|
||||||
m_packageName = AndroidManager::packageName(target());
|
m_packageName = AndroidManager::packageName(target());
|
||||||
const QString targetSDK = AndroidManager::targetSDK(target());
|
const QString targetSDK = AndroidManager::targetSDK(target());
|
||||||
const QString targetArch = AndroidManager::targetArch(target());
|
m_targetArch = AndroidManager::targetArch(target());
|
||||||
|
|
||||||
writeOutput(tr("Please wait, searching for a suitable device for target:%1, ABI:%2").arg(targetSDK).arg(targetArch));
|
writeOutput(tr("Please wait, searching for a suitable device for target:%1, ABI:%2").arg(targetSDK).arg(m_targetArch));
|
||||||
m_deviceAPILevel = targetSDK.mid(targetSDK.indexOf(QLatin1Char('-')) + 1).toInt();
|
m_deviceAPILevel = targetSDK.mid(targetSDK.indexOf(QLatin1Char('-')) + 1).toInt();
|
||||||
QString error;
|
QString error;
|
||||||
m_deviceSerialNumber = AndroidConfigurations::instance().getDeployDeviceSerialNumber(&m_deviceAPILevel, targetArch, &error);
|
m_deviceSerialNumber = AndroidConfigurations::instance().getDeployDeviceSerialNumber(&m_deviceAPILevel, m_targetArch, &error);
|
||||||
if (!error.isEmpty())
|
if (!error.isEmpty())
|
||||||
writeOutput(error);
|
writeOutput(error);
|
||||||
|
|
||||||
|
m_avdName.clear();
|
||||||
if (m_deviceSerialNumber.isEmpty()) {
|
if (m_deviceSerialNumber.isEmpty()) {
|
||||||
writeOutput(tr("Falling back to Android virtual machine device."));
|
writeOutput(tr("Falling back to Android virtual machine device."));
|
||||||
m_deviceSerialNumber = AndroidConfigurations::instance().startAVD(&m_deviceAPILevel);
|
m_avdName = AndroidConfigurations::instance().findAvd(&m_deviceAPILevel, m_targetArch);
|
||||||
|
if (m_avdName.isEmpty())
|
||||||
|
m_avdName = AndroidConfigurations::instance().createAVD(m_deviceAPILevel, m_targetArch);
|
||||||
|
if (m_avdName.isEmpty()) // user canceled
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_deviceSerialNumber.length()) {
|
if (m_deviceSerialNumber.isEmpty() && m_avdName.isEmpty()) {
|
||||||
m_deviceSerialNumber.clear();
|
m_deviceSerialNumber.clear();
|
||||||
raiseError(tr("Cannot deploy: no devices or emulators found for your package."));
|
raiseError(tr("Cannot deploy: no devices or emulators found for your package."));
|
||||||
return false;
|
return false;
|
||||||
@@ -196,8 +201,15 @@ void AndroidDeployStep::cleanLibsOnDevice()
|
|||||||
|
|
||||||
int deviceAPILevel = targetSDK.mid(targetSDK.indexOf(QLatin1Char('-')) + 1).toInt();
|
int deviceAPILevel = targetSDK.mid(targetSDK.indexOf(QLatin1Char('-')) + 1).toInt();
|
||||||
QString deviceSerialNumber = AndroidConfigurations::instance().getDeployDeviceSerialNumber(&deviceAPILevel, targetArch);
|
QString deviceSerialNumber = AndroidConfigurations::instance().getDeployDeviceSerialNumber(&deviceAPILevel, targetArch);
|
||||||
if (deviceSerialNumber.isEmpty())
|
if (deviceSerialNumber.isEmpty()) {
|
||||||
deviceSerialNumber = AndroidConfigurations::instance().startAVD(&deviceAPILevel);
|
QString avdName = AndroidConfigurations::instance().findAvd(&deviceAPILevel, targetArch);
|
||||||
|
if (avdName.isEmpty()) {
|
||||||
|
// No avd found, don't create one just error out
|
||||||
|
Core::MessageManager::instance()->printToOutputPane(tr("Could not find a device."), Core::MessageManager::NoModeSwitch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deviceSerialNumber = AndroidConfigurations::instance().startAVD(avdName, deviceAPILevel, targetArch);
|
||||||
|
}
|
||||||
if (!deviceSerialNumber.length()) {
|
if (!deviceSerialNumber.length()) {
|
||||||
Core::MessageManager::instance()->printToOutputPane(tr("Could not run adb. No device found."), Core::MessageManager::NoModeSwitch);
|
Core::MessageManager::instance()->printToOutputPane(tr("Could not run adb. No device found."), Core::MessageManager::NoModeSwitch);
|
||||||
return;
|
return;
|
||||||
@@ -249,8 +261,15 @@ void AndroidDeployStep::installQASIPackage(const QString &packagePath)
|
|||||||
const QString targetSDK = AndroidManager::targetSDK(target());
|
const QString targetSDK = AndroidManager::targetSDK(target());
|
||||||
int deviceAPILevel = targetSDK.mid(targetSDK.indexOf(QLatin1Char('-')) + 1).toInt();
|
int deviceAPILevel = targetSDK.mid(targetSDK.indexOf(QLatin1Char('-')) + 1).toInt();
|
||||||
QString deviceSerialNumber = AndroidConfigurations::instance().getDeployDeviceSerialNumber(&deviceAPILevel, targetArch);
|
QString deviceSerialNumber = AndroidConfigurations::instance().getDeployDeviceSerialNumber(&deviceAPILevel, targetArch);
|
||||||
if (deviceSerialNumber.isEmpty())
|
if (deviceSerialNumber.isEmpty()) {
|
||||||
deviceSerialNumber = AndroidConfigurations::instance().startAVD(&deviceAPILevel);
|
QString avdName = AndroidConfigurations::instance().findAvd(&deviceAPILevel, targetArch);
|
||||||
|
if (avdName.isEmpty()) {
|
||||||
|
Core::MessageManager::instance()->printToOutputPane(tr("No device found."),
|
||||||
|
Core::MessageManager::NoModeSwitch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deviceSerialNumber = AndroidConfigurations::instance().startAVD(avdName, deviceAPILevel, targetArch);
|
||||||
|
}
|
||||||
if (!deviceSerialNumber.length()) {
|
if (!deviceSerialNumber.length()) {
|
||||||
Core::MessageManager::instance()->printToOutputPane(tr("Could not run adb. No device found."), Core::MessageManager::NoModeSwitch);
|
Core::MessageManager::instance()->printToOutputPane(tr("Could not run adb. No device found."), Core::MessageManager::NoModeSwitch);
|
||||||
return;
|
return;
|
||||||
@@ -292,8 +311,8 @@ bool AndroidDeployStep::runCommand(QProcess *buildProc,
|
|||||||
.arg(program).arg(arguments.join(QLatin1String(" "))).arg(buildProc->errorString()), BuildStep::ErrorMessageOutput);
|
.arg(program).arg(arguments.join(QLatin1String(" "))).arg(buildProc->errorString()), BuildStep::ErrorMessageOutput);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
buildProc->waitForFinished(-1);
|
if (!buildProc->waitForFinished(2 * 60 * 1000)
|
||||||
if (buildProc->error() != QProcess::UnknownError
|
|| buildProc->error() != QProcess::UnknownError
|
||||||
|| buildProc->exitCode() != 0) {
|
|| buildProc->exitCode() != 0) {
|
||||||
QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.")
|
QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.")
|
||||||
.arg(program).arg(arguments.join(QLatin1String(" ")));
|
.arg(program).arg(arguments.join(QLatin1String(" ")));
|
||||||
@@ -452,6 +471,12 @@ void AndroidDeployStep::deployFiles(QProcess *process, const QList<DeployItem> &
|
|||||||
|
|
||||||
bool AndroidDeployStep::deployPackage()
|
bool AndroidDeployStep::deployPackage()
|
||||||
{
|
{
|
||||||
|
if (!m_avdName.isEmpty()) {
|
||||||
|
if (!AndroidConfigurations::instance().startAVDAsync(m_avdName))
|
||||||
|
return false;
|
||||||
|
m_deviceSerialNumber = AndroidConfigurations::instance().waitForAvd(m_deviceAPILevel, m_targetArch);
|
||||||
|
}
|
||||||
|
|
||||||
QProcess *const deployProc = new QProcess;
|
QProcess *const deployProc = new QProcess;
|
||||||
connect(deployProc, SIGNAL(readyReadStandardOutput()), this,
|
connect(deployProc, SIGNAL(readyReadStandardOutput()), this,
|
||||||
SLOT(handleBuildOutput()));
|
SLOT(handleBuildOutput()));
|
||||||
|
|||||||
@@ -138,10 +138,12 @@ private:
|
|||||||
private:
|
private:
|
||||||
QString m_deviceSerialNumber;
|
QString m_deviceSerialNumber;
|
||||||
int m_deviceAPILevel;
|
int m_deviceAPILevel;
|
||||||
|
QString m_targetArch;
|
||||||
|
|
||||||
AndroidDeployAction m_deployAction;
|
AndroidDeployAction m_deployAction;
|
||||||
|
|
||||||
// members to transfer data from init() to run
|
// members to transfer data from init() to run
|
||||||
|
QString m_avdName;
|
||||||
QString m_packageName;
|
QString m_packageName;
|
||||||
QString m_qtVersionSourcePath;
|
QString m_qtVersionSourcePath;
|
||||||
QtSupport::BaseQtVersion::QmakeBuildConfigs m_qtVersionQMakeBuildConfig;
|
QtSupport::BaseQtVersion::QmakeBuildConfigs m_qtVersionQMakeBuildConfig;
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ QVariant AvdModel::data(const QModelIndex &index, int role) const
|
|||||||
case 1:
|
case 1:
|
||||||
return QString::fromLatin1("API %1").arg(m_list[index.row()].sdk);
|
return QString::fromLatin1("API %1").arg(m_list[index.row()].sdk);
|
||||||
case 2:
|
case 2:
|
||||||
return m_list[index.row()].cpuAbi;
|
return m_list[index.row()].cpuAbi.first();
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@@ -401,8 +401,7 @@ void AndroidSettingsWidget::removeAVD()
|
|||||||
|
|
||||||
void AndroidSettingsWidget::startAVD()
|
void AndroidSettingsWidget::startAVD()
|
||||||
{
|
{
|
||||||
int tempApiLevel = -1;
|
AndroidConfigurations::instance().startAVDAsync(m_AVDModel.avdName(m_ui->AVDTableView->currentIndex()));
|
||||||
AndroidConfigurations::instance().startAVD(&tempApiLevel, m_AVDModel.avdName(m_ui->AVDTableView->currentIndex()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidSettingsWidget::avdActivated(QModelIndex index)
|
void AndroidSettingsWidget::avdActivated(QModelIndex index)
|
||||||
|
|||||||
Reference in New Issue
Block a user