Невозможно выполнить это действие для незапечатанного экземпляра Исключение java.lang.IllegalStateException

С Android AccessibilityService можно вставить в другое поле EditText приложения, но с браузером testfields (браузер по умолчанию для эмулятора или браузер по умолчанию для Samsung) он не работает, выдавая ошибку:

Невозможно выполнить это действие на незапечатанном экземпляре.

В браузере Android Chrome с некоторым текстовым полем Singnup он работает, но не для всех текстовых полей.

 @Override
public void onAccessibilityEvent(AccessibilityEvent event) {

    AccessibilityNodeInfo source = event.getSource();
    if (source != null && ( event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED ) ) {
            // || event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED ) &&
            //event.getClassName().equals("android.widget.EditText")
            //) {
        ctx = getApplicationContext();
        ClipboardManager clipboard = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE);
        ClipData clip = ClipData.newPlainText("label", "XYZ");
        clipboard.setPrimaryClip(clip);
        source.performAction(AccessibilityNodeInfo.ACTION_PASTE); 
        //Not Working, always return false.

        //Tried with other options
        Bundle argumentsTest = new Bundle();
        argumentsTest.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, "Bundle Test Data");
        source.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT,argumentsTest )
        // Not Working, throw java.lang.IllegalStateException exception
        //Message: "Cannot perform this action on a not sealed instance"
    }
}   

person Gulshan Singh    schedule 26.09.2015    source источник


Ответы (1)


Я не верю, что ты пытаешься делать то, что, как тебе кажется, ты пытаешься сделать.

Когда вы устанавливаете «текст» для accessibilityNodeInfo, вы изменяете свойство text этого объекта, поскольку оно относится к вашей службе специальных возможностей. ЭТО НЕ ОЗНАЧАЕТ, что вы изменяете текст поля EditText, на который ссылается объект accessibilityNodeInfo. К тому времени, когда ваша служба специальных возможностей получит этот объект, эти два объекта будут совершенно отделены друг от друга. Даже если ваш код запустится успешно, вы не получите ожидаемых результатов. Теперь, что касается того, почему вы не можете выполнить это действие, зная это, это должно быть очевидно. Для службы специальных возможностей не имеет смысла изменять имеющиеся у нее узлы. Таким образом, они становятся запечатанными (подумайте об этом как о принудительном выполнении константы). Узлы доступности становятся запечатанными и разгерметизированными в различные моменты их жизни. Части платформы, которые имеют доступ к информации о незапечатанных узлах, — это классы View и частные API. Любые задачи, связанные со службой специальных возможностей, будут иметь дело с запечатанными экземплярами, доступными только для чтения.

Что касается того, почему ваше оригинальное решение не работает, я считаю, что у нас недостаточно информации. Подход «ACTION_PASTE» является (приблизительно) правильным подходом, ОДНАКО при этом возникает множество проблем с веб-браузерами. Версия браузера, версия Android, версия устройства, веб-сайт и т. д. — все это играет роль. Особенно, если ваша установка достаточно старая, чтобы не использовать новый WebView (чистый веб-просмотр хрома, а не старый подход 4.+ с нечетными встроенными мобильными WebView, основанными на устаревших версиях WebKit, которые теперь никогда не будут обновляться). Я рекомендую протестировать ваш код на новейшем устройстве Nexus, используя как минимум Android 5.0, и посмотреть, работает ли ваш код. Если вы не можете этого сделать, сообщите информацию о версии для вашей установки. Если уже есть, то на каком сайте?

person ChrisCM    schedule 28.09.2015
comment
У нас эта штука работает сейчас или какая-то другая альтернатива? - person suv; 04.10.2018
comment
Откуда у этого столько голосов? Разглагольствования, содержащиеся в этом ответе, неверны: ACTION_SET_TEXT, по сути, предназначен для того, чтобы разрешить службам специальных возможностей изменять текст в исходном виджете — PerformAction — это мост для этого, при условии, что у вашей службы есть соответствующие разрешения. Ваш ответ также не касается того факта, что узел еще/больше не запечатан, что является реальной проблемой и предотвращает большинство действий (даже просто получение менее тривиальной информации через его API): либо узел каким-то образом еще не готов, либо уже был переработано () чем-то. - person Keilaron; 16.09.2019
comment
Вы неправильно понимаете предпосылку ответа. Я ни разу не сказал, что ACTION_SET_TEXT или ACTIO_PASTE — неправильный способ сделать что-либо из этого. Но скорее то, что AccessibilityNodeInfo, к которому они привязались, был неправильным. AccessibilityNodeInfo, поступающий из AccessiblityEvent, больше не является допустимым объектом для выполнения действий. Только AccessibilityNodeInfo, полученный в результате обхода RootInActiveWindow, является допустимым узлом для выполнения таких действий. У него так много голосов, потому что это правильно. - person ChrisCM; 17.09.2019
comment
Судя по вашим комментариям о готовности узлов, вы также в корне не понимаете этого. Оно ни то, ни другое не готово и не переработано. Узлы, поступающие от AccessibilityEvents, служат принципиально другой цели. Когда AccessibilityService получает событие, это событие является окончательным. Вы ничего не можете изменить в этом. Поступать так было бы в корне неправильно. Если вы хотите попытаться изменить состояние любого приложения, вы должны пройти иерархию представлений из корневого узла и выполнить действия на этих узлах. - person ChrisCM; 17.09.2019
comment
Ничто в вопросе не упоминает непосредственное редактирование текстового члена, так что да, похоже, вы говорили, что использование ACTION_SET_TEXT было неправильным путем. Почему ANI из события может быть неправильным? Срок его действия не истек; Он загружается по запросу с помощью getSource(). Если вы используете любую из функций поиска для загрузки дочернего узла, она также будет действительна. Если событие больше недействительно/слишком старо, вы получите нуль. Если ANI недействителен (был переработан), вы получите исключение практически при любой операции, даже при чтении большинства членов ANI. - person Keilaron; 22.10.2019
comment
Являются ли эти вещи, о которых вы говорите, специфическими для работы с браузерами? - person Keilaron; 22.10.2019
comment
Нет. Это для собственных приложений и специальных возможностей. Когда служба специальных возможностей получает событие AccessibilityEvent. Когда Приложение отправляет Службе событие AccessibilityEvent, это событие запечатывается. Итак, вы правы, вы не получите Null или что-то еще, и вы, безусловно, можете выполнять действия на этих узлах (например, запускать функции). Но вы не можете выполнять действия, которые пытаются манипулировать содержимым экрана (например, манипулировать текстом EditTexts) из ANI, которые вы получаете от событий. Вы должны получить ANI из исследования иерархии узлов, иначе узлы будут запечатаны. - person ChrisCM; 23.10.2019
comment
Sealed — это, по сути, способ операционной системы Android для обеспечения постоянного типа отношений. Есть два типа ANI, которые вы можете получить. Запечатанные экземпляры поступают из AccessibilityEvents, а незапечатанные экземпляры поступают из getRootInActiveWIndow() и рекурсивно обходят дочерние элементы. Существует гораздо более слабая связь между ANI, полученными от AccessibilityEvents, и теми, которые получены от обхода getRootInActiveWindow, особенно в отношении событий AccessibilityEvents, которые отправляются часто (картинка с быстрой прокруткой содержимого). - person ChrisCM; 23.10.2019
comment
Изменение текста этих экземпляров Unsealed бессмысленно, потому что виртуальный ANI не тесно связан с их реальными объектами View на экране. Любые действия, которые вы можете выполнить из-за того, что Android не применяет должным образом Unsealed vs Sealed, являются случайными и не приведут к детерминированно значимым вещам, происходящим в результате. - person ChrisCM; 23.10.2019