我的应用程序中的搜索活动正在singleTop
模式下运行,因此我正在通过@Override
of处理传入的搜索意图onNewIntent()
。在此方法中,您需要做的第一件事是检查传入的意图是否实际上是搜索意图。我们通过以下方式完成此操作:
if (intent.getAction().equals(Intent.ACTION_SEARCH)){}
下一部分有点棘手,并导致我对旧 API 产生了一些误报。有两个附加到ACTION_SEARCH
意图:QUERY
和USER_QUERY
. SearchManager
如果我们在docs中阅读这两个值,我们会发现以下信息:
public static final String QUERY
:
意图额外数据键:使用此键
content.Intent.getStringExtra()
来获取查询字符串
Intent.ACTION_SEARCH
。
public static final String USER_QUERY
:
Intent extra data key:使用这个key
content.Intent.getStringExtra()
来获取用户输入的查询字符串。如果意图是选择建议的结果,这可能与 QUERY 的值不同。在这种情况下,QUERY 将包含建议的 SUGGEST_COLUMN_QUERY 的值,
而 USER_QUERY 将包含用户键入的字符串。
本质上,我们可以从这两个 doc 条目中收集到的值QUERY
将始终包含搜索的实际值,而不管搜索是如何执行的。因此,无论用户是输入搜索内容、通过语音识别说出它还是选择了搜索建议,这都无关紧要——该字段将包含他们正在搜索的内容的原始字符串值。
另一方面,USER_QUERY
可能为空,也可能不为空,具体取决于执行搜索的方式。如果用户使用文本输入他们的搜索,该字段将包含他们的搜索值。如果用户使用语音识别执行搜索,则此值为 null。
这为我们提供了一种很好的(尽管在某种程度上是骇人听闻的)方法来确定用户是在搜索中键入文本还是使用了语音搜索功能。但这里是棘手的部分:正如您在上面的文档中看到的,建议使用getStringExtra()
从意图中检索此值。这是不可靠的,因为 的值USER_QUERY
实际上是 a SpannableString
,而不是 a String
。这可能会导致 a ClassCastException
,因为如果您使用getStringExtra()
,您会尝试将 a 强制转换SpannableString
为 a String
,这是行不通的。将自动为您捕获异常,但您可能会收到一个误报的空值作为结果,导致您的代码相信搜索是通过语音识别执行的,而实际上键入的文本值只是因为 ClassCastException 而丢失。
因此,解决方案是改为使用SpannableString
from USER_QUERY
,并检查其是否为 null,这样您就不会触发 ClassCastException 和误报 null。但是你会注意到它Intent
没有获取 SpannableStrings 的方法,但它确实有一个getCharSequenceExtra()
方法。由于SpannableString
implements 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 和 StackOverflow 上的搜索很难找到这些信息,尤其是当官方 Android 文档提供了有关如何使用这些值的误导性信息时。希望这个答案将为寻找类似信息的其他人提供更容易访问的资源。