1
0
forked from BRT/arc
arc/android/adb/AdbUtils.cpp
slava 59cef50ad3 Add enhanced account and transaction handling features
Refactored code to improve account and transaction data parsing and management, introducing support for additional fields like card numbers and account statuses. Added new utilities for database connections, device-specific screenshot handling, and XML parsing for enriched account and transaction details.
2025-05-07 14:15:08 +07:00

222 lines
8.7 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) {
// TODO убрать логирование в xml файл
QProcess process;
QString 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));
process.start("sh", {"-c", xml});
process.waitForFinished();
if (false) {
// 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 screen_%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::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;
}