Как определить, был ли поиск выполнен посредством ввода текста или распознавания голоса?
Это будет вопрос с самостоятельным ответом, потому что я хотел бы четко документировать, как определить, была ли цель поиска вызвана вводом текста или распознаванием голоса. Причиной этого было то, что я пытался записать результаты поиска в своем приложении в Google Analytics, и мне нужно было знать, печатал ли пользователь свои запросы на клавиатуре в виде текста или использовал функцию голосового поиска.
Я нашел несколько вопросов о Stackru, которые касались этого вопроса, но я обнаружил, что их трудно найти и они плохо документированы. Поэтому, надеюсь, мой ответ предоставит правильные ключевые слова и детали, которые помогут другим найти эту тему быстрее и яснее в будущем.
1 ответ
Активность поиска в моем приложении выполняется в singleTop
режим, и поэтому я обрабатываю входящие поисковые запросы через @Override
из onNewIntent()
, В рамках этого метода первое, что вам нужно сделать, это проверить, является ли входящее намерение фактически поисковым. Мы осуществляем это следующим образом:
if (intent.getAction().equals(Intent.ACTION_SEARCH)){}
Следующая часть немного сложна и вызвала у меня некоторые ложные срабатывания на старых API. Есть два дополнения, которые прилагаются к ACTION_SEARCH
цель: QUERY
а также USER_QUERY
, Если мы прочитаем об этих двух значениях в SearchManager
документы, мы находим следующую информацию:
public static final String QUERY
:
Назначение дополнительного ключа данных: используйте этот ключ с
content.Intent.getStringExtra()
получить строку запроса изIntent.ACTION_SEARCH
,
public static final String USER_QUERY
:
Назначение дополнительного ключа данных: используйте этот ключ с
content.Intent.getStringExtra()
получить строку запроса, набранную пользователем. Это может отличаться от значения QUERY, если намерение является результатом выбора предложения. В этом случае QUERY будет содержать значение SUGGEST_COLUMN_QUERY для предложения, а USER_QUERY будет содержать строку, введенную пользователем.
По сути, мы можем извлечь из этих двух записей в документе, что значение QUERY
всегда будет содержать фактическое значение поиска, независимо от того, как поиск был выполнен. Таким образом, не имеет значения, набрал ли пользователь в поиске, произнес это с помощью распознавания голоса или выбрал поисковое предложение - это поле будет содержать необработанное значение String того, что он искал.
С другой стороны, USER_QUERY
может быть или не быть нулевым, в зависимости от того, как был выполнен поиск. Если пользователь вводит в своем поиске текст, это поле будет содержать значение его поиска. Если пользователь выполняет поиск с распознаванием голоса, это значение будет нулевым.
Это дает нам отличный (хотя и в какой-то степени хакерский) способ определить, набрал ли пользователь текст в поиске или использовал функцию голосового поиска. Но вот сложная часть: как вы можете видеть в документации выше, предлагается использовать getStringExtra()
чтобы получить это значение из намерения. Это не надежно, потому что ценность USER_QUERY
на самом деле SpannableString
не String
, Это, вероятно, приведет к ClassCastException
потому что если вы используете getStringExtra()
вы пытаетесь разыграть SpannableString
к String
, который не будет работать. Исключение будет автоматически перехвачено для вас, но в результате вы можете получить ложно-положительное значение NULL, в результате чего ваш код поверит, что поиск был выполнен с помощью распознавания голоса, тогда как на самом деле введенное текстовое значение просто потеряно, потому что ClassCastException.
Таким образом, решение состоит в том, чтобы вместо этого работать с SpannableString
приходящий из USER_QUERY
и вместо этого проверьте нулевое значение, чтобы не вызывать исключение ClassCastException и ложноположительное значение null. Но вы заметите, что Intent
не имеет метода для получения SpannableStrings, но у него есть getCharSequenceExtra()
метод. поскольку SpannableString
инвентарь CharSequence
, мы можем просто использовать этот метод, чтобы извлечь нашу USER_QUERY SpannableString и привести ее к выходу. Итак, мы сделаем это так:
SpannableString user_query_spannable = (SpannableString) intent.getCharSequenceExtra(SearchManager.USER_QUERY);
Теперь мы можем проверить нулевое значение этого значения, чтобы безопасно определить, набрал ли пользователь текст или выполнил поиск каким-либо другим способом, таким как распознавание голоса.
Собрав все это вместе, мы получим что-то вроде этого:
@Override
protected void onNewIntent(Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SEARCH)) {
SpannableString user_query_spannable = (SpannableString) intent.getCharSequenceExtra(SearchManager.USER_QUERY);
//if this was a voice search
if (user_query_spannable == null) {
//Log, send Analytics hit, etc.
//Then perform search as normal...
performSearch(intent.getStringExtra(SearchManager.QUERY));
} else {
//Log, send Analytics hit, etc.
//Then perform search as normal
performSearch(intent.getStringExtra(SearchManager.QUERY));
}
}
}
Как я упоминал ранее, для меня эту информацию было нелегко найти с помощью поисков в Google и в Stackru, особенно когда официальная документация по Android содержит вводящую в заблуждение информацию о том, как работать с этими значениями. Надеемся, что этот ответ предоставит гораздо более удобный источник доступа для тех, кто ищет подобную информацию.
Пакет [{android.speech.extra.RESULTS=[hello], query=hello, android.speech.extra.CONFIDENCE_SCORES=[0.9299549]}] ЭТО БУДЕТ В НАБОРЕ ДЛЯ ГОЛОСА