getExtractedText при неактивном предупреждении InputConnection на android

129

В моем журнале появляется следующее предупреждение.

getExtractedText on inactive InputConnection

Я не могу найти причину этого. Пожалуйста помоги

pankajagarwal
источник
4
Я не понимаю, что в этом вопросе двусмысленно / расплывчато / неполно? Я получаю это предупреждение в моем журнале при запуске своего приложения, я хочу знать причину этого предупреждения.
pankajagarwal
2
Я также вижу это в своем приложении, которое разрабатываю, и понятия не имею, откуда оно взялось и почему. Если кто-нибудь узнает, оставьте, пожалуйста, комментарий. На самом деле он показывает много разных предупреждений, кроме "getExtractedText". Я также вижу: beginBatchEdit, endBatchEdit, getTextBeforeCursor и многие другие.
span
1
смотрят ли модераторы на этот вопрос? Если нет, то они должны, потому что если они все еще считают этот вопрос расплывчатым и неоднозначным даже после 14 голосов, то я не знаю, что сказать
панкаджагарвал
Я согласен, это проблема, которую мне тоже нужно решить. Я понятия не имею о причине.
JonWillis
3
Какой у вас код, вызывающий эту ошибку?
Bill the Lizard

Ответы:

44

Я столкнулся с подобной проблемой. Мой логарифм:

W/IInputConnectionWrapper(21214): getTextBeforeCursor on inactive InputConnection
W/IInputConnectionWrapper(21214): getSelectedText on inactive InputConnection
W/IInputConnectionWrapper(21214): getTextBeforeCursor on inactive InputConnection
W/IInputConnectionWrapper(21214): getTextAfterCursor on inactive InputConnection
...
I/Choreographer(20010): Skipped 30 frames!  The application may be doing too much work on its main thread.

Моя ситуация: у меня есть представление EditText, в которое вводит пользователь. EditText очищается, когда пользователь нажимает кнопку. Когда я быстро нажимаю кнопку, выводится множество неактивных записей InputConnection.

Пример:

editText.setText(null);

Последняя строка в моем logcat выше дает отличное представление о том, что происходит. Конечно, InputConnection перегружен запросами на очистку текста. Я попытался изменить код, чтобы проверить длину текста, прежде чем пытаться его очистить:

if (editText.length() > 0) {
    editText.setText(null);
}

Это помогает смягчить проблему, поскольку быстрое нажатие кнопки больше не вызывает поток предупреждений IInputConnectionWrapper. Однако это по-прежнему подвержено проблемам, когда пользователь быстро переключается между набором текста и нажатием кнопки или нажатием кнопки, когда приложение находится под достаточной нагрузкой и т. Д.

К счастью, я нашел другой способ очистки текста: Editable.clear () . При этом я вообще не получаю предупреждений:

if (editText.length() > 0) {
    editText.getText().clear();
}

Обратите внимание, что если вы хотите очистить все состояние ввода, а не только текст (автотекст, автокап, мультитап, отменить), вы можете использовать TextKeyListener.clear (Editable e) .

if (editText.length() > 0) {
    TextKeyListener.clear(editText.getText());
}
Джонсон Вонг
источник
1
Я также получал предупреждения IInputConnectionWrapper, и мое приложение получило почти ANR, у меня сработал метод clear () ... супер странная ошибка, до того, как я установил setText ("");
бокс
17

Обновить:

Причина, по которой я получал предупреждения InputConnection, заключалась не в том, где я устанавливал текст (например, в обратном вызове onTextChangedили afterTextChanged) , а в том , что я использовал setText.

Я решил проблему, позвонив:

hiddenKeyboardText.getText().clear();
hiddenKeyboardText.append("some string");

Примечание: я все еще вызываю afterTextChangedобратный вызов, хотя он также работает без предупреждений от ontextChanged.

Предыдущий ответ:

Я также получал идентичные сообщения в logcat, хотя мой сценарий был немного другим. Я хотел прочитать каждый символ, входящий в EditText (или составленные символы / вставленный текст), а затем сбросить соответствующий EditText на строку инициализации по умолчанию.

Часть с открытым текстом работает в соответствии с решением Джонсона выше. Однако сбросить текст было проблематично, и я получал предупреждения о входном соединении.

Изначально my onTextChanged(CharSequence s, ...)определялся следующим образом:

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    if (isResettingKeyboard)
        return;

    // ... do what needs to be done

    resetKeyboardString();

}

public void resetKeyboardString()
{
    isResettingKeyboard = true;

    hiddenKeyboardText.getText().clear();
    hiddenKeyboardText.setText(keyboardInitString);
    hiddenKeyboardText.setSelection(defaultKeyboardCursorLocation);

    isResettingKeyboard = false;
}

Когда onTextChanged(...)вызывается, EditText находится в режиме только для чтения. Я не уверен, означает ли это, что мы не можем сделать больше, чем вызвать getText.clear()его ( setText(...)вызовы также вызывают предупреждения inputConnection).

Однако обратный вызов afterTextChanged(Editable s)- это правильное место для установки текста.

@Override
public void afterTextChanged(Editable s) {

    if (isResettingKeyboard)
        return;

    resetKeyboardString();

    // ... 
}

Пока это работает без каких-либо предупреждений.

ahash
источник
У меня тоже была такая же проблема. Я понял, что, хотя ваше решение заставляет исчезнуть предупреждения InputConnection, я заметил, что afterTextChangedметод вызывается hiddenKeyboardText.getText().clear();так же, как hiddenKeyboardText.append("some string");и включен , и этот факт также следует учитывать. +1 от меня!
Ник
@Nick true - важно убедиться, что if (isResettingKeyboard) return;он на высоте ...
ахаш
7

Из справочных документов

http://developer.android.com/reference/android/view/inputmethod/InputConnection.html

Интерфейс InputConnection - это канал связи от InputMethod обратно к приложению, которое получает его ввод. Он используется для выполнения таких вещей, как чтение текста вокруг курсора, фиксация текста в текстовом поле и отправка необработанных ключевых событий в приложение.

Кроме того, дальнейшее чтение показывает

getExtractedText (): этот метод может завершиться ошибкой, если входное соединение стало недействительным (например, сбой его процесса), или клиент слишком долго отвечает с текстом (ему дается пара секунд для возврата) . В любом случае возвращается ноль.

Похоже, он также отслеживает изменения такого текста и предупреждает об изменениях.

Чтобы разобраться в проблеме, вам нужно будет изучить любые запросы к базе данных, которые вы делаете, возможно, в отношении listViews или списков в макете.

Если у вас нет представлений, например, это происходит случайным образом в фоновом режиме, я бы предположил, что это не проблема элемента пользовательского интерфейса, поэтому игнорируйте текстовые поля и тому подобное. Это может быть фоновая служба, которая хранит информацию в курсоре или запрашивает курсор.

Кроме того, возникает ли проблема из-за вашего приложения? или, возможно, чужой, который вы недавно установили. Вывести полную трассировку logCat. Кто-то может распознать проблему.

Я рискну предположить, что если вы не написали что-то конкретное по этому поводу, это сообщение журнала кого-то еще или, возможно, библиотеки, которую вы используете?

Emile
источник
1
спасибо, я делаю запросы к базе данных, но, как ни странно, это предупреждение не появляется при запуске приложения на эмуляторе, поэтому на самом деле это может быть связано с каким-то другим приложением, установленным на моем устройстве. Будем смотреть в этом направлении
pankajagarwal
Я думаю, что последний logCat показывает ваши сообщения, отличные от других приложений, отфильтрованные. Однако не использовал его достаточно, чтобы подтвердить это. Вы можете создать новое пустое приложение и следить за журналом cat, чтобы увидеть, возникает ли ошибка, которая устранит ваше приложение. от вопроса.
Эмиль
@frieza не обязательно другое приложение. Я добавил ArrayAdapter с sqlite и теперь тоже получаю это предупреждение по телефону. Я предполагаю, что вы не видите ошибок в эмуляторе, потому что он работает медленно, и, как следствие, пороги производительности отключены.
alandarev
7

У меня была такая же проблема. Предупреждение появилось, когда программная клавиатура была активирована в одном из моих EditTextsи активность потеряла фокус.

Что я сделал, так это спрятал клавиатуру в onPause ();

@Override
protected void onPause() {

    // hide the keyboard in order to avoid getTextBeforeCursor on inactive InputConnection
    InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);

    inputMethodManager.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);

    super.onPause();
}
antoniom
источник
2
Это правильный ответ. Убедитесь, что вы скрыли клавиатуру, прежде чем уходить от активности, которая в данный момент отображается на экране.
Gábor
1

Решил эту проблему для себя, возможно, у вас такая же проблема.

Это было вызвано объектом в HeaderView из списка адаптеров .

Я раздул View, объявил Object и поместил на него TextWatcher .

View v = LayoutInflater.from(CONTEXT).inflate(R.layout.in_overscrollview, null);
Object= (Object) v.findViewById(R.id.OBJECT_ID);

Object.addTextChangedListener(new TextWatcher() {
        @Override
        public void afterTextChanged(Editable s) {
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after){
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        //Do my work
        //Update my view
        }
});

Добавил его в список адаптеров и построил адаптер.

JobListView = (ListView) getListView().findViewWithTag("JOBLISTVIEWTAG");
JobListView.addHeaderView(v, null, false);
JobsAdapter = new IN_JOBS_ADAPTER(CONTEXT, ITEMS_FOR_ADATER);
ListView.setAdapter(JOBSadapter);

Все нормально Text Watcher работает.

НО, если я когда-нибудь пересобираю адаптер после первоначальной сборки.

JobsAdapter = new IN_JOBS_ADAPTER(CONTEXT, DIFFERENT_ITEMS_FOR_ADAPTER);
ListView.setAdapter(JOBSadapter);

Этот HeaderView тоже перестраивается.

Это предупреждение появилось, потому что объект был удален, а Text Watcher все еще наблюдал за ним.

Список адаптер и Object были заменены, и я предполагаю , что текст Watcher смотрит в другую сторону , когда это случилось.

Таким образом, предупреждение исчезает, и чудесным образом Text Watcher находит HeaderView и Object . Но он теряет фокус и регистрирует это предупреждение.

С помощью

JOBSadapter.notifyDataSetChanged();

исправил проблему.

НО, если у вас есть объект внутри адаптера , а Text Watcher прикреплен к объекту внутри адаптера . Тогда вам, возможно, придется проделать еще немного работы.

Попробуйте удалить Listener и снова присоединить его после выполнения любой работы.

Object.removeTextChangedListener();

или

Object.addTextChangedListener(null);
Xjasz
источник
1

Помимо ответа Антониома, убедитесь, что любые дальнейшие действия, которые необходимо выполнить, действительно выполняются после скрытия клавиатуры, поэтому, если вы скрыли клавиатуру, как показано ниже:

public void hideKeyboard() {
InputMethodManager inputMethodManager =(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
}

, вам необходимо выполнить следующие действия после скрытия клавиатуры, например:

getWindow().getDecorView().post(new Runnable() {            
        @Override
        public void run() {
            finish(); //Sample succeeding code
     }
});
Пьер Бетос
источник
0

У меня была эта проблема, когда мне нужно было изменить или получить текст из EditText, и он был сфокусирован.

Поэтому, прежде чем изменить или получить от него, я закрыл клавиатуру и исправил ее.

InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);

Может, у тебя проблема в другом.

Анджело Морони
источник
0

Я решил свою проблему, вставив тип ввода в xml следующим образом: android: inputType = "none | text | textCapWords | textUri"

до этого был android: inputType = "text" Это решило мою проблему.

Neemias Fernandes
источник
3
Ничего не сделал для меня.
DSlomer64
0

Ошибка в Logcat: getTextBeforeCursor при неактивном InputConnection

Решение: скройте клавиатуру ввода и запустите приложение.

Shyam
источник
0

Скрыть программную клавиатуру перед очисткой EditText - предупреждения не будут отображаться.

Кроме того, похоже, это зависит от устройства . Видел только на Nexus 4 (Android 7.1). Никаких предупреждений на эмуляторах (8.0, 7.1) или Nexus 5.

Inoy
источник
0

Моя проблема была вызвана установкой видимости EditTextдля, GONEа затем немедленной установкой ее на VISIBLEкаждый раз, когда пользователь вводил символ, так как я запускал проверку ввода каждый раз, когда текст менялся, а в некоторых случаях представление необходимо было скрыть.

Поэтому решение состоит в том, чтобы не устанавливать для видимости представления или макета значение GONE между обновлениями пользовательского интерфейса или состояния, так как они EditTextмогут потерять фокус.

Это
источник
0

Решите ту же проблему и исправьте ее, преобразовав мой виджет без сохранения состояния в виджет с полным состоянием, вы можете попробовать

Мохамед Адли
источник