Android 的搜索机制 II-提供更复杂的搜索功能

提供语音搜索功能:

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

xml version="1.0" encoding="utf-8"?>
xmlns:android="http://schemas.android.com/apk/res/android"
    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的数据为用户提供的搜索建议, 如下图). 

Android 的搜索机制 II-提供更复杂的搜索功能_第1张图片

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

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

Android 的搜索机制 II-提供更复杂的搜索功能_第2张图片

最近查询搜索建议只是简单的保存过去的信息. 当用户选择其中某一个建议的时候, 我们的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. 栗子:


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

修改Searchableconfiguration:

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

xml version="1.0" encoding="utf-8"?>
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=" ?"
>

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




你可能感兴趣的:(Android,基础)