我们可以为search dialog或者search widget增加语音搜索功能, 我们要做的就是在searchable configuration中添加android:voiceSearchMode属性. 这将会增加一个语音搜索按钮.当用户讲完要搜索的内容之后, 录制的查询内容将会发送到我们的searchable activity. 栗子:
xml version="1.0" encoding="utf-8"?>
android:label="@string/search_label"
android:hint="@string/search_hint"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" >
其中showVoiceSearchButton是必须的, 第二个值launchRecognizer指定了语音搜索按钮应该启动一个语音识别器, 它可以返回语音中的文本, 并发送给searchable activity. 我们还可以指定更加丰富的值给android:voiceSearchMode属性, 比如设置希望识别的语言和可以返回的最长的内容. 更多内容可以参考这里.
我们要慎重考虑是否使用语音搜索功能, 因为所有的搜索内容都会直接发送给searchable activity而不给用户重新查看的机会, 所以我们要进行充分的测试, 以保证用户得到的信息是我们想要给他们看的.
Search dialog和Search widget都可以支持搜索建议, Android会管理搜索建议的列表, 并且处理用户选择某条建议时候的事件. 我们可以提供两种搜索建议, 分别是最近查询搜索建议和自定义搜索建议(就是我们根据自己的APP的数据为用户提供的搜索建议, 如下图).
最近查询的搜索建议就是用户之前搜索过的内容作为搜索建议. 比如, 如果一个用户之前搜索过”puppies”, 那么当用户再次开始输入相同的字母的时候, 就会出现提示. 如下图:
最近查询搜索建议只是简单的保存过去的信息. 当用户选择其中某一个建议的时候, 我们的searchable activity就会收到一个带有ACTION_SEARCH的intent, 之后的操作跟以前的搜索过程就一样了. 想要提供一个这样的最近查询搜索建议, 我们需要:
1. 一个searchable activity.
2. 创建一个content provider, 需要继承自SearchRecentSuggestionsProvider并且在manifest文件中声明它.
3. 修改searchable configuration, 将content provider的内容加入到其中.
4. 在每次查询之后将查询内容保存到content provider中.
当Android显示search dialog的时候, 也会在其下面显示搜索建议, 所有我们要做的就是为Android指定一个可以获取搜索建议的源. 当Android发现用户点击了一个可以搜索并且支持搜索建议的搜索框, 那么就会发生这些:
1. Android获取到搜索框中的文本, 然后在我们指定的提供搜索建议的content provider中做查询.
2. 我们的content provider会返回一个包含所有符合条件的搜索建议的Cursor对象,.
3. Android通过这个Cursor显示一个搜索建议列表.
一旦这个搜索建议框显示出来了, 那么可能会发生下面的情况:
1. 如果用户点击了其他的按钮, 或者用别的方法修改了查询内容, 上述的步骤将会被重复然后列表会被更新.
2. 如果用户执行了搜索操作, 那么搜索建议将会被忽略掉, 并且后续跟普通的搜索操作一样, 会发送带有ACTION_SEARCH的intent给searchable activity.
3. 如果用户选择了某一条搜索建议, 那么将会使用搜索建议所在的文本发送一条带有ACTION_SEARCH的intent给searchable activity.
虽然看上去东西挺多, 但是我们并不需要写太多的代码, SearchRecentSuggestionsProvider类将会自动完成这些工作.
我们使用的content provider必须继承自SearchRecentSuggestionsProvider类. 该类几乎为我们做好了所有需要做的事, 我们需要完成的只是写一个带有一行代码的构造方法. 栗子:
public class MySuggestionProvider extends SearchRecentSuggestionsProvider {
public final static String AUTHORITY = "com.example.MySuggestionProvider";
public final static int MODE = DATABASE_MODE_QUERIES;
public MySuggestionProvider() {
setupSuggestions(AUTHORITY, MODE);
}
}
SetupSuggestions()方法传入两个参数, 第一个参数指定搜索权限的名字, 可以为任何唯一的字符串, 但是最好使用content provider的完整名. 第二个参数是数据库模式, 必须包含DATABASE_MODE_QUERIES, 可以包含DATABASE_MODE_2LINES,该参数为搜索建议多加一列数据, 如果想要每个搜索建议有两列数据的话, 我们可以这样做:
public final static int MODE = DATABASE_MODE_QUERIES |DATABASE_MODE_2LINES;
然后我们要做的就是在manifest文件中声明一个具有相同搜索权限名字的content provider. 栗子:
android:authorities="com.example.MySuggestionProvider" />
...
想要让Android使用我们的content provider, 我们需要为
xml version="1.0" encoding="utf-8"?>
android:label="@string/app_label"
android:hint="@string/search_hint"
android:searchSuggestAuthority="com.example.MySuggestionProvider"
android:searchSuggestSelection=" ?" >
其中android:searchSuggestAuthority应该是content provider的完整名字, 并且跟contentprovider的权限名字(authority)一样(就是上面栗子中的AUTHORITY字符串).
而android:searchSuggestSelection必须是一个前面有一个空格的问号, 这是SQLite的选择参数的占位符.
想要填充我们的”最近查询”, 增加每次查询到SearchRecentSuggestionsProvider, 需要这做: 创建一个SearchRecentSuggestions实例并在每次searchableactivity收到查询的时候调用saveRecentQuery()方法. 比如我们可以在searchable activity的onCreate()方法中这样做:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);
suggestions.saveRecentQuery(query, null);
}
}
SearchRecentSuggestionsProvider的构造方法需要跟contentprovider相同的authority和database mode. SaveRecentQuery()方法使用查询的字符串作为第一个参数, 第二个参数则是可选的, 是第二列的搜索建议, 它只有在我们使用DATABASE_MODE_2LINES模式的时候有用. 如果使用了这种两列模式, 那么当Android查找匹配的建议的时候也会去查询第二列数据.
为了保护用户的隐私, 我们应该提供给用户清除最近查询建议的方法. 想要清除查询历史, 我们可以调用clearHistory()方法, 栗子:
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
HelloSuggestionProvider.AUTHORITY, HelloSuggestionProvider.MODE);
suggestions.clearHistory();
可以设置一个菜单项或者一个按钮来关联这个操作, 在用户点击这个按钮之后我们应该提供一个确认的对话框.
想要实现最近查询的搜索建议功能, 流程是这样的: 首先需要构建搜索系统, 包括searchable configuration, searchable activity和搜索接口; 然后通过继承SearchRecentSuggesttionsProvider来创建contentprovider; 修改searchable configuration关联content provider; 最后记得实现保存最近查询和清空查询操作.
自定义搜索建议跟最近搜索建议类似, 但是要自己建立保存机制, 也更复杂一些, 详情可以参考这里.
参考: http://developer.android.com/guide/topics/search/adding-recent-query-suggestions.html