diff --git a/android/dushanbe/CommonScript.cpp b/android/dushanbe/CommonScript.cpp index 11d2ebb..d15cbad 100644 --- a/android/dushanbe/CommonScript.cpp +++ b/android/dushanbe/CommonScript.cpp @@ -295,4 +295,26 @@ void CommonScript::stop() { 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 diff --git a/android/dushanbe/CommonScript.h b/android/dushanbe/CommonScript.h index a1bb32e..68c72de 100644 --- a/android/dushanbe/CommonScript.h +++ b/android/dushanbe/CommonScript.h @@ -47,6 +47,12 @@ protected: 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; ScreenXmlParser xmlScreenParser; int m_counter = 0; diff --git a/android/dushanbe/GetLastTransactionsScript.cpp b/android/dushanbe/GetLastTransactionsScript.cpp index 972be62..4c61c51 100644 --- a/android/dushanbe/GetLastTransactionsScript.cpp +++ b/android/dushanbe/GetLastTransactionsScript.cpp @@ -288,6 +288,7 @@ void GetLastTransactionsScript::doStart() { bool historyLoaded = false; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); // Проверяем диалог "Ошибка" — нажимаем "ОК" и обновляем свайпом вниз if (!xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Ошибка")).isEmpty()) { @@ -390,6 +391,7 @@ void GetLastTransactionsScript::doStart() { return; } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); // Верх нижнего меню: минимальный y1() среди табов и FAB "Сканировать". // Тап по строке с y >= navTopY - navMargin промахивается и попадает в FAB/таб. @@ -632,6 +634,7 @@ void GetLastTransactionsScript::doStart() { for (int attempt = 0; attempt < 10; ++attempt) { if (interrupted()) { m_error = "Interrupted"; emit finishedWithResult(m_error); return; } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); for (const Node &n : xmlScreenParser.findAllNodes()) { if (!n.contentDesc.contains(QString::fromUtf8("Успешный платеж"))) continue; if (!n.contentDesc.contains(QString::fromUtf8("Дата:"))) continue; diff --git a/android/dushanbe/GetProfileInfoScript.cpp b/android/dushanbe/GetProfileInfoScript.cpp index eef24bf..e28d2ab 100644 --- a/android/dushanbe/GetProfileInfoScript.cpp +++ b/android/dushanbe/GetProfileInfoScript.cpp @@ -82,6 +82,7 @@ void GetProfileInfoScript::doStart() { bool sideMenuFound = false; for (int attempt = 0; attempt < 5; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); if (xmlScreenParser.isSideMenu()) { sideMenuFound = true; break; diff --git a/android/dushanbe/PayByCardScript.cpp b/android/dushanbe/PayByCardScript.cpp index 994e4cd..b8a79cf 100644 --- a/android/dushanbe/PayByCardScript.cpp +++ b/android/dushanbe/PayByCardScript.cpp @@ -166,6 +166,7 @@ void PayByCardScript::makePayment( Node cardTransferBtn; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); cardTransferBtn = xmlScreenParser.findNodeByContentDesc( QString::fromUtf8("DC (по номеру карты)"), true); if (!cardTransferBtn.isEmpty()) { @@ -193,6 +194,7 @@ void PayByCardScript::makePayment( bool inputScreenLoaded = false; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); Node editText = xmlScreenParser.findEditTextByHint( QString::fromUtf8("Номер карты получателя")); if (editText.isEmpty()) { @@ -233,6 +235,7 @@ void PayByCardScript::makePayment( Node sumEditText; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); sumEditText = xmlScreenParser.findEditTextByHint(QString::fromUtf8("Сумма")); if (!sumEditText.isEmpty()) break; qDebug() << "[Dushanbe::PayByCard] Waiting for sum input, attempt" << attempt + 1 << "/ 10"; @@ -301,6 +304,7 @@ void PayByCardScript::makePayment( bool oplatitFound = false; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); Node oplatitBtn = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Оплатить")); if (oplatitBtn.isEmpty()) { oplatitBtn = xmlScreenParser.findButtonNode(QString::fromUtf8("Оплатить"), false); @@ -330,6 +334,7 @@ void PayByCardScript::makePayment( bool confirmed = false; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); // Пин-код может появиться if (xmlScreenParser.isPinCodeScreen()) { @@ -370,6 +375,7 @@ void PayByCardScript::makePayment( bool success = false; for (int attempt = 0; attempt < 15; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); // Пин-код if (xmlScreenParser.isPinCodeScreen()) { diff --git a/android/dushanbe/PayByPhoneScript.cpp b/android/dushanbe/PayByPhoneScript.cpp index e1a003e..4b10fe8 100644 --- a/android/dushanbe/PayByPhoneScript.cpp +++ b/android/dushanbe/PayByPhoneScript.cpp @@ -163,6 +163,7 @@ void PayByPhoneScript::makePayment( Node phoneTransferBtn; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); phoneTransferBtn = xmlScreenParser.findNodeByContentDesc( QString::fromUtf8("DC (по номеру телефона)"), true); if (!phoneTransferBtn.isEmpty()) { @@ -190,6 +191,7 @@ void PayByPhoneScript::makePayment( bool inputScreenLoaded = false; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); Node editText = xmlScreenParser.findEditTextByHint( QString::fromUtf8("Номер телефона получателя")); if (editText.isEmpty()) { @@ -234,6 +236,7 @@ void PayByPhoneScript::makePayment( Node sumEditText; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); sumEditText = xmlScreenParser.findEditTextByHint(QString::fromUtf8("Сумма")); if (!sumEditText.isEmpty()) break; qDebug() << "[Dushanbe::PayByPhone] Waiting for sum input, attempt" << attempt + 1 << "/ 10"; @@ -301,6 +304,7 @@ void PayByPhoneScript::makePayment( bool oplatitFound = false; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); Node oplatitBtn = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Оплатить")); if (oplatitBtn.isEmpty()) { oplatitBtn = xmlScreenParser.findButtonNode(QString::fromUtf8("Оплатить"), false); @@ -328,6 +332,7 @@ void PayByPhoneScript::makePayment( bool confirmed = false; for (int attempt = 0; attempt < 10; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); if (xmlScreenParser.isPinCodeScreen()) { qDebug() << "[Dushanbe::PayByPhone] PIN code screen, entering PIN..."; @@ -365,6 +370,7 @@ void PayByPhoneScript::makePayment( bool success = false; for (int attempt = 0; attempt < 15; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); if (xmlScreenParser.isPinCodeScreen()) { qDebug() << "[Dushanbe::PayByPhone] PIN code screen (retry), entering PIN..."; diff --git a/android/dushanbe/ScreenXmlParser.cpp b/android/dushanbe/ScreenXmlParser.cpp index d6bdc3b..2338c94 100644 --- a/android/dushanbe/ScreenXmlParser.cpp +++ b/android/dushanbe/ScreenXmlParser.cpp @@ -497,4 +497,37 @@ Node ScreenXmlParser::findEditTextByHint(const QString &hint) { 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 diff --git a/android/dushanbe/ScreenXmlParser.h b/android/dushanbe/ScreenXmlParser.h index 66ab386..7f26299 100644 --- a/android/dushanbe/ScreenXmlParser.h +++ b/android/dushanbe/ScreenXmlParser.h @@ -115,6 +115,14 @@ public: // Находит EditText по 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: QList m_nodes; QDomElement m_xml; diff --git a/android/ozon/CommonScript.cpp b/android/ozon/CommonScript.cpp index 058e0ae..f3232b6 100644 --- a/android/ozon/CommonScript.cpp +++ b/android/ozon/CommonScript.cpp @@ -227,6 +227,16 @@ bool CommonScript::tryToCloseAllBannersOnHomePage(const QString &deviceId, const bool CommonScript::closeGooglePlayBannerIfVisible( 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); if (gpNode.isEmpty()) return false; qDebug() << "[Ozon] Google Play update banner detected mid-task, closing..."; diff --git a/android/ozon/GetLastTransactionsScript.cpp b/android/ozon/GetLastTransactionsScript.cpp index e8e2e49..881f15b 100644 --- a/android/ozon/GetLastTransactionsScript.cpp +++ b/android/ozon/GetLastTransactionsScript.cpp @@ -206,6 +206,7 @@ bool GetLastTransactionsScript::navigateToTransactionList(const DeviceInfo &devi AdbUtils::makeSwipe(m_deviceId, x, device.screenHeight - 200, x, 200, 100); QThread::msleep(1500); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); allBtn = xmlScreenParser.findButtonNode("Все", false); 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) { if (QThread::currentThread()->isInterruptionRequested()) break; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); if (!xmlScreenParser.findNodeByContentDesc("Поделиться").isEmpty()) { docLoaded = true; break; @@ -750,6 +752,7 @@ void GetLastTransactionsScript::scanRecentTransactions(const DeviceInfo &device, AdbUtils::makeSwipe(m_deviceId, x, device.screenHeight - offset, x, offset); QThread::msleep(1000); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); txButtons = xmlScreenParser.findTransactionButtons(8); 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; for (int da = 0; da < 15; ++da) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); if (!xmlScreenParser.findNodeByContentDesc("Поделиться").isEmpty()) { docLoaded = true; break; @@ -860,6 +864,7 @@ void GetLastTransactionsScript::scanRecentTransactions(const DeviceInfo &device, bool docLoaded = false; for (int da = 0; da < 20; ++da) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); if (!xmlScreenParser.findNodeByContentDesc("Поделиться").isEmpty()) { docLoaded = true; break; } diff --git a/android/ozon/GetProfileInfoScript.cpp b/android/ozon/GetProfileInfoScript.cpp index ae9a367..56dfccc 100644 --- a/android/ozon/GetProfileInfoScript.cpp +++ b/android/ozon/GetProfileInfoScript.cpp @@ -108,6 +108,7 @@ void GetProfileInfoScript::doStart() { // Читаем XML профиля и проверяем что мы действительно там for (int attempt = 0; attempt < 5; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); if (xmlScreenParser.isProfileScreen()) { break; } diff --git a/android/ozon/PayByCardScript.cpp b/android/ozon/PayByCardScript.cpp index 121778e..b1434be 100644 --- a/android/ozon/PayByCardScript.cpp +++ b/android/ozon/PayByCardScript.cpp @@ -176,6 +176,7 @@ void PayByCardScript::makePayment( for (int attempt = 0; attempt < 10; ++attempt) { if (!checkApp()) return; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); Node title = xmlScreenParser.findTextNode("Платежи и переводы"); if (!title.isEmpty()) titleSeen = true; cardBtn = xmlScreenParser.findButtonNode("По номеру карты", false); @@ -205,6 +206,7 @@ void PayByCardScript::makePayment( for (int attempt = 0; attempt < 10; ++attempt) { if (!checkApp()) return; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); Node title = xmlScreenParser.findTextNode("Перевод по номеру карты"); if (!title.isEmpty()) { cardScreenLoaded = true; @@ -231,6 +233,7 @@ void PayByCardScript::makePayment( qDebug() << "[PayByCard] Waiting for 'Номер карты получателя' input, attempt" << attempt + 1 << "/ 10"; QThread::msleep(1500); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); } if (cardInput.isEmpty()) { @@ -249,6 +252,7 @@ void PayByCardScript::makePayment( for (int attempt = 0; attempt < 10; ++attempt) { if (!checkApp()) return; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); sumInput = xmlScreenParser.findEditTextByHint("Сумма от"); if (!sumInput.isEmpty()) break; qDebug() << "[PayByCard] Waiting for 'Сумма от' input, attempt" << attempt + 1 << "/ 10"; @@ -274,6 +278,7 @@ void PayByCardScript::makePayment( for (int attempt = 0; attempt < 15; ++attempt) { if (!checkApp()) return; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); bool foundKomissiya = false; for (const Node &node : xmlScreenParser.findAllNodes()) { @@ -332,6 +337,7 @@ void PayByCardScript::makePayment( for (int attempt = 0; attempt < 15; ++attempt) { if (!checkApp()) return; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); // Если PIN-код появился позже — вводим if (const QList pinNodes = xmlScreenParser.tryToFindPinCode(pinCode, "Введите ПИН"); diff --git a/android/ozon/PayByPhoneScript.cpp b/android/ozon/PayByPhoneScript.cpp index 01c45ee..9d49aad 100644 --- a/android/ozon/PayByPhoneScript.cpp +++ b/android/ozon/PayByPhoneScript.cpp @@ -176,6 +176,7 @@ void PayByPhoneScript::makePayment( for (int attempt = 0; attempt < 10; ++attempt) { if (!checkApp()) return; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); Node phoneField = xmlScreenParser.findFirstEditText(); if (!phoneField.isEmpty()) { paymentsPageLoaded = true; @@ -202,6 +203,7 @@ void PayByPhoneScript::makePayment( for (int attempt = 0; attempt < 10; ++attempt) { if (!checkApp()) return; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); // Закрываем диалог "Разрешить доступ к контактам" Node notNowBtn = xmlScreenParser.findButtonNode("Не сейчас", false); @@ -232,6 +234,7 @@ void PayByPhoneScript::makePayment( for (int attempt = 0; attempt < 10; ++attempt) { if (!checkApp()) return; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); phoneInput = xmlScreenParser.findFirstEditText(); if (!phoneInput.isEmpty()) break; 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) { if (!checkApp()) return; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); // Проверяем: уже на экране суммы? Node sumTitle = xmlScreenParser.findTextNode("По номеру телефона"); @@ -375,6 +379,7 @@ void PayByPhoneScript::makePayment( qDebug() << "[PayByPhone] Waiting for sum input field, attempt" << attempt + 1 << "/ 10"; QThread::msleep(1500); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); } if (sumInput.isEmpty()) { m_error = "Поле ввода суммы не найдено"; @@ -404,6 +409,7 @@ void PayByPhoneScript::makePayment( for (int attempt = 0; attempt < 10; ++attempt) { if (!checkApp()) return; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); Node confirmTitle = xmlScreenParser.findTextNode("Подтвердите перевод"); if (!confirmTitle.isEmpty()) { confirmScreenLoaded = true; @@ -428,6 +434,7 @@ void PayByPhoneScript::makePayment( qDebug() << "[PayByPhone] Waiting for 'Перевести ...' button, attempt" << attempt + 1 << "/ 10"; QThread::msleep(1500); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); } if (transferConfirmBtn.isEmpty()) { m_error = "Кнопка 'Перевести ...' не найдена на экране подтверждения"; @@ -452,6 +459,7 @@ void PayByPhoneScript::makePayment( for (int attempt = 0; attempt < 15; ++attempt) { if (!checkApp()) return; xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(deviceId, width, height); // Если PIN-код появился позже — вводим if (const QList pinNodes = xmlScreenParser.tryToFindPinCode(pinCode, "Введите ПИН"); diff --git a/android/ozon/ScreenXmlParser.cpp b/android/ozon/ScreenXmlParser.cpp index 6c9dd1a..fdf20ca 100644 --- a/android/ozon/ScreenXmlParser.cpp +++ b/android/ozon/ScreenXmlParser.cpp @@ -222,6 +222,21 @@ Node ScreenXmlParser::tryToFindAdBanner() { 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) { // Баннер Google Play "Доступно обновление" — ищем кнопку закрытия по content-desc for (const Node &node : m_nodes) { diff --git a/android/ozon/ScreenXmlParser.h b/android/ozon/ScreenXmlParser.h index 2143a84..a3254cc 100644 --- a/android/ozon/ScreenXmlParser.h +++ b/android/ozon/ScreenXmlParser.h @@ -44,6 +44,10 @@ public: 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) Node findCardButtonOnHomeScreen();