Skip to content

Commit 372138e

Browse files
Device Selection for APK Installation (#208)
* Fix dock state saving during minimize * Support installing to specific device
1 parent 57e87b4 commit 372138e

8 files changed

Lines changed: 457 additions & 37 deletions

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ set(SOURCES
7474
sources/apksignworker.cpp
7575
sources/appearancesettingswidget.cpp
7676
sources/binarysettingswidget.cpp
77+
sources/devicelistworker.cpp
78+
sources/deviceselectiondialog.cpp
7779
sources/findreplacedialog.cpp
7880
sources/flickcharm.cpp
7981
sources/hexedit.cpp
@@ -99,6 +101,8 @@ set(HEADERS
99101
sources/apksignworker.h
100102
sources/appearancesettingswidget.h
101103
sources/binarysettingswidget.h
104+
sources/devicelistworker.h
105+
sources/deviceselectiondialog.h
102106
sources/findreplacedialog.h
103107
sources/flickcharm.h
104108
sources/hexedit.h

sources/adbinstallworker.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
#include "adbinstallworker.h"
33
#include "processutils.h"
44

5-
AdbInstallWorker::AdbInstallWorker(const QString &apk, QObject *parent)
6-
: QObject(parent), m_Apk(apk)
5+
AdbInstallWorker::AdbInstallWorker(const QString &apk, const QString &deviceId, QObject *parent)
6+
: QObject(parent), m_Apk(apk), m_DeviceId(deviceId)
77
{
88
}
99

@@ -19,7 +19,11 @@ void AdbInstallWorker::install()
1919
return;
2020
}
2121
QStringList args;
22-
args << "install" << "-r" << m_Apk;
22+
args << "install";
23+
if (!m_DeviceId.isEmpty()) {
24+
args << "-s" << m_DeviceId;
25+
}
26+
args << "-r" << m_Apk;
2327
ProcessResult result = ProcessUtils::runCommand(adb, args);
2428
#ifdef QT_DEBUG
2529
qDebug() << "ADB returned code" << result.code;

sources/adbinstallworker.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ class AdbInstallWorker : public QObject
77
{
88
Q_OBJECT
99
public:
10-
explicit AdbInstallWorker(const QString &apk, QObject *parent = nullptr);
10+
explicit AdbInstallWorker(const QString &apk, const QString &deviceId = QString(), QObject *parent = nullptr);
1111
void install();
1212
private:
1313
QString m_Apk;
14+
QString m_DeviceId;
1415
signals:
1516
void finished();
1617
void installFailed(const QString &apk);

sources/devicelistworker.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#include <QDebug>
2+
#include <QRegularExpression>
3+
#include "devicelistworker.h"
4+
#include "processutils.h"
5+
6+
DeviceListWorker::DeviceListWorker(QObject *parent)
7+
: QObject(parent)
8+
{
9+
}
10+
11+
void DeviceListWorker::listDevices()
12+
{
13+
emit started();
14+
15+
const QString adb = ProcessUtils::adbExe();
16+
if (adb.isEmpty()) {
17+
emit error(tr("ADB not found. Please configure it in Settings."));
18+
emit finished();
19+
return;
20+
}
21+
22+
// Get device list with details
23+
ProcessResult result = ProcessUtils::runCommand(adb, QStringList() << "devices" << "-l");
24+
if (result.code != 0) {
25+
emit error(tr("Failed to query devices: %1").arg(result.error.join("\n")));
26+
emit finished();
27+
return;
28+
}
29+
30+
QList<DeviceInfo> devices;
31+
32+
// Parse device list
33+
bool foundHeader = false;
34+
for (const QString &line : result.output) {
35+
QString trimmed = line.trimmed();
36+
if (trimmed.isEmpty()) {
37+
continue;
38+
}
39+
if (!foundHeader) {
40+
if (trimmed.startsWith("List of devices")) {
41+
foundHeader = true;
42+
}
43+
continue;
44+
}
45+
46+
DeviceInfo device = parseDeviceLine(trimmed);
47+
if (!device.serial.isEmpty()) {
48+
// Get additional device properties if not already found
49+
if (device.model.isEmpty()) {
50+
device.model = getDeviceProperty(device.serial, "ro.product.model");
51+
}
52+
device.androidSdkVersion = getDeviceProperty(device.serial, "ro.build.version.sdk");
53+
device.androidVersion = getDeviceProperty(device.serial, "ro.build.version.release");
54+
devices.append(device);
55+
}
56+
}
57+
58+
emit devicesListed(devices);
59+
emit finished();
60+
}
61+
62+
DeviceInfo DeviceListWorker::parseDeviceLine(const QString &line)
63+
{
64+
DeviceInfo device;
65+
66+
// Format: SERIAL STATUS [PROPERTY:VALUE]...
67+
// Example: emulator-5554 device product:sdk_gphone64_arm64 model:sdk_gphone64_arm64 device:emu64xa
68+
QRegularExpression regex(R"(^(\S+)\s+(\S+)(?:\s+(.+))?$)");
69+
QRegularExpressionMatch match = regex.match(line);
70+
71+
if (match.hasMatch()) {
72+
device.serial = match.captured(1);
73+
device.status = match.captured(2);
74+
75+
// Parse properties from the rest of the line
76+
QString properties = match.captured(3);
77+
if (!properties.isEmpty()) {
78+
QRegularExpression propRegex(R"((\w+):([^\s]+))");
79+
QRegularExpressionMatchIterator propIter = propRegex.globalMatch(properties);
80+
while (propIter.hasNext()) {
81+
QRegularExpressionMatch propMatch = propIter.next();
82+
QString key = propMatch.captured(1);
83+
QString value = propMatch.captured(2);
84+
if (key == "model") {
85+
device.model = value;
86+
}
87+
}
88+
}
89+
}
90+
91+
return device;
92+
}
93+
94+
QString DeviceListWorker::getDeviceProperty(const QString &serial, const QString &property)
95+
{
96+
const QString adb = ProcessUtils::adbExe();
97+
if (adb.isEmpty()) {
98+
return QString();
99+
}
100+
101+
QStringList args;
102+
args << "-s" << serial << "shell" << "getprop" << property;
103+
ProcessResult result = ProcessUtils::runCommand(adb, args, 5);
104+
105+
if (result.code == 0 && !result.output.isEmpty()) {
106+
return result.output.first().trimmed();
107+
}
108+
109+
return QString();
110+
}
111+

sources/devicelistworker.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#ifndef DEVICELISTWORKER_H
2+
#define DEVICELISTWORKER_H
3+
4+
#include <QList>
5+
#include <QObject>
6+
#include <QString>
7+
8+
struct DeviceInfo {
9+
QString serial;
10+
QString status;
11+
QString model;
12+
QString androidSdkVersion;
13+
QString androidVersion;
14+
};
15+
16+
class DeviceListWorker : public QObject
17+
{
18+
Q_OBJECT
19+
public:
20+
explicit DeviceListWorker(QObject *parent = nullptr);
21+
void listDevices();
22+
signals:
23+
void finished();
24+
void devicesListed(const QList<DeviceInfo> &devices);
25+
void error(const QString &message);
26+
void started();
27+
private:
28+
DeviceInfo parseDeviceLine(const QString &line);
29+
QString getDeviceProperty(const QString &serial, const QString &property);
30+
};
31+
32+
#endif // DEVICELISTWORKER_H
33+

0 commit comments

Comments
 (0)