如何确定搜索是通过文本输入还是语音识别进行的?
How to determine if a search was performed through text input or voice recognition?
这将是一个自我回答的问题,因为我想清楚地记录如何确定搜索意图是由文本输入还是语音识别触发的。我需要这个的原因是因为我试图将我的应用程序中的搜索记录到 Google Analytics,我需要知道用户是否在键盘上以文本形式输入他们的搜索,或者他们是否使用语音搜索功能。
我在 Whosebug 上发现了几个解决这个问题的问题,但我发现它们很难找到并且记录很少。所以希望我的回答能提供正确的关键字和细节,帮助其他人在未来更快更清楚地找到这个主题。
我的应用程序中的搜索 Activity 在 singleTop
模式下是 运行,因此我通过 @Override
或 onNewIntent()
处理传入的搜索意图].在此方法中,您需要做的第一件事是检查传入的意图是否实际上是搜索意图。我们通过以下方式完成此操作:
if (intent.getAction().equals(Intent.ACTION_SEARCH)){}
下一部分有点棘手,导致我对旧 API 产生了一些误报。 ACTION_SEARCH
意图附加了两个附加项:QUERY
和 USER_QUERY
。如果我们在 SearchManager
docs 中阅读这两个值,我们会发现以下信息:
public static final String QUERY
:
Intent extra data key: Use this key with
content.Intent.getStringExtra()
to obtain the query string from
Intent.ACTION_SEARCH
.
public static final String USER_QUERY
:
Intent extra data key: Use this key with
content.Intent.getStringExtra()
to obtain the query string typed in
by the user. This may be different from the value of QUERY if the
intent is the result of selecting a suggestion. In that case, QUERY
will contain the value of SUGGEST_COLUMN_QUERY for the suggestion,
and USER_QUERY will contain the string typed by the user.
基本上我们可以从这两个文档条目中收集到的是 QUERY
的值将始终包含搜索的实际值,无论搜索是如何执行的。因此,无论用户是输入搜索内容、通过语音识别说出搜索内容还是选择搜索建议,都没有关系——该字段将包含他们所搜索内容的原始字符串值。
另一方面,USER_QUERY
可能为空也可能不为空,具体取决于搜索的执行方式。如果用户使用文本输入他们的搜索,这个字段将包含他们搜索的值。如果用户使用语音识别执行搜索,此值将为 null。
这为我们提供了一个很好的(尽管在某种程度上是 hacky)方法来确定用户是使用文本输入搜索还是使用语音搜索功能。但这是棘手的部分:正如您在上面的文档中看到的,建议使用 getStringExtra()
从意图中检索此值。 这个不靠谱,因为USER_QUERY
的值实际上是一个SpannableString
,而不是String
。这可能会导致 ClassCastException
,因为如果您使用 getStringExtra()
,您试图将 SpannableString
转换为 String
,这将不起作用。系统会自动为您捕获异常,但您可能会收到一个误报 null 作为结果,导致您的代码认为搜索是通过语音识别执行的,而实际上由于 ClassCastException,输入的文本值丢失了。
因此解决方案是改为使用来自 USER_QUERY
的 SpannableString
,并检查其是否为 null,这样您就不会触发 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 和 Whosebug 上的搜索不容易找到这些信息,尤其是当官方 Android 文档提供有关如何使用这些值的误导性信息时.希望这个答案将为其他寻找类似信息的人提供更容易访问的资源。
捆绑包[{android.speech.extra.RESULTS=[你好],查询=你好,android.speech.extra.CONFIDENCE_SCORES=[0.9299549]}]
这将包含在语音包中
这将是一个自我回答的问题,因为我想清楚地记录如何确定搜索意图是由文本输入还是语音识别触发的。我需要这个的原因是因为我试图将我的应用程序中的搜索记录到 Google Analytics,我需要知道用户是否在键盘上以文本形式输入他们的搜索,或者他们是否使用语音搜索功能。
我在 Whosebug 上发现了几个解决这个问题的问题,但我发现它们很难找到并且记录很少。所以希望我的回答能提供正确的关键字和细节,帮助其他人在未来更快更清楚地找到这个主题。
我的应用程序中的搜索 Activity 在 singleTop
模式下是 运行,因此我通过 @Override
或 onNewIntent()
处理传入的搜索意图].在此方法中,您需要做的第一件事是检查传入的意图是否实际上是搜索意图。我们通过以下方式完成此操作:
if (intent.getAction().equals(Intent.ACTION_SEARCH)){}
下一部分有点棘手,导致我对旧 API 产生了一些误报。 ACTION_SEARCH
意图附加了两个附加项:QUERY
和 USER_QUERY
。如果我们在 SearchManager
docs 中阅读这两个值,我们会发现以下信息:
public static final String QUERY
:
Intent extra data key: Use this key with
content.Intent.getStringExtra()
to obtain the query string fromIntent.ACTION_SEARCH
.
public static final String USER_QUERY
:
Intent extra data key: Use this key with
content.Intent.getStringExtra()
to obtain the query string typed in by the user. This may be different from the value of QUERY if the intent is the result of selecting a suggestion. In that case, QUERY will contain the value of SUGGEST_COLUMN_QUERY for the suggestion, and USER_QUERY will contain the string typed by the user.
基本上我们可以从这两个文档条目中收集到的是 QUERY
的值将始终包含搜索的实际值,无论搜索是如何执行的。因此,无论用户是输入搜索内容、通过语音识别说出搜索内容还是选择搜索建议,都没有关系——该字段将包含他们所搜索内容的原始字符串值。
另一方面,USER_QUERY
可能为空也可能不为空,具体取决于搜索的执行方式。如果用户使用文本输入他们的搜索,这个字段将包含他们搜索的值。如果用户使用语音识别执行搜索,此值将为 null。
这为我们提供了一个很好的(尽管在某种程度上是 hacky)方法来确定用户是使用文本输入搜索还是使用语音搜索功能。但这是棘手的部分:正如您在上面的文档中看到的,建议使用 getStringExtra()
从意图中检索此值。 这个不靠谱,因为USER_QUERY
的值实际上是一个SpannableString
,而不是String
。这可能会导致 ClassCastException
,因为如果您使用 getStringExtra()
,您试图将 SpannableString
转换为 String
,这将不起作用。系统会自动为您捕获异常,但您可能会收到一个误报 null 作为结果,导致您的代码认为搜索是通过语音识别执行的,而实际上由于 ClassCastException,输入的文本值丢失了。
因此解决方案是改为使用来自 USER_QUERY
的 SpannableString
,并检查其是否为 null,这样您就不会触发 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 和 Whosebug 上的搜索不容易找到这些信息,尤其是当官方 Android 文档提供有关如何使用这些值的误导性信息时.希望这个答案将为其他寻找类似信息的人提供更容易访问的资源。
捆绑包[{android.speech.extra.RESULTS=[你好],查询=你好,android.speech.extra.CONFIDENCE_SCORES=[0.9299549]}] 这将包含在语音包中