diff --git a/android/black/CommonScript.cpp b/android/black/CommonScript.cpp index 6b214ec..9933374 100644 --- a/android/black/CommonScript.cpp +++ b/android/black/CommonScript.cpp @@ -261,4 +261,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() << "[Black] 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() << "[Black] 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 Black diff --git a/android/black/CommonScript.h b/android/black/CommonScript.h index 7cdfff1..29d3635 100644 --- a/android/black/CommonScript.h +++ b/android/black/CommonScript.h @@ -49,6 +49,13 @@ protected: // Создаёт bank_profile на сервере если ещё не создан 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/black/GetCardInfoScript.cpp b/android/black/GetCardInfoScript.cpp index b184e92..df6007d 100644 --- a/android/black/GetCardInfoScript.cpp +++ b/android/black/GetCardInfoScript.cpp @@ -41,6 +41,7 @@ void GetCardInfoScript::doStart() { // Читаем текущий экран xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); // Если не на домашнем экране — перезапускаем if (!xmlScreenParser.isHomeScreen()) { @@ -54,6 +55,7 @@ void GetCardInfoScript::doStart() { return; } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); } // 1. Парсим баланс с домашнего экрана @@ -78,6 +80,7 @@ void GetCardInfoScript::doStart() { bool cvuScreenFound = 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.isCVUScreen()) { cvuScreenFound = true; break; diff --git a/android/black/ScreenXmlParser.cpp b/android/black/ScreenXmlParser.cpp index 0db3069..b3b2df4 100644 --- a/android/black/ScreenXmlParser.cpp +++ b/android/black/ScreenXmlParser.cpp @@ -542,4 +542,37 @@ Node ScreenXmlParser::findEditTextByHint(const QString &hint) { 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 {}; +} + +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 {}; +} + } // namespace Black diff --git a/android/black/ScreenXmlParser.h b/android/black/ScreenXmlParser.h index 535b819..eb0afae 100644 --- a/android/black/ScreenXmlParser.h +++ b/android/black/ScreenXmlParser.h @@ -110,6 +110,13 @@ 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 + Node tryToFindSystemPermissionDenyButton(); + private: QList m_nodes; QDomElement m_xml; diff --git a/android/dushanbe/GetCardInfoScript.cpp b/android/dushanbe/GetCardInfoScript.cpp index 07ae89e..688af30 100644 --- a/android/dushanbe/GetCardInfoScript.cpp +++ b/android/dushanbe/GetCardInfoScript.cpp @@ -39,6 +39,7 @@ void GetCardInfoScript::doStart() { TaskDumpRecorder::Scope dumpScope("dushanbe", "FETCH_CARDS", m_deviceId, dumpMeta, &m_error); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); if (!xmlScreenParser.isHomeScreen()) { qDebug() << "[Dushanbe::GetCardInfo] Not on home screen, restarting app..."; @@ -51,6 +52,7 @@ void GetCardInfoScript::doStart() { return; } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); } // Парсим баланс с домашнего экрана @@ -77,6 +79,7 @@ void GetCardInfoScript::doStart() { bool cardsScreenFound = 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.isCardsScreen()) { cardsScreenFound = true; break; @@ -127,6 +130,7 @@ void GetCardInfoScript::doStart() { bool detailFound = 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.isCardDetailScreen()) { detailFound = true; break; @@ -142,6 +146,7 @@ void GetCardInfoScript::doStart() { // Ждём загрузки баланса (может быть 0 пока данные подтягиваются) QThread::msleep(1500); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); QString fullNumber = xmlScreenParser.parseFullCardNumber(); const double cardBalance = xmlScreenParser.parseCardDetailBalance(); @@ -283,6 +288,7 @@ void GetCardInfoScript::doStart() { // Ждём возврата на экран "Мои карты" for (int attempt = 0; attempt < 5; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); if (xmlScreenParser.isCardsScreen()) break; QThread::msleep(1000); } diff --git a/android/ozon/GetCardInfoScript.cpp b/android/ozon/GetCardInfoScript.cpp index aaf0ea4..1d26051 100644 --- a/android/ozon/GetCardInfoScript.cpp +++ b/android/ozon/GetCardInfoScript.cpp @@ -90,6 +90,7 @@ void GetCardInfoScript::doStart() { 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; QThread::msleep(1000); } @@ -106,12 +107,14 @@ void GetCardInfoScript::doStart() { AdbUtils::goBack(m_deviceId); QThread::msleep(1500); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); } else { qDebug() << "[GetCardInfo] Profile info already in DB or username not found, skipping profile parse"; } // Проверяем что на домашнем экране перед поиском карт xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); if (!xmlScreenParser.isHomeScreen()) { qDebug() << "[GetCardInfo] Not on home screen before card search, restarting..."; if (!runAppAndGoToHomeScreen(m_deviceId, app.package, app.pinCode, @@ -130,6 +133,9 @@ void GetCardInfoScript::doStart() { QList cards; for (int attempt = 0; attempt < 5; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + if (closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight)) { + // баннер закрыт, дамп уже обновлён внутри helper'а + } cards = xmlScreenParser.parseCardsOnHomeScreen(); if (!cards.isEmpty()) break; qDebug() << "[GetCardInfo] No cards found on home screen, attempt" << attempt + 1 << "/ 5"; @@ -262,6 +268,7 @@ void GetCardInfoScript::doStart() { for (int scrollAttempt = 0; scrollAttempt < 6; ++scrollAttempt) { QThread::msleep(scrollAttempt == 0 ? 2000 : 600); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); Node candidate = xmlScreenParser.findButtonNode("Показать", false); if (candidate.isEmpty()) { @@ -293,6 +300,7 @@ void GetCardInfoScript::doStart() { for (int attempt = 0; attempt < 10; ++attempt) { QThread::msleep(attempt == 0 ? 2000 : 500); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); Node candidate = xmlScreenParser.findButtonNode("Показать", false); Node requisites = xmlScreenParser.findTextNode("Реквизиты карты"); @@ -332,6 +340,7 @@ void GetCardInfoScript::doStart() { AdbUtils::goBack(m_deviceId); QThread::msleep(1500); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); continue; } @@ -343,6 +352,7 @@ void GetCardInfoScript::doStart() { for (int attempt = 0; attempt < 10; ++attempt) { QThread::msleep(2000); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); cardNumber = xmlScreenParser.findFullCardNumber(); if (!cardNumber.isEmpty()) { qDebug() << "[GetCardInfo] Card number found on attempt" << attempt + 1; @@ -411,6 +421,7 @@ void GetCardInfoScript::doStart() { AdbUtils::goBack(m_deviceId); QThread::msleep(2000); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + closeGooglePlayBannerIfVisible(m_deviceId, device.screenWidth, device.screenHeight); } }