Add closeGooglePlayBannerIfVisible to handle Google Play update banners across scripts:
- Integrate banner dismissal in retry loops for XML parsing in payment and profile scripts. - Add detection logic for permission deny buttons and update banner handling in `ScreenXmlParser`. - Ensure reliable operation during input field detection, transactions fetching, and confirmation screens.
This commit is contained in:
parent
d480cc51b0
commit
f200eae2bd
@ -295,4 +295,26 @@ void CommonScript::stop() {
|
|||||||
m_running = false;
|
m_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CommonScript::closeGooglePlayBannerIfVisible(
|
||||||
|
const QString &deviceId, const int width, const int height
|
||||||
|
) {
|
||||||
|
// 1. Системный диалог запроса разрешения Android (permissioncontroller) — тапаем "ЗАПРЕТИТЬ"
|
||||||
|
if (Node denyBtn = xmlScreenParser.tryToFindSystemPermissionDenyButton(); !denyBtn.isEmpty()) {
|
||||||
|
qDebug() << "[Dushanbe] System permission dialog detected mid-task, tapping 'ЗАПРЕТИТЬ'...";
|
||||||
|
AdbUtils::makeTap(deviceId, denyBtn.x(), denyBtn.y());
|
||||||
|
QThread::msleep(1500);
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Google Play in-app update bottom sheet
|
||||||
|
Node gpNode = xmlScreenParser.tryToFindGooglePlayBanner(width, height);
|
||||||
|
if (gpNode.isEmpty()) return false;
|
||||||
|
qDebug() << "[Dushanbe] Google Play update banner detected mid-task, closing...";
|
||||||
|
AdbUtils::makeTap(deviceId, gpNode.x(), gpNode.y());
|
||||||
|
QThread::msleep(1500);
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Dushanbe
|
} // namespace Dushanbe
|
||||||
|
|||||||
@ -47,6 +47,12 @@ protected:
|
|||||||
|
|
||||||
void createBankProfileIfNeeded(const QString &deviceId, const QString &appCode, double parsedBalance = -1.0);
|
void createBankProfileIfNeeded(const QString &deviceId, const QString &appCode, double parsedBalance = -1.0);
|
||||||
|
|
||||||
|
// Если виден баннер Google Play "Доступно обновление" — закрывает его и перепарсивает XML.
|
||||||
|
// Безопасно вызывать на любом экране; возвращает true если баннер был закрыт.
|
||||||
|
bool closeGooglePlayBannerIfVisible(
|
||||||
|
const QString &deviceId, int width, int height
|
||||||
|
);
|
||||||
|
|
||||||
bool m_running = true;
|
bool m_running = true;
|
||||||
ScreenXmlParser xmlScreenParser;
|
ScreenXmlParser xmlScreenParser;
|
||||||
int m_counter = 0;
|
int m_counter = 0;
|
||||||
|
|||||||
@ -288,6 +288,7 @@ void GetLastTransactionsScript::doStart() {
|
|||||||
bool historyLoaded = false;
|
bool historyLoaded = false;
|
||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight);
|
||||||
|
|
||||||
// Проверяем диалог "Ошибка" — нажимаем "ОК" и обновляем свайпом вниз
|
// Проверяем диалог "Ошибка" — нажимаем "ОК" и обновляем свайпом вниз
|
||||||
if (!xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Ошибка")).isEmpty()) {
|
if (!xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Ошибка")).isEmpty()) {
|
||||||
@ -390,6 +391,7 @@ void GetLastTransactionsScript::doStart() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight);
|
||||||
|
|
||||||
// Верх нижнего меню: минимальный y1() среди табов и FAB "Сканировать".
|
// Верх нижнего меню: минимальный y1() среди табов и FAB "Сканировать".
|
||||||
// Тап по строке с y >= navTopY - navMargin промахивается и попадает в FAB/таб.
|
// Тап по строке с y >= navTopY - navMargin промахивается и попадает в FAB/таб.
|
||||||
@ -632,6 +634,7 @@ void GetLastTransactionsScript::doStart() {
|
|||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
if (interrupted()) { m_error = "Interrupted"; emit finishedWithResult(m_error); return; }
|
if (interrupted()) { m_error = "Interrupted"; emit finishedWithResult(m_error); return; }
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight);
|
||||||
for (const Node &n : xmlScreenParser.findAllNodes()) {
|
for (const Node &n : xmlScreenParser.findAllNodes()) {
|
||||||
if (!n.contentDesc.contains(QString::fromUtf8("Успешный платеж"))) continue;
|
if (!n.contentDesc.contains(QString::fromUtf8("Успешный платеж"))) continue;
|
||||||
if (!n.contentDesc.contains(QString::fromUtf8("Дата:"))) continue;
|
if (!n.contentDesc.contains(QString::fromUtf8("Дата:"))) continue;
|
||||||
|
|||||||
@ -82,6 +82,7 @@ void GetProfileInfoScript::doStart() {
|
|||||||
bool sideMenuFound = false;
|
bool sideMenuFound = false;
|
||||||
for (int attempt = 0; attempt < 5; ++attempt) {
|
for (int attempt = 0; attempt < 5; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight);
|
||||||
if (xmlScreenParser.isSideMenu()) {
|
if (xmlScreenParser.isSideMenu()) {
|
||||||
sideMenuFound = true;
|
sideMenuFound = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -166,6 +166,7 @@ void PayByCardScript::makePayment(
|
|||||||
Node cardTransferBtn;
|
Node cardTransferBtn;
|
||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
cardTransferBtn = xmlScreenParser.findNodeByContentDesc(
|
cardTransferBtn = xmlScreenParser.findNodeByContentDesc(
|
||||||
QString::fromUtf8("DC (по номеру карты)"), true);
|
QString::fromUtf8("DC (по номеру карты)"), true);
|
||||||
if (!cardTransferBtn.isEmpty()) {
|
if (!cardTransferBtn.isEmpty()) {
|
||||||
@ -193,6 +194,7 @@ void PayByCardScript::makePayment(
|
|||||||
bool inputScreenLoaded = false;
|
bool inputScreenLoaded = false;
|
||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
Node editText = xmlScreenParser.findEditTextByHint(
|
Node editText = xmlScreenParser.findEditTextByHint(
|
||||||
QString::fromUtf8("Номер карты получателя"));
|
QString::fromUtf8("Номер карты получателя"));
|
||||||
if (editText.isEmpty()) {
|
if (editText.isEmpty()) {
|
||||||
@ -233,6 +235,7 @@ void PayByCardScript::makePayment(
|
|||||||
Node sumEditText;
|
Node sumEditText;
|
||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
sumEditText = xmlScreenParser.findEditTextByHint(QString::fromUtf8("Сумма"));
|
sumEditText = xmlScreenParser.findEditTextByHint(QString::fromUtf8("Сумма"));
|
||||||
if (!sumEditText.isEmpty()) break;
|
if (!sumEditText.isEmpty()) break;
|
||||||
qDebug() << "[Dushanbe::PayByCard] Waiting for sum input, attempt" << attempt + 1 << "/ 10";
|
qDebug() << "[Dushanbe::PayByCard] Waiting for sum input, attempt" << attempt + 1 << "/ 10";
|
||||||
@ -301,6 +304,7 @@ void PayByCardScript::makePayment(
|
|||||||
bool oplatitFound = false;
|
bool oplatitFound = false;
|
||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
Node oplatitBtn = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Оплатить"));
|
Node oplatitBtn = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Оплатить"));
|
||||||
if (oplatitBtn.isEmpty()) {
|
if (oplatitBtn.isEmpty()) {
|
||||||
oplatitBtn = xmlScreenParser.findButtonNode(QString::fromUtf8("Оплатить"), false);
|
oplatitBtn = xmlScreenParser.findButtonNode(QString::fromUtf8("Оплатить"), false);
|
||||||
@ -330,6 +334,7 @@ void PayByCardScript::makePayment(
|
|||||||
bool confirmed = false;
|
bool confirmed = false;
|
||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
|
|
||||||
// Пин-код может появиться
|
// Пин-код может появиться
|
||||||
if (xmlScreenParser.isPinCodeScreen()) {
|
if (xmlScreenParser.isPinCodeScreen()) {
|
||||||
@ -370,6 +375,7 @@ void PayByCardScript::makePayment(
|
|||||||
bool success = false;
|
bool success = false;
|
||||||
for (int attempt = 0; attempt < 15; ++attempt) {
|
for (int attempt = 0; attempt < 15; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
|
|
||||||
// Пин-код
|
// Пин-код
|
||||||
if (xmlScreenParser.isPinCodeScreen()) {
|
if (xmlScreenParser.isPinCodeScreen()) {
|
||||||
|
|||||||
@ -163,6 +163,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
Node phoneTransferBtn;
|
Node phoneTransferBtn;
|
||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
phoneTransferBtn = xmlScreenParser.findNodeByContentDesc(
|
phoneTransferBtn = xmlScreenParser.findNodeByContentDesc(
|
||||||
QString::fromUtf8("DC (по номеру телефона)"), true);
|
QString::fromUtf8("DC (по номеру телефона)"), true);
|
||||||
if (!phoneTransferBtn.isEmpty()) {
|
if (!phoneTransferBtn.isEmpty()) {
|
||||||
@ -190,6 +191,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
bool inputScreenLoaded = false;
|
bool inputScreenLoaded = false;
|
||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
Node editText = xmlScreenParser.findEditTextByHint(
|
Node editText = xmlScreenParser.findEditTextByHint(
|
||||||
QString::fromUtf8("Номер телефона получателя"));
|
QString::fromUtf8("Номер телефона получателя"));
|
||||||
if (editText.isEmpty()) {
|
if (editText.isEmpty()) {
|
||||||
@ -234,6 +236,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
Node sumEditText;
|
Node sumEditText;
|
||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
sumEditText = xmlScreenParser.findEditTextByHint(QString::fromUtf8("Сумма"));
|
sumEditText = xmlScreenParser.findEditTextByHint(QString::fromUtf8("Сумма"));
|
||||||
if (!sumEditText.isEmpty()) break;
|
if (!sumEditText.isEmpty()) break;
|
||||||
qDebug() << "[Dushanbe::PayByPhone] Waiting for sum input, attempt" << attempt + 1 << "/ 10";
|
qDebug() << "[Dushanbe::PayByPhone] Waiting for sum input, attempt" << attempt + 1 << "/ 10";
|
||||||
@ -301,6 +304,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
bool oplatitFound = false;
|
bool oplatitFound = false;
|
||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
Node oplatitBtn = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Оплатить"));
|
Node oplatitBtn = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Оплатить"));
|
||||||
if (oplatitBtn.isEmpty()) {
|
if (oplatitBtn.isEmpty()) {
|
||||||
oplatitBtn = xmlScreenParser.findButtonNode(QString::fromUtf8("Оплатить"), false);
|
oplatitBtn = xmlScreenParser.findButtonNode(QString::fromUtf8("Оплатить"), false);
|
||||||
@ -328,6 +332,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
bool confirmed = false;
|
bool confirmed = false;
|
||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
|
|
||||||
if (xmlScreenParser.isPinCodeScreen()) {
|
if (xmlScreenParser.isPinCodeScreen()) {
|
||||||
qDebug() << "[Dushanbe::PayByPhone] PIN code screen, entering PIN...";
|
qDebug() << "[Dushanbe::PayByPhone] PIN code screen, entering PIN...";
|
||||||
@ -365,6 +370,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
bool success = false;
|
bool success = false;
|
||||||
for (int attempt = 0; attempt < 15; ++attempt) {
|
for (int attempt = 0; attempt < 15; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
|
|
||||||
if (xmlScreenParser.isPinCodeScreen()) {
|
if (xmlScreenParser.isPinCodeScreen()) {
|
||||||
qDebug() << "[Dushanbe::PayByPhone] PIN code screen (retry), entering PIN...";
|
qDebug() << "[Dushanbe::PayByPhone] PIN code screen (retry), entering PIN...";
|
||||||
|
|||||||
@ -497,4 +497,37 @@ Node ScreenXmlParser::findEditTextByHint(const QString &hint) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node ScreenXmlParser::tryToFindSystemPermissionDenyButton() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.resourceId == "com.android.permissioncontroller:id/permission_deny_button"
|
||||||
|
&& node.clickable) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.clickable && node.text.trimmed() == QString::fromUtf8("ЗАПРЕТИТЬ")) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Node ScreenXmlParser::tryToFindGooglePlayBanner(const int screenWidth, const int screenHeight) {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.contentDesc.contains("Закрыть диалоговое окно") && node.clickable) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.contentDesc.contains("Доступно обновление")) {
|
||||||
|
Node tapNode;
|
||||||
|
const int cx = screenWidth / 2;
|
||||||
|
const int cy = screenHeight / 20;
|
||||||
|
tapNode.setBounds(cx, cy, cx + 1, cy + 1);
|
||||||
|
return tapNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Dushanbe
|
} // namespace Dushanbe
|
||||||
|
|||||||
@ -115,6 +115,14 @@ public:
|
|||||||
// Находит EditText по hint
|
// Находит EditText по hint
|
||||||
Node findEditTextByHint(const QString &hint);
|
Node findEditTextByHint(const QString &hint);
|
||||||
|
|
||||||
|
// Находит кнопку закрытия Google Play in-app update bottom sheet
|
||||||
|
// ("com.android.vending" оверлей "Доступно обновление"), если он показан
|
||||||
|
Node tryToFindGooglePlayBanner(int screenWidth, int screenHeight);
|
||||||
|
|
||||||
|
// Находит кнопку "ЗАПРЕТИТЬ" в системном диалоге запроса разрешения Android
|
||||||
|
// (com.google.android.permissioncontroller). Возвращает пустой Node если диалог не виден.
|
||||||
|
Node tryToFindSystemPermissionDenyButton();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<Node> m_nodes;
|
QList<Node> m_nodes;
|
||||||
QDomElement m_xml;
|
QDomElement m_xml;
|
||||||
|
|||||||
@ -227,6 +227,16 @@ bool CommonScript::tryToCloseAllBannersOnHomePage(const QString &deviceId, const
|
|||||||
bool CommonScript::closeGooglePlayBannerIfVisible(
|
bool CommonScript::closeGooglePlayBannerIfVisible(
|
||||||
const QString &deviceId, const int width, const int height
|
const QString &deviceId, const int width, const int height
|
||||||
) {
|
) {
|
||||||
|
// 1. Системный диалог запроса разрешения Android (permissioncontroller) — тапаем "ЗАПРЕТИТЬ"
|
||||||
|
if (Node denyBtn = xmlScreenParser.tryToFindSystemPermissionDenyButton(); !denyBtn.isEmpty()) {
|
||||||
|
qDebug() << "[Ozon] System permission dialog detected mid-task, tapping 'ЗАПРЕТИТЬ'...";
|
||||||
|
AdbUtils::makeTap(deviceId, denyBtn.x(), denyBtn.y());
|
||||||
|
QThread::msleep(1500);
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Google Play in-app update bottom sheet
|
||||||
Node gpNode = xmlScreenParser.tryToFindGooglePlayBanner(width, height);
|
Node gpNode = xmlScreenParser.tryToFindGooglePlayBanner(width, height);
|
||||||
if (gpNode.isEmpty()) return false;
|
if (gpNode.isEmpty()) return false;
|
||||||
qDebug() << "[Ozon] Google Play update banner detected mid-task, closing...";
|
qDebug() << "[Ozon] Google Play update banner detected mid-task, closing...";
|
||||||
|
|||||||
@ -206,6 +206,7 @@ bool GetLastTransactionsScript::navigateToTransactionList(const DeviceInfo &devi
|
|||||||
AdbUtils::makeSwipe(m_deviceId, x, device.screenHeight - 200, x, 200, 100);
|
AdbUtils::makeSwipe(m_deviceId, x, device.screenHeight - 200, x, 200, 100);
|
||||||
QThread::msleep(1500);
|
QThread::msleep(1500);
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight);
|
||||||
|
|
||||||
allBtn = xmlScreenParser.findButtonNode("Все", false);
|
allBtn = xmlScreenParser.findButtonNode("Все", false);
|
||||||
if (!allBtn.isEmpty() && allBtn.y() > 0 && allBtn.y() < navBarTop) break;
|
if (!allBtn.isEmpty() && allBtn.y() > 0 && allBtn.y() < navBarTop) break;
|
||||||
@ -569,6 +570,7 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int
|
|||||||
for (int da = 0; da < 5; ++da) {
|
for (int da = 0; da < 5; ++da) {
|
||||||
if (QThread::currentThread()->isInterruptionRequested()) break;
|
if (QThread::currentThread()->isInterruptionRequested()) break;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight);
|
||||||
if (!xmlScreenParser.findNodeByContentDesc("Поделиться").isEmpty()) {
|
if (!xmlScreenParser.findNodeByContentDesc("Поделиться").isEmpty()) {
|
||||||
docLoaded = true;
|
docLoaded = true;
|
||||||
break;
|
break;
|
||||||
@ -750,6 +752,7 @@ void GetLastTransactionsScript::scanRecentTransactions(const DeviceInfo &device,
|
|||||||
AdbUtils::makeSwipe(m_deviceId, x, device.screenHeight - offset, x, offset);
|
AdbUtils::makeSwipe(m_deviceId, x, device.screenHeight - offset, x, offset);
|
||||||
QThread::msleep(1000);
|
QThread::msleep(1000);
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight);
|
||||||
txButtons = xmlScreenParser.findTransactionButtons(8);
|
txButtons = xmlScreenParser.findTransactionButtons(8);
|
||||||
if (i < txButtons.size() && txButtons[i].y() > 0 && txButtons[i].y() < navBarTop) break;
|
if (i < txButtons.size() && txButtons[i].y() > 0 && txButtons[i].y() < navBarTop) break;
|
||||||
}
|
}
|
||||||
@ -788,6 +791,7 @@ void GetLastTransactionsScript::scanRecentTransactions(const DeviceInfo &device,
|
|||||||
bool docLoaded = false;
|
bool docLoaded = false;
|
||||||
for (int da = 0; da < 15; ++da) {
|
for (int da = 0; da < 15; ++da) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight);
|
||||||
if (!xmlScreenParser.findNodeByContentDesc("Поделиться").isEmpty()) {
|
if (!xmlScreenParser.findNodeByContentDesc("Поделиться").isEmpty()) {
|
||||||
docLoaded = true;
|
docLoaded = true;
|
||||||
break;
|
break;
|
||||||
@ -860,6 +864,7 @@ void GetLastTransactionsScript::scanRecentTransactions(const DeviceInfo &device,
|
|||||||
bool docLoaded = false;
|
bool docLoaded = false;
|
||||||
for (int da = 0; da < 20; ++da) {
|
for (int da = 0; da < 20; ++da) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight);
|
||||||
if (!xmlScreenParser.findNodeByContentDesc("Поделиться").isEmpty()) {
|
if (!xmlScreenParser.findNodeByContentDesc("Поделиться").isEmpty()) {
|
||||||
docLoaded = true; break;
|
docLoaded = true; break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,6 +108,7 @@ void GetProfileInfoScript::doStart() {
|
|||||||
// Читаем XML профиля и проверяем что мы действительно там
|
// Читаем XML профиля и проверяем что мы действительно там
|
||||||
for (int attempt = 0; attempt < 5; ++attempt) {
|
for (int attempt = 0; attempt < 5; ++attempt) {
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight);
|
||||||
if (xmlScreenParser.isProfileScreen()) {
|
if (xmlScreenParser.isProfileScreen()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -176,6 +176,7 @@ void PayByCardScript::makePayment(
|
|||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
if (!checkApp()) return;
|
if (!checkApp()) return;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
Node title = xmlScreenParser.findTextNode("Платежи и переводы");
|
Node title = xmlScreenParser.findTextNode("Платежи и переводы");
|
||||||
if (!title.isEmpty()) titleSeen = true;
|
if (!title.isEmpty()) titleSeen = true;
|
||||||
cardBtn = xmlScreenParser.findButtonNode("По номеру карты", false);
|
cardBtn = xmlScreenParser.findButtonNode("По номеру карты", false);
|
||||||
@ -205,6 +206,7 @@ void PayByCardScript::makePayment(
|
|||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
if (!checkApp()) return;
|
if (!checkApp()) return;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
Node title = xmlScreenParser.findTextNode("Перевод по номеру карты");
|
Node title = xmlScreenParser.findTextNode("Перевод по номеру карты");
|
||||||
if (!title.isEmpty()) {
|
if (!title.isEmpty()) {
|
||||||
cardScreenLoaded = true;
|
cardScreenLoaded = true;
|
||||||
@ -231,6 +233,7 @@ void PayByCardScript::makePayment(
|
|||||||
qDebug() << "[PayByCard] Waiting for 'Номер карты получателя' input, attempt" << attempt + 1 << "/ 10";
|
qDebug() << "[PayByCard] Waiting for 'Номер карты получателя' input, attempt" << attempt + 1 << "/ 10";
|
||||||
QThread::msleep(1500);
|
QThread::msleep(1500);
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cardInput.isEmpty()) {
|
if (cardInput.isEmpty()) {
|
||||||
@ -249,6 +252,7 @@ void PayByCardScript::makePayment(
|
|||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
if (!checkApp()) return;
|
if (!checkApp()) return;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
sumInput = xmlScreenParser.findEditTextByHint("Сумма от");
|
sumInput = xmlScreenParser.findEditTextByHint("Сумма от");
|
||||||
if (!sumInput.isEmpty()) break;
|
if (!sumInput.isEmpty()) break;
|
||||||
qDebug() << "[PayByCard] Waiting for 'Сумма от' input, attempt" << attempt + 1 << "/ 10";
|
qDebug() << "[PayByCard] Waiting for 'Сумма от' input, attempt" << attempt + 1 << "/ 10";
|
||||||
@ -274,6 +278,7 @@ void PayByCardScript::makePayment(
|
|||||||
for (int attempt = 0; attempt < 15; ++attempt) {
|
for (int attempt = 0; attempt < 15; ++attempt) {
|
||||||
if (!checkApp()) return;
|
if (!checkApp()) return;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
|
|
||||||
bool foundKomissiya = false;
|
bool foundKomissiya = false;
|
||||||
for (const Node &node : xmlScreenParser.findAllNodes()) {
|
for (const Node &node : xmlScreenParser.findAllNodes()) {
|
||||||
@ -332,6 +337,7 @@ void PayByCardScript::makePayment(
|
|||||||
for (int attempt = 0; attempt < 15; ++attempt) {
|
for (int attempt = 0; attempt < 15; ++attempt) {
|
||||||
if (!checkApp()) return;
|
if (!checkApp()) return;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
|
|
||||||
// Если PIN-код появился позже — вводим
|
// Если PIN-код появился позже — вводим
|
||||||
if (const QList<Node> pinNodes = xmlScreenParser.tryToFindPinCode(pinCode, "Введите ПИН");
|
if (const QList<Node> pinNodes = xmlScreenParser.tryToFindPinCode(pinCode, "Введите ПИН");
|
||||||
|
|||||||
@ -176,6 +176,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
if (!checkApp()) return;
|
if (!checkApp()) return;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
Node phoneField = xmlScreenParser.findFirstEditText();
|
Node phoneField = xmlScreenParser.findFirstEditText();
|
||||||
if (!phoneField.isEmpty()) {
|
if (!phoneField.isEmpty()) {
|
||||||
paymentsPageLoaded = true;
|
paymentsPageLoaded = true;
|
||||||
@ -202,6 +203,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
if (!checkApp()) return;
|
if (!checkApp()) return;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
|
|
||||||
// Закрываем диалог "Разрешить доступ к контактам"
|
// Закрываем диалог "Разрешить доступ к контактам"
|
||||||
Node notNowBtn = xmlScreenParser.findButtonNode("Не сейчас", false);
|
Node notNowBtn = xmlScreenParser.findButtonNode("Не сейчас", false);
|
||||||
@ -232,6 +234,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
if (!checkApp()) return;
|
if (!checkApp()) return;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
phoneInput = xmlScreenParser.findFirstEditText();
|
phoneInput = xmlScreenParser.findFirstEditText();
|
||||||
if (!phoneInput.isEmpty()) break;
|
if (!phoneInput.isEmpty()) break;
|
||||||
qDebug() << "[PayByPhone] Waiting for phone input field, attempt" << attempt + 1 << "/ 10";
|
qDebug() << "[PayByPhone] Waiting for phone input field, attempt" << attempt + 1 << "/ 10";
|
||||||
@ -255,6 +258,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
for (int attempt = 0; attempt < 20; ++attempt) {
|
for (int attempt = 0; attempt < 20; ++attempt) {
|
||||||
if (!checkApp()) return;
|
if (!checkApp()) return;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
|
|
||||||
// Проверяем: уже на экране суммы?
|
// Проверяем: уже на экране суммы?
|
||||||
Node sumTitle = xmlScreenParser.findTextNode("По номеру телефона");
|
Node sumTitle = xmlScreenParser.findTextNode("По номеру телефона");
|
||||||
@ -375,6 +379,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
qDebug() << "[PayByPhone] Waiting for sum input field, attempt" << attempt + 1 << "/ 10";
|
qDebug() << "[PayByPhone] Waiting for sum input field, attempt" << attempt + 1 << "/ 10";
|
||||||
QThread::msleep(1500);
|
QThread::msleep(1500);
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
}
|
}
|
||||||
if (sumInput.isEmpty()) {
|
if (sumInput.isEmpty()) {
|
||||||
m_error = "Поле ввода суммы не найдено";
|
m_error = "Поле ввода суммы не найдено";
|
||||||
@ -404,6 +409,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
for (int attempt = 0; attempt < 10; ++attempt) {
|
for (int attempt = 0; attempt < 10; ++attempt) {
|
||||||
if (!checkApp()) return;
|
if (!checkApp()) return;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
Node confirmTitle = xmlScreenParser.findTextNode("Подтвердите перевод");
|
Node confirmTitle = xmlScreenParser.findTextNode("Подтвердите перевод");
|
||||||
if (!confirmTitle.isEmpty()) {
|
if (!confirmTitle.isEmpty()) {
|
||||||
confirmScreenLoaded = true;
|
confirmScreenLoaded = true;
|
||||||
@ -428,6 +434,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
qDebug() << "[PayByPhone] Waiting for 'Перевести ...' button, attempt" << attempt + 1 << "/ 10";
|
qDebug() << "[PayByPhone] Waiting for 'Перевести ...' button, attempt" << attempt + 1 << "/ 10";
|
||||||
QThread::msleep(1500);
|
QThread::msleep(1500);
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
}
|
}
|
||||||
if (transferConfirmBtn.isEmpty()) {
|
if (transferConfirmBtn.isEmpty()) {
|
||||||
m_error = "Кнопка 'Перевести ...' не найдена на экране подтверждения";
|
m_error = "Кнопка 'Перевести ...' не найдена на экране подтверждения";
|
||||||
@ -452,6 +459,7 @@ void PayByPhoneScript::makePayment(
|
|||||||
for (int attempt = 0; attempt < 15; ++attempt) {
|
for (int attempt = 0; attempt < 15; ++attempt) {
|
||||||
if (!checkApp()) return;
|
if (!checkApp()) return;
|
||||||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
closeGooglePlayBannerIfVisible(deviceId, width, height);
|
||||||
|
|
||||||
// Если PIN-код появился позже — вводим
|
// Если PIN-код появился позже — вводим
|
||||||
if (const QList<Node> pinNodes = xmlScreenParser.tryToFindPinCode(pinCode, "Введите ПИН");
|
if (const QList<Node> pinNodes = xmlScreenParser.tryToFindPinCode(pinCode, "Введите ПИН");
|
||||||
|
|||||||
@ -222,6 +222,21 @@ Node ScreenXmlParser::tryToFindAdBanner() {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node ScreenXmlParser::tryToFindSystemPermissionDenyButton() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.resourceId == "com.android.permissioncontroller:id/permission_deny_button"
|
||||||
|
&& node.clickable) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.clickable && node.text.trimmed() == QString::fromUtf8("ЗАПРЕТИТЬ")) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
Node ScreenXmlParser::tryToFindGooglePlayBanner(const int screenWidth, const int screenHeight) {
|
Node ScreenXmlParser::tryToFindGooglePlayBanner(const int screenWidth, const int screenHeight) {
|
||||||
// Баннер Google Play "Доступно обновление" — ищем кнопку закрытия по content-desc
|
// Баннер Google Play "Доступно обновление" — ищем кнопку закрытия по content-desc
|
||||||
for (const Node &node : m_nodes) {
|
for (const Node &node : m_nodes) {
|
||||||
|
|||||||
@ -44,6 +44,10 @@ public:
|
|||||||
|
|
||||||
Node tryToFindGooglePlayBanner(int screenWidth, int screenHeight);
|
Node tryToFindGooglePlayBanner(int screenWidth, int screenHeight);
|
||||||
|
|
||||||
|
// Находит кнопку "ЗАПРЕТИТЬ" в системном диалоге запроса разрешения Android
|
||||||
|
// (com.google.android.permissioncontroller). Возвращает пустой Node если диалог не виден.
|
||||||
|
Node tryToFindSystemPermissionDenyButton();
|
||||||
|
|
||||||
// Returns a Button node whose text is exactly 4 digits (card last numbers)
|
// Returns a Button node whose text is exactly 4 digits (card last numbers)
|
||||||
Node findCardButtonOnHomeScreen();
|
Node findCardButtonOnHomeScreen();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user