Enable reliable activation of ADB Keyboard and improve fallback handling:
- Add comprehensive verification and logging for IME activation steps in `AdbUtils`. - Update `PayByPhoneScript` to handle IME activation failures with error reporting. - Improve edit text detection in `ScreenXmlParser` for devices with missing hint attributes.
This commit is contained in:
parent
9015a5db59
commit
1a3ccd8df5
@ -338,6 +338,7 @@ bool AdbUtils::makeTap(const QString &deviceId, const int x, const int y) {
|
||||
|
||||
bool AdbUtils::enableAdbIMEKeyboard(const QString &deviceId) {
|
||||
const QString adb = adbPath();
|
||||
const QString imeId = QStringLiteral("com.android.adbkeyboard/.AdbIME");
|
||||
|
||||
// Проверяем, установлен ли ADB Keyboard
|
||||
QString installedList;
|
||||
@ -353,20 +354,63 @@ bool AdbUtils::enableAdbIMEKeyboard(const QString &deviceId) {
|
||||
qDebug() << "[AdbUtils] ADB Keyboard installed successfully";
|
||||
}
|
||||
|
||||
struct Step { QStringList args; };
|
||||
Step steps[] = {
|
||||
{{"-s", deviceId, "shell", "ime", "enable", "com.android.adbkeyboard/.AdbIME"}},
|
||||
{{"-s", deviceId, "shell", "ime", "set", "com.android.adbkeyboard/.AdbIME"}}
|
||||
};
|
||||
// Пакет мог быть отключён производителем (pm disable-user).
|
||||
// Пытаемся включить; ошибку не считаем фатальной (на некоторых прошивках команда
|
||||
// отвергается, но сам IME при этом включается).
|
||||
{
|
||||
QString pmOut, pmErr;
|
||||
if (!startProcess(adb, {"-s", deviceId, "shell", "pm", "enable", "com.android.adbkeyboard"}, &pmOut, &pmErr)) {
|
||||
qWarning() << "[AdbUtils] pm enable com.android.adbkeyboard failed:" << pmErr.trimmed()
|
||||
<< "(продолжаем)";
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &step : steps) {
|
||||
QString stdErr;
|
||||
if (!startProcess(adb, step.args, nullptr, &stdErr)) {
|
||||
qWarning() << "ADB command failed:" << step.args.join(' ');
|
||||
qWarning() << "Error:" << stdErr;
|
||||
// ime enable
|
||||
{
|
||||
QString out, err;
|
||||
if (!startProcess(adb, {"-s", deviceId, "shell", "ime", "enable", imeId}, &out, &err)) {
|
||||
qWarning() << "[AdbUtils] ime enable failed:" << err.trimmed();
|
||||
return false;
|
||||
}
|
||||
qDebug() << "[AdbUtils] ime enable:" << out.trimmed();
|
||||
}
|
||||
|
||||
// Верификация: IME должен появиться в списке разрешённых
|
||||
{
|
||||
QString enabledList;
|
||||
startProcess(adb, {"-s", deviceId, "shell", "ime", "list", "-s"}, &enabledList);
|
||||
if (!enabledList.contains(imeId)) {
|
||||
qWarning() << "[AdbUtils] ADB Keyboard отсутствует в 'ime list -s' после 'ime enable'."
|
||||
<< "Вывод:" << enabledList.trimmed()
|
||||
<< "(прошивка/OEM может блокировать сторонние IME)";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ime set
|
||||
{
|
||||
QString out, err;
|
||||
if (!startProcess(adb, {"-s", deviceId, "shell", "ime", "set", imeId}, &out, &err)) {
|
||||
qWarning() << "[AdbUtils] ime set failed:" << err.trimmed();
|
||||
return false;
|
||||
}
|
||||
qDebug() << "[AdbUtils] ime set:" << out.trimmed();
|
||||
}
|
||||
|
||||
// Верификация: активный IME должен совпасть с нашим
|
||||
{
|
||||
QString defaultIme;
|
||||
startProcess(adb, {"-s", deviceId, "shell", "settings", "get", "secure", "default_input_method"}, &defaultIme);
|
||||
const QString trimmed = defaultIme.trimmed();
|
||||
if (!trimmed.contains(imeId)) {
|
||||
qWarning() << "[AdbUtils] default_input_method =" << trimmed
|
||||
<< "— ожидали" << imeId
|
||||
<< "(прошивка откатывает смену IME)";
|
||||
return false;
|
||||
}
|
||||
qDebug() << "[AdbUtils] Active IME verified:" << trimmed;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -315,7 +315,11 @@ void PayByPhoneScript::makePayment(
|
||||
QThread::msleep(500);
|
||||
|
||||
// Ввод кириллицы через ADB Keyboard
|
||||
AdbUtils::enableAdbIMEKeyboard(deviceId);
|
||||
if (!AdbUtils::enableAdbIMEKeyboard(deviceId)) {
|
||||
m_error = "Не удалось активировать ADB Keyboard (см. логи 'ime list -s' / default_input_method)";
|
||||
qWarning() << "[PayByPhone]" << m_error;
|
||||
return;
|
||||
}
|
||||
QThread::msleep(500);
|
||||
AdbUtils::makeTap(deviceId, bankInput.x(), bankInput.y());
|
||||
QThread::msleep(500);
|
||||
|
||||
@ -149,7 +149,31 @@ Node ScreenXmlParser::findEditTextByHint(const QString &hintPrefix) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
// Некоторые устройства/прошивки (напр. Infinix) в uiautomator-дампе не отдают
|
||||
// атрибут hint для EditText внутри WebView. В этом случае ищем TextView-label
|
||||
// с нужным текстом и ближайший к нему EditText с горизонтальным перекрытием.
|
||||
Node label;
|
||||
for (const Node &node : m_nodes) {
|
||||
if (node.className == "android.widget.TextView" && node.text.contains(hintPrefix)) {
|
||||
label = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (label.isEmpty()) return {};
|
||||
|
||||
Node best;
|
||||
int bestDy = INT_MAX;
|
||||
for (const Node &node : m_nodes) {
|
||||
if (node.className != "android.widget.EditText") continue;
|
||||
const bool hOverlap = node.x1() < label.x2() && node.x2() > label.x1();
|
||||
if (!hOverlap) continue;
|
||||
const int dy = std::abs(node.y() - label.y());
|
||||
if (dy < bestDy) {
|
||||
bestDy = dy;
|
||||
best = node;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
Node ScreenXmlParser::findButtonNode(const QString &text, const bool contains) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user