summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/topics/search/adding-recent-query-suggestions.jd
blob: 37e0e8275edffb86f1e882ca6a90244889ecfd85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
page.title=Adding Recent Query Suggestions
parent.title=Search
parent.link=index.html
@jd:body

<div id="qv-wrapper">
<div id="qv">
<h2>Key classes</h2>
<ol>
<li>{@link android.provider.SearchRecentSuggestions}</li>
<li>{@link android.content.SearchRecentSuggestionsProvider}</li>
</ol>
<h2>In this document</h2>
<ol>
<li><a href="#TheBasics">The Basics</a></li>
<li><a href="#RecentQuerySearchableConfiguration">Modifying the searchable
configuration</a></li>
<li><a href="#RecentQueryContentProvider">Creating a Content Provider</a></li>
<li><a href="#SavingQueries">Saving queries</a></li>
<li><a href="#ClearingSuggestionData">Clearing the suggestion data</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="searchable-config.html">Searchable Configuration</a></li>
</ol>
</div>
</div>

<p>The Android search framework provides the ability for your application to
provide suggestions while the user types into the Android search dialog. In this guide, you'll learn
how to create recent query suggestions. These are suggestions based
on queries previously entered by the user. So, if the user previously searched for "puppies" then it
will appear as a suggestion as they begin typing the same string of text. The screenshot below
shows an example of recent query suggestions.</p>

<p>Before you begin, you need to have implemented the Android search dialog for searches in your
application. If you haven't done this, see <a href="search-dialog.html">Using the Android Search
Dialog</a>.</p>


<h2 id="TheBasics">The Basics</h2>

<img src="{@docRoot}images/search/search-suggest-recent-queries.png" alt="" height="417"
style="float:right;clear:right;" />

<p>Recent query suggestions are simply saved searches. When the user selects one of
the suggestions, your searchable Activity will receive a normal {@link
android.content.Intent#ACTION_SEARCH} Intent with the suggestion as the search query, which your
searchable Activity will already handle.</p>

<p>To provide recent queries suggestions, you need to:</p>

<ul>
  <li>Implement a basic searchable Activity, as documented in <a
href="{@docRoot}guide/topics/search/search-dialog.html">Using the Android Search Dialog</a>.</li>
  <li>Create a content provider that extends {@link
android.content.SearchRecentSuggestionsProvider} and declare it in your application manifest.</li>
  <li>Modify the searchable configuration with information about the content provider.</li>
  <li>Save queries to your content provider each time a search is made.</li>
</ul>

<p>Just like the Search Manager handles the rendering of the search dialog, it will also do the work
to display all search suggestions below the search dialog. All you need to do is provide a source
from which the suggestions can be retrieved.</p>

<p>When the Search Manager identifies that your Activity is searchable and also provides search
suggestions, the following procedure will take place as soon as the user types into the Android
search box:</p>

<ul>
  <li>The Search Manager takes the search query text (whatever has been typed so far) and performs a
query to the content provider that manages your suggestions.</li>
  <li>Your content provider then returns a {@link android.database.Cursor} that points to all
suggestions that are relevant to the search query text.</li>
  <li>The Search Manager then displays the list of suggestions provided by the Cursor (as
demonstrated in the screenshot to the right).</li>
</ul>

<p>At this point, the following may happen:</p>

<ul>
  <li>If the user types another key, or changes the query in any way, the above steps are repeated
and the suggestion list is updated as appropriate.</li>
  <li>If the user executes the search, the suggestions are ignored and the search is delivered
to your searchable Activity using the normal {@link android.content.Intent#ACTION_SEARCH}
Intent.</li>
  <li>If the user selects a suggestion, a normal
{@link android.content.Intent#ACTION_SEARCH} Intent is triggered, using the suggested text as the
query.</li>
</ul>

<p>As you'll soon discover, the {@link android.content.SearchRecentSuggestionsProvider} class that
you'll extend for your content provider will automatically do the work described above, so there's
actually very little code to write.</p>


<h2 id="RecentQuerySearchableConfiguration">Modifying the searchable configuration</h2>

<p>First, you need to add the {@code android:searchSuggestAuthority} and
{@code android:searchSuggestSelection} attributes to the {@code &lt;searchable&gt;} element in your
searchable configuration file. For example:</p>

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

<p>The value for {@code android:searchSuggestAuthority} should be a fully-qualified name for
your content provider: your application package name followed by the name of your content provider.
This string must match the authority used in the content provider (discussed in the next section).
</p>

<p>The value for {@code android:searchSuggestSelection} must be a single question-mark, preceded by
a space (" ?"), which is simply a placeholder for the SQLite selection argument (which will be
automatically replaced by the query text entered by the user).</p>


<h2 id="RecentQueryContentProvider">Creating a Content Provider</h2>

<p>The content provider that you need for recent query suggestions must be an implementation
of {@link android.content.SearchRecentSuggestionsProvider}. This class does practically everything
for you. All you have to do is write a class constructor that executes one line of code.</p>

<p>For example, here's a complete implementation of a content provider for recent query
suggestions:</p>

<pre>
public class MySuggestionProvider extends SearchRecentSuggestionsProvider {
    public final static String AUTHORITY = "my.package.MySuggestionProvider";
    public final static int MODE = DATABASE_MODE_QUERIES;

    public MySuggestionProvider() {
        setupSuggestions(AUTHORITY, MODE);
    }
}
</pre>

<p>The call to {@link android.content.SearchRecentSuggestionsProvider#setupSuggestions(String,int)}
passes the name of the search authority (matching the one in the searchable configuration) and a
database mode. The database mode must include {@link
android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_QUERIES} and can optionally include
{@link
android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_2LINES}, which will add another column
to the suggestions table that allows you to provide a second line of text with each suggestion. For
example:</p>
<pre>
public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;
</pre>

<p>In the following section, you'll see how to save both lines of text.</p>

<p>Now simply declare the content provider in your application manifest with the same authority
string used in the class (and in the searchable configuration). For example:</p>

<pre>
&lt;application>
    &lt;provider android:name=".MySuggestionProvider"
              android:authorities="my.package.authority" />
    ...
&lt;/application>
</pre>


<h2 id="SavingQueries">Saving queries</h2>

<p>In order to populate your collection of recent queries, you need to add each query
received by your searchable Activity to the content provider you've just built. To do this, create
an instance of {@link
android.provider.SearchRecentSuggestions} and call {@link
android.provider.SearchRecentSuggestions#saveRecentQuery(String,String)} each time your searchable
Activity receives a query. For example, here's how you can save the query during your
Activity's {@link android.app.Activity#onCreate(Bundle) onCreate()} method:</p>

<pre>
&#64;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);
    }
}
</pre>

<p>Notice that the {@link android.content.SearchRecentSuggestionsProvider} constructor requires the
same authority and database mode declared by your content provider.</p>

<p>The {@link android.provider.SearchRecentSuggestions#saveRecentQuery(String,String)} method takes
the search query string as the first parameter and, optionally, a second string to include as the
second line of the suggestion. The second parameter is only used if you've enabled two-line mode
for the search suggestions with {@link
android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_2LINES}. If you have enabled
two-line mode, then the query text will be matched against this second line as well.</p>

<p>That's all that's needed to build a recent queries suggestion provider. However, there's one
other important thing to do: provide the ability for the user to clear this search history.</p>


<h2 id="ClearingSuggestionData">Clearing the suggestion data</h2>

<p>To protect the user's privacy, you should always provide a way for the user to clear the recent
query suggestions. To clear the recent queries, simply call {@link
android.provider.SearchRecentSuggestions#clearHistory()}. For example:</p>

<pre>
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
        HelloSuggestionProvider.AUTHORITY, HelloSuggestionProvider.MODE);
suggestions.clearHistory();
</pre>

<p>Simply execute this from your choice of a "Clear Search History" menu item,
preference item, or button. You should also provide a confirmation dialog when this is pressed, to
verify that the user wants to delete their search history.</p>