1
0
forked from BRT/arc
arc/android/adb/AdbUtils.cpp
trnsmkot b766725b1a Refactor scripts and add enhanced error handling
Revised scripts for payments and history retrieval, introducing improved error management with screenshots for debugging. Added a new LoginAndCheckAccountsScript for account validation, streamlined multi-threading, and updated application logic for clarity and reliability.
2025-05-30 22:16:25 +07:00

270 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "AdbUtils.h"
#include <QProcess>
#include <qDebug>
#include <QString>
AdbUtils::AdbUtils(QObject *parent) : QObject(parent) {
}
// adb shell dumpsys package ru.rshb.dbo | grep permission
// 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 cmd appops set ru.rshb.dbo POST_NOTIFICATION ignore
/**
* Возвращает список найденных устройств в виде пар (ID устройства и Статус)
* @return [(id, status), ...]
*/
QList<QPair<QString, QString> > AdbUtils::getListDevices() {
QProcess process;
process.start("adb", {"devices"});
process.waitForFinished();
const QString output = process.readAllStandardOutput();
QList<QPair<QString, QString> > devices;
const QStringList lines = output.split('\n');
for (int i = 1; i < lines.size(); ++i) {
QString line = lines.at(i).trimmed();
if (line.isEmpty()) {
continue;
}
/**
* device — устройство готово к использованию.
* offline — устройство подключено, но не может быть использовано.
* unauthorized — устройство не авторизовано для работы с ADB (нужно подтвердить запрос на подключение на самом устройстве).
* recovery — устройство в режиме восстановления.
*/
if (QStringList parts = line.split('\t'); parts.size() == 2) {
const QString &id = parts.at(0);
const QString &status = parts.at(1);
devices.append(qMakePair(id, status));
}
}
return devices;
}
QString AdbUtils::tryToGetRunningAppPid(const QString &deviceId, const QString &packageName) {
QProcess process;
process.start("adb", {
"-s", deviceId,
"shell", "pidof", packageName
});
process.waitForFinished();
QString pid = process.readAllStandardOutput();
return pid.replace("\n", "");
}
bool AdbUtils::tryToStartApplication(const QString &deviceId, const QString &packageName) {
QProcess process;
process.start("adb", {
"-s", deviceId,
"shell", "monkey",
"-p", packageName,
"-c", "android.intent.category.LAUNCHER",
"1"
});
process.waitForFinished();
const QString output = process.readAllStandardOutput();
// Если процесс запустился, там будет такая строка.
// Если нет, то: "** No activities found to run, monkey aborted."
if (output.contains("Events injected: 1")) {
return true;
}
// Тут надо в логи писать, почему не стартует
qDebug() << "Start app output:" << output;
return false;
}
bool AdbUtils::tryToKillApplication(const QString &deviceId, const QString &packageName) {
QProcess process;
process.start("adb", {
"-s", deviceId,
"shell", "am",
"force-stop", packageName
});
process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
}
// 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'
QString AdbUtils::getScreenDumpAsXml(const QString &deviceId, const int idx, const bool screenshot) {
// TODO убрать логирование в xml файл
// "adb -s %1 pull /sdcard/uidump.xml step_%2.xml && "
QProcess process;
QString xml;
if (screenshot) {
xml = QString(
"adb -s %1 shell 'uiautomator dump /sdcard/uidump.xml' && "
"adb -s %1 pull /sdcard/uidump.xml step_%2.xml && "
"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);
}
process.start("sh", {"-c", xml});
process.waitForFinished();
if (screenshot) {
// TODO делаем скрин, убрать потом
// 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'
QProcess processScreenshot;
QString screenshot = QString(
"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();
}
// чтобы убедиться, что мы прочитали без ошибок
if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) {
return {};
}
QByteArray xmlBytes = process.readAllStandardOutput();
// UI hierchary dumped to: /sdcard/uidump.xml\n
if (const int startIndex = xmlBytes.indexOf("<?xml"); startIndex != -1) {
xmlBytes = xmlBytes.mid(startIndex); // Обрезаем всё до "<?xml"
}
return QString::fromUtf8(xmlBytes);
}
bool AdbUtils::takeScreenshot(const QString &deviceId, const QString &name) {
QProcess process;
QString screenshot = QString(
"adb -s %1 shell 'screencap -p /sdcard/screen.png' && "
"adb -s %1 pull /sdcard/screen.png %2.png && "
"adb -s %1 shell 'rm /sdcard/screen.png'"
).arg(deviceId, name);
process.start("sh", {"-c", screenshot});
process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
}
bool AdbUtils::takeXmlDump(const QString &deviceId, const QString &name) {
QProcess process;
QString xml = QString(
"adb -s %1 shell 'uiautomator dump /sdcard/uidump.xml' && "
"adb -s %1 pull /sdcard/uidump.xml %2.xml && "
"adb -s %1 shell 'cat /sdcard/uidump.xml' && "
"adb -s %1 shell 'rm /sdcard/uidump.xml'"
).arg(deviceId, name);
process.start("sh", {"-c", xml});
process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
}
bool AdbUtils::makeTap(const QString &deviceId, const int x, const int y) {
QProcess process;
process.start("adb", {
"-s", deviceId,
"shell", "input",
"tap", QString::number(x), QString::number(y)
});
process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
}
bool AdbUtils::enableAdbIMEKeyboard(const QString &deviceId) {
QProcess process;
QString command = QString(
"adb -s %1 shell ime enable com.android.adbkeyboard/.AdbIME "
"&& adb -s %1 shell ime set com.android.adbkeyboard/.AdbIME"
).arg(deviceId);
process.start(command);
process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
}
bool AdbUtils::inputAdbIMEText(const QString &deviceId, const QString &text) {
QProcess process;
QString command = QString(
"adb -s %1 shell am broadcast -a ADB_INPUT_TEXT --es msg '%2'"
).arg(deviceId, text);
process.start(command);
process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
}
bool AdbUtils::disableAdbIMEKeyboard(const QString &deviceId) {
QProcess process;
QString command = QString(
"adb -s %1 shell ime disable com.android.adbkeyboard/.AdbIME"
).arg(deviceId);
process.start(command);
process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
}
bool AdbUtils::makeSwipe(const QString &deviceId, const int x1, const int y1, const int x2, const int y2) {
QProcess process;
process.start(
"adb",
{
"-s", deviceId,
"shell", "input",
"swipe", QString("%1 %2 %3 %4").arg(x1).arg(y1).arg(x2).arg(y2)
}
);
process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
}
bool AdbUtils::inputText(const QString &deviceId, const QString &text) {
QProcess process;
process.start("adb", {
"-s", deviceId,
"shell", "input",
"text", text
});
process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
}
bool AdbUtils::goBack(const QString &deviceId) {
QProcess process;
process.start("adb", {
"-s", deviceId,
"shell", "input",
"keyevent", "4"
});
process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
}
QSet<QString> AdbUtils::getListApps(const QString &deviceId) {
QProcess process;
process.start("adb", {
"-s", deviceId,
"shell", "pm list",
"packages", "-3"
});
process.waitForFinished();
const QString output = process.readAllStandardOutput();
QSet<QString> apps;
const QStringList lines = output.split('\n');
for (int i = 0; i < lines.size(); ++i) {
QString line = lines.at(i).trimmed().replace("package:", "");
if (line.isEmpty()) {
continue;
}
apps.insert(line);
}
return apps;
}