Refactor ADB utilities to use dynamic adb paths and streamline processes.
Updated all ADB operations to use the dynamically determined adb path for better platform compatibility. Consolidated redundant process-handling code using a new `startProcess` helper method to simplify and standardize command execution. Enhanced `getScreenDumpAsXml` and related functions to improve modularity and maintainability.
This commit is contained in:
parent
b8b2b38f8a
commit
6988794657
@ -9,12 +9,36 @@ AdbUtils::AdbUtils(QObject *parent) : QObject(parent) {
|
|||||||
|
|
||||||
QString AdbUtils::adbPath() {
|
QString AdbUtils::adbPath() {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
return QCoreApplication::applicationDirPath() + "/tools/adb/adb.exe";
|
return QCoreApplication::applicationDirPath() + "/tools/adb/windows/adb.exe";
|
||||||
#else
|
#else
|
||||||
return QCoreApplication::applicationDirPath() + "/tools/adb/macos/adb";
|
return QCoreApplication::applicationDirPath() + "/tools/adb/macos/adb";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AdbUtils::startProcess(const QString &cmd, QString *stdOut = nullptr, QString *stdErr = nullptr) {
|
||||||
|
QProcess process;
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
process.start("cmd.exe", {"/C", cmd});
|
||||||
|
#else
|
||||||
|
process.start("sh", {"-c", cmd});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!process.waitForFinished() ||
|
||||||
|
process.exitStatus() != QProcess::NormalExit ||
|
||||||
|
process.exitCode() != 0) {
|
||||||
|
if (stdErr) {
|
||||||
|
*stdErr = QString::fromUtf8(process.readAllStandardError());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stdOut) {
|
||||||
|
*stdOut = QString::fromUtf8(process.readAllStandardOutput());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// adb shell dumpsys package ru.rshb.dbo | grep permission
|
// adb shell dumpsys package ru.rshb.dbo | grep permission
|
||||||
// TODO доделать обработку пермишинов
|
// TODO доделать обработку пермишинов
|
||||||
// adb shell pm revoke ru.rshb.dbo android.permission.WRITE_CONTACTS; adb shell pm revoke ru.rshb.dbo android.permission.READ_CONTACTS; adb shell pm revoke ru.rshb.dbo android.permission.ACCESS_COARSE_LOCATION; adb shell pm revoke ru.rshb.dbo android.permission.ACCESS_FINE_LOCATION
|
// adb shell pm revoke ru.rshb.dbo android.permission.WRITE_CONTACTS; adb shell pm revoke ru.rshb.dbo android.permission.READ_CONTACTS; adb shell pm revoke ru.rshb.dbo android.permission.ACCESS_COARSE_LOCATION; adb shell pm revoke ru.rshb.dbo android.permission.ACCESS_FINE_LOCATION
|
||||||
@ -26,7 +50,7 @@ QString AdbUtils::adbPath() {
|
|||||||
*/
|
*/
|
||||||
QList<QPair<QString, QString> > AdbUtils::getListDevices() {
|
QList<QPair<QString, QString> > AdbUtils::getListDevices() {
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start("adb", {"devices"});
|
process.start(adbPath(), {"devices"});
|
||||||
process.waitForFinished();
|
process.waitForFinished();
|
||||||
|
|
||||||
const QString output = process.readAllStandardOutput();
|
const QString output = process.readAllStandardOutput();
|
||||||
@ -56,7 +80,7 @@ QList<QPair<QString, QString> > AdbUtils::getListDevices() {
|
|||||||
|
|
||||||
QString AdbUtils::tryToGetRunningAppPid(const QString &deviceId, const QString &packageName) {
|
QString AdbUtils::tryToGetRunningAppPid(const QString &deviceId, const QString &packageName) {
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start("adb", {
|
process.start(adbPath(), {
|
||||||
"-s", deviceId,
|
"-s", deviceId,
|
||||||
"shell", "pidof", packageName
|
"shell", "pidof", packageName
|
||||||
});
|
});
|
||||||
@ -67,7 +91,7 @@ QString AdbUtils::tryToGetRunningAppPid(const QString &deviceId, const QString &
|
|||||||
|
|
||||||
bool AdbUtils::tryToStartApplication(const QString &deviceId, const QString &packageName) {
|
bool AdbUtils::tryToStartApplication(const QString &deviceId, const QString &packageName) {
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start("adb", {
|
process.start(adbPath(), {
|
||||||
"-s", deviceId,
|
"-s", deviceId,
|
||||||
"shell", "monkey",
|
"shell", "monkey",
|
||||||
"-p", packageName,
|
"-p", packageName,
|
||||||
@ -90,7 +114,7 @@ bool AdbUtils::tryToStartApplication(const QString &deviceId, const QString &pac
|
|||||||
|
|
||||||
bool AdbUtils::tryToKillApplication(const QString &deviceId, const QString &packageName) {
|
bool AdbUtils::tryToKillApplication(const QString &deviceId, const QString &packageName) {
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start("adb", {
|
process.start(adbPath(), {
|
||||||
"-s", deviceId,
|
"-s", deviceId,
|
||||||
"shell", "am",
|
"shell", "am",
|
||||||
"force-stop", packageName
|
"force-stop", packageName
|
||||||
@ -101,65 +125,73 @@ bool AdbUtils::tryToKillApplication(const QString &deviceId, const QString &pack
|
|||||||
|
|
||||||
// idx - временный лог
|
// idx - временный лог
|
||||||
// adb -s 6edc4a47 shell 'uiautomator dump /sdcard/uidump.xml' && adb -s 6edc4a47 pull /sdcard/uidump.xml step_1.xml && adb -s 6edc4a47 shell 'rm /sdcard/uidump.xml'
|
// adb -s 6edc4a47 shell 'uiautomator dump /sdcard/uidump.xml' && adb -s 6edc4a47 pull /sdcard/uidump.xml step_1.xml && adb -s 6edc4a47 shell 'rm /sdcard/uidump.xml'
|
||||||
QString AdbUtils::getScreenDumpAsXml(const QString &deviceId, const int idx, const bool screenshot) {
|
QString AdbUtils::getScreenDumpAsXml(const QString &deviceId, int idx, bool screenshot) {
|
||||||
// TODO убрать логирование в xml файл
|
const QString adb = adbPath();
|
||||||
// "adb -s %1 pull /sdcard/uidump.xml step_%2.xml && "
|
QString output;
|
||||||
QProcess process;
|
|
||||||
QString xml;
|
// 1. Dump UI hierarchy
|
||||||
if (screenshot) {
|
QString dumpCmd = QString("%1 -s %2 shell uiautomator dump /sdcard/uidump.xml").arg(adb, deviceId);
|
||||||
xml = QString(
|
if (!startProcess(dumpCmd)) {
|
||||||
"adb -s %1 shell 'uiautomator dump /sdcard/uidump.xml' && "
|
qWarning() << "Failed to dump UI hierarchy.";
|
||||||
"adb -s %1 pull /sdcard/uidump.xml step_%2.xml && "
|
return {};
|
||||||
"adb -s %1 shell 'cat /sdcard/uidump.xml' && "
|
|
||||||
"adb -s %1 shell 'rm /sdcard/uidump.xml'"
|
|
||||||
).arg(deviceId, QString::number(idx));
|
|
||||||
} else {
|
|
||||||
xml = QString(
|
|
||||||
"adb -s %1 shell 'uiautomator dump /sdcard/uidump.xml' && "
|
|
||||||
"adb -s %1 shell 'cat /sdcard/uidump.xml' && "
|
|
||||||
"adb -s %1 shell 'rm /sdcard/uidump.xml'"
|
|
||||||
).arg(deviceId);
|
|
||||||
}
|
}
|
||||||
|
// 2. Optionally pull and save the XML file
|
||||||
process.start("sh", {"-c", xml});
|
|
||||||
process.waitForFinished();
|
|
||||||
|
|
||||||
if (screenshot) {
|
if (screenshot) {
|
||||||
// TODO делаем скрин, убрать потом
|
QString pullCmd = QString("%1 -s %2 pull /sdcard/uidump.xml step_%3.xml").arg(adb, deviceId).arg(idx);
|
||||||
// adb -s 6edc4a47 shell 'screencap -p /sdcard/screen.png' && adb -s 6edc4a47 pull /sdcard/screen.png screen_step_1.png && adb -s 6edc4a47 shell 'rm /sdcard/screen.png'
|
if (!startProcess(pullCmd)) {
|
||||||
QProcess processScreenshot;
|
qWarning() << "Failed to pull UIDump XML.";
|
||||||
QString screenshot = QString(
|
return {};
|
||||||
"adb -s %1 shell 'screencap -p /sdcard/screen.png' && "
|
}
|
||||||
"adb -s %1 pull /sdcard/screen.png screen_step_%2.png && "
|
|
||||||
"adb -s %1 shell 'rm /sdcard/screen.png'"
|
|
||||||
).arg(deviceId, QString::number(idx));
|
|
||||||
processScreenshot.start("sh", {"-c", screenshot});
|
|
||||||
processScreenshot.waitForFinished();
|
|
||||||
}
|
}
|
||||||
|
// 3. Read the XML content
|
||||||
// чтобы убедиться, что мы прочитали без ошибок
|
QString catCmd = QString("%1 -s %2 shell cat /sdcard/uidump.xml").arg(adb, deviceId);
|
||||||
if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) {
|
QString xmlOut;
|
||||||
|
if (!startProcess(catCmd, &xmlOut)) {
|
||||||
|
qWarning() << "Failed to read UIDump XML.";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray xmlBytes = process.readAllStandardOutput();
|
// 4. Remove temp XML file
|
||||||
// UI hierchary dumped to: /sdcard/uidump.xml\n
|
QString rmCmd = QString("%1 -s %2 shell rm /sdcard/uidump.xml").arg(adb, deviceId);
|
||||||
if (const int startIndex = xmlBytes.indexOf("<?xml"); startIndex != -1) {
|
startProcess(rmCmd); // неважно, успешна ли команда
|
||||||
xmlBytes = xmlBytes.mid(startIndex); // Обрезаем всё до "<?xml"
|
|
||||||
|
// 5. Screenshot (if needed)
|
||||||
|
if (screenshot) {
|
||||||
|
QString shotCmds[] = {
|
||||||
|
QString("%1 -s %2 shell screencap -p /sdcard/screen.png").arg(adb, deviceId),
|
||||||
|
QString("%1 -s %2 pull /sdcard/screen.png screen_step_%3.png").arg(adb, deviceId).arg(idx),
|
||||||
|
QString("%1 -s %2 shell rm /sdcard/screen.png").arg(adb, deviceId)
|
||||||
|
};
|
||||||
|
for (const QString &cmd : shotCmds) {
|
||||||
|
startProcess(cmd); // ошибки игнорируем для скриншота
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Обрезка к началу XML
|
||||||
|
QByteArray xmlBytes = xmlOut.toUtf8();
|
||||||
|
if (const int start = xmlBytes.indexOf("<?xml"); start != -1) {
|
||||||
|
xmlBytes = xmlBytes.mid(start);
|
||||||
}
|
}
|
||||||
return QString::fromUtf8(xmlBytes);
|
return QString::fromUtf8(xmlBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AdbUtils::takeScreenshot(const QString &deviceId, const QString &name) {
|
bool AdbUtils::takeScreenshot(const QString &deviceId, const QString &name) {
|
||||||
QProcess process;
|
const QString adb = adbPath();
|
||||||
QString screenshot = QString(
|
QStringList commands = {
|
||||||
"adb -s %1 shell 'screencap -p /sdcard/screen.png' && "
|
QString("%1 -s %2 shell screencap -p /sdcard/screen.png").arg(adb, deviceId),
|
||||||
"adb -s %1 pull /sdcard/screen.png %2.png && "
|
QString("%1 -s %2 pull /sdcard/screen.png %3.png").arg(adb, deviceId, name),
|
||||||
"adb -s %1 shell 'rm /sdcard/screen.png'"
|
QString("%1 -s %2 shell rm /sdcard/screen.png").arg(adb, deviceId)
|
||||||
).arg(deviceId, name);
|
};
|
||||||
process.start("sh", {"-c", screenshot});
|
|
||||||
process.waitForFinished();
|
for (const QString &cmd: commands) {
|
||||||
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
|
QString stderr;
|
||||||
|
if (!startProcess(cmd, nullptr, &stderr)) {
|
||||||
|
qWarning() << "ADB command failed:" << cmd;
|
||||||
|
qWarning() << "Error:" << stderr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AdbUtils::takeXmlDump(const QString &deviceId, const QString &name) {
|
bool AdbUtils::takeXmlDump(const QString &deviceId, const QString &name) {
|
||||||
@ -172,26 +204,19 @@ bool AdbUtils::takeXmlDump(const QString &deviceId, const QString &name) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (const QString &cmd: commands) {
|
for (const QString &cmd: commands) {
|
||||||
QProcess process;
|
QString stderr;
|
||||||
#ifdef Q_OS_WIN
|
if (!startProcess(cmd, nullptr, &stderr)) {
|
||||||
process.start("cmd.exe", {"/C", cmd});
|
|
||||||
#else
|
|
||||||
process.start("sh", {"-c", cmd});
|
|
||||||
#endif
|
|
||||||
if (!process.waitForFinished() ||
|
|
||||||
process.exitStatus() != QProcess::NormalExit ||
|
|
||||||
process.exitCode() != 0) {
|
|
||||||
qWarning() << "ADB command failed:" << cmd;
|
qWarning() << "ADB command failed:" << cmd;
|
||||||
|
qWarning() << "Error:" << stderr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AdbUtils::makeTap(const QString &deviceId, const int x, const int y) {
|
bool AdbUtils::makeTap(const QString &deviceId, const int x, const int y) {
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start("adb", {
|
process.start(adbPath(), {
|
||||||
"-s", deviceId,
|
"-s", deviceId,
|
||||||
"shell", "input",
|
"shell", "input",
|
||||||
"tap", QString::number(x), QString::number(y)
|
"tap", QString::number(x), QString::number(y)
|
||||||
@ -201,21 +226,28 @@ bool AdbUtils::makeTap(const QString &deviceId, const int x, const int y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AdbUtils::enableAdbIMEKeyboard(const QString &deviceId) {
|
bool AdbUtils::enableAdbIMEKeyboard(const QString &deviceId) {
|
||||||
QProcess process;
|
const QString adb = adbPath();
|
||||||
QString command = QString(
|
QStringList commands = {
|
||||||
"adb -s %1 shell ime enable com.android.adbkeyboard/.AdbIME "
|
QString("%1 -s %2 shell ime enable com.android.adbkeyboard/.AdbIME").arg(adb, deviceId),
|
||||||
"&& adb -s %1 shell ime set com.android.adbkeyboard/.AdbIME"
|
QString("%1 -s %2 shell ime set com.android.adbkeyboard/.AdbIME").arg(adb, deviceId)
|
||||||
).arg(deviceId);
|
};
|
||||||
process.start(command);
|
|
||||||
process.waitForFinished();
|
for (const QString &cmd: commands) {
|
||||||
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
|
QString stderr;
|
||||||
|
if (!startProcess(cmd, nullptr, &stderr)) {
|
||||||
|
qWarning() << "ADB command failed:" << cmd;
|
||||||
|
qWarning() << "Error:" << stderr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AdbUtils::inputAdbIMEText(const QString &deviceId, const QString &text) {
|
bool AdbUtils::inputAdbIMEText(const QString &deviceId, const QString &text) {
|
||||||
QProcess process;
|
QProcess process;
|
||||||
QString command = QString(
|
QString command = QString(
|
||||||
"adb -s %1 shell am broadcast -a ADB_INPUT_TEXT --es msg '%2'"
|
"%1 -s %2 shell am broadcast -a ADB_INPUT_TEXT --es msg '%3'"
|
||||||
).arg(deviceId, text);
|
).arg(adbPath(), deviceId, text);
|
||||||
process.start(command);
|
process.start(command);
|
||||||
process.waitForFinished();
|
process.waitForFinished();
|
||||||
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
|
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
|
||||||
@ -224,8 +256,8 @@ bool AdbUtils::inputAdbIMEText(const QString &deviceId, const QString &text) {
|
|||||||
bool AdbUtils::disableAdbIMEKeyboard(const QString &deviceId) {
|
bool AdbUtils::disableAdbIMEKeyboard(const QString &deviceId) {
|
||||||
QProcess process;
|
QProcess process;
|
||||||
QString command = QString(
|
QString command = QString(
|
||||||
"adb -s %1 shell ime disable com.android.adbkeyboard/.AdbIME"
|
"%1 -s %2 shell ime disable com.android.adbkeyboard/.AdbIME"
|
||||||
).arg(deviceId);
|
).arg(adbPath(), deviceId);
|
||||||
process.start(command);
|
process.start(command);
|
||||||
process.waitForFinished();
|
process.waitForFinished();
|
||||||
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
|
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
|
||||||
@ -234,7 +266,7 @@ bool AdbUtils::disableAdbIMEKeyboard(const QString &deviceId) {
|
|||||||
bool AdbUtils::makeSwipe(const QString &deviceId, const int x1, const int y1, const int x2, const int y2) {
|
bool AdbUtils::makeSwipe(const QString &deviceId, const int x1, const int y1, const int x2, const int y2) {
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start(
|
process.start(
|
||||||
"adb",
|
adbPath(),
|
||||||
{
|
{
|
||||||
"-s", deviceId,
|
"-s", deviceId,
|
||||||
"shell", "input",
|
"shell", "input",
|
||||||
@ -247,7 +279,7 @@ bool AdbUtils::makeSwipe(const QString &deviceId, const int x1, const int y1, co
|
|||||||
|
|
||||||
bool AdbUtils::inputText(const QString &deviceId, const QString &text) {
|
bool AdbUtils::inputText(const QString &deviceId, const QString &text) {
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start("adb", {
|
process.start(adbPath(), {
|
||||||
"-s", deviceId,
|
"-s", deviceId,
|
||||||
"shell", "input",
|
"shell", "input",
|
||||||
"text", text
|
"text", text
|
||||||
@ -258,7 +290,7 @@ bool AdbUtils::inputText(const QString &deviceId, const QString &text) {
|
|||||||
|
|
||||||
bool AdbUtils::goBack(const QString &deviceId) {
|
bool AdbUtils::goBack(const QString &deviceId) {
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start("adb", {
|
process.start(adbPath(), {
|
||||||
"-s", deviceId,
|
"-s", deviceId,
|
||||||
"shell", "input",
|
"shell", "input",
|
||||||
"keyevent", "4"
|
"keyevent", "4"
|
||||||
@ -269,7 +301,7 @@ bool AdbUtils::goBack(const QString &deviceId) {
|
|||||||
|
|
||||||
QSet<QString> AdbUtils::getListApps(const QString &deviceId) {
|
QSet<QString> AdbUtils::getListApps(const QString &deviceId) {
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start("adb", {
|
process.start(adbPath(), {
|
||||||
"-s", deviceId,
|
"-s", deviceId,
|
||||||
"shell", "pm list",
|
"shell", "pm list",
|
||||||
"packages", "-3"
|
"packages", "-3"
|
||||||
|
|||||||
@ -40,4 +40,7 @@ public:
|
|||||||
static bool goBack(const QString &deviceId);
|
static bool goBack(const QString &deviceId);
|
||||||
|
|
||||||
static QSet<QString> getListApps(const QString &deviceId);
|
static QSet<QString> getListApps(const QString &deviceId);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool startProcess(const QString &cmd, QString *stdOut, QString *stdErr);
|
||||||
};
|
};
|
||||||
|
|||||||
Binary file not shown.
8
main.cpp
8
main.cpp
@ -145,11 +145,9 @@ int main(int argc, char *argv[]) {
|
|||||||
// 79641815146 - Мама Альфа
|
// 79641815146 - Мама Альфа
|
||||||
// 79199196105 - Папа рсхб
|
// 79199196105 - Папа рсхб
|
||||||
|
|
||||||
// startNetworkService(app);
|
startNetworkService(app);
|
||||||
// startDeviceScreener(app);
|
startDeviceScreener(app);
|
||||||
// startEventHandler(app);
|
startEventHandler(app);
|
||||||
|
|
||||||
AdbUtils::takeXmlDump("29301FDH20036X", "test");
|
|
||||||
|
|
||||||
MainWindow window;
|
MainWindow window;
|
||||||
window.show();
|
window.show();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user