提供语音搜索功能:

我们可以为search dialog或者search widget增加语音搜索功能, 我们要做的就是在searchable configuration中添加android:voiceSearchMode属性. 这将会增加一个语音搜索按钮.当用户讲完要搜索的内容之后, 录制的查询内容将会发送到我们的searchable activity. 栗子:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
     android:label="@string/search_label"
     android:hint="@string/search_hint"
     android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" >
</searchable>


其中showVoiceSearchButton是必须的, 第二个值launchRecognizer指定了语音搜索按钮应该启动一个语音识别器, 它可以返回语音中的文本, 并发送给searchable activity. 我们还可以指定更加丰富的值给android:voiceSearchMode属性, 比如设置希望识别的语言和可以返回的最长的内容. 更多内容可以参考这里.

我们要慎重考虑是否使用语音搜索功能, 因为所有的搜索内容都会直接发送给searchable activity而不给用户重新查看的机会, 所以我们要进行充分的测试, 以保证用户得到的信息是我们想要给他们看的.

增加搜索建议:

Search dialog和Search widget都可以支持搜索建议, Android会管理搜索建议的列表, 并且处理用户选择某条建议时候的事件. 我们可以提供两种搜索建议, 分别是最近查询搜索建议和自定义搜索建议(就是我们根据自己的APP的数据为用户提供的搜索建议, 如下图). 

android keycode数字对应 android code search_search

如何使用最近查询的搜索建议:

最近查询的搜索建议就是用户之前搜索过的内容作为搜索建议. 比如, 如果一个用户之前搜索过”puppies”, 那么当用户再次开始输入相同的字母的时候, 就会出现提示. 如下图:


android keycode数字对应 android code search_搜索_02


最近查询搜索建议只是简单的保存过去的信息. 当用户选择其中某一个建议的时候, 我们的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类将会自动完成这些工作.

创建一个ContentProvider:

我们使用的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. 栗子:

<application>
     <provider android:name=".MySuggestionProvider"
               android:authorities="com.example.MySuggestionProvider" />
     ...
</application>


修改Searchableconfiguration:

想要让Android使用我们的content provider, 我们需要为<searchable>添加两个属性, android:searchSuggestAuthority和android:searchSuggestSelection,栗子:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
     android:label="@string/app_label"
     android:hint="@string/search_hint"
     android:searchSuggestAuthority="com.example.MySuggestionProvider"
     android:searchSuggestSelection=" ?" >
</searchable>


其中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