summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/topics/search/adding-recent-query-suggestions.jd
blob: e1020dd185650f9c241e46b1d658e58ed1f87cb3 (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
226
227
228
229
230
231
232
233
234
235
236
page.title=Adding Recent Query Suggestions
page.tags=SearchRecentSuggestions,SearchRecentSuggestionsProvider

@jd:body

<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#TheBasics">The Basics</a></li>
<li><a href="#RecentQueryContentProvider">Creating a Content Provider</a></li>
<li><a href="#RecentQuerySearchableConfiguration">Modifying the Searchable
Configuration</a></li>
<li><a href="#SavingQueries">Saving Queries</a></li>
<li><a href="#ClearingSuggestionData">Clearing the Suggestion Data</a></li>
</ol>

<h2>Key classes</h2>
<ol>
<li>{@link android.provider.SearchRecentSuggestions}</li>
<li>{@link android.content.SearchRecentSuggestionsProvider}</li>
</ol>

<h2>See also</h2>
<ol>
<li><a href="searchable-config.html">Searchable Configuration</a></li>
</ol>
</div>
</div>

<p>When using the Android search dialog or search widget, you can provide search suggestions based
on recent search
queries. For example, if a user previously searched for "puppies," then that query appears as a
suggestion once he or she begins typing the same query. Figure 1 shows an example of a search dialog
with recent query suggestions.</p>

<p>Before you begin, you need to implement the search dialog or a search widget for basic searches
in your application.
If you haven't, see <a href="search-dialog.html">Creating a Search Interface</a>.</p>



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

<div class="figure" style="width:250px">
<img src="{@docRoot}images/search/search-suggest-recent-queries.png" alt="" height="417"  />
<p class="img-caption"><strong>Figure 1.</strong> Screenshot of a search dialog with recent query
suggestions.</p>
</div>

<p>Recent query suggestions are simply saved searches. When the user selects one of
the suggestions, your searchable activity receives a {@link
android.content.Intent#ACTION_SEARCH} intent with the suggestion as the search query, which your
searchable activity already handles (as described in <a href="search-dialog.html">Creating a Search
Interface</a>).</p>

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

<ul>
  <li>Implement a searchable activity, as described in <a
href="{@docRoot}guide/topics/search/search-dialog.html">Creating a Search Interface</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 that
provides search suggestions.</li>
  <li>Save queries to your content provider each time a search is executed.</li>
</ul>

<p>Just as the Android system displays the search dialog, it also displays the
search suggestions below the dialog or search widget. All you need to do is provide a source from
which the system can retrieve suggestions.</p>

<p>When the system identifies that your activity is searchable and provides search
suggestions, the following procedure takes place as soon as the user begins typing a query:</p>

<ol>
  <li>The system takes the search query text (whatever has been typed so far) and performs a
query to the content provider that contains your suggestions.</li>
  <li>Your content provider returns a {@link android.database.Cursor} that points to all
suggestions that match the search query text.</li>
  <li>The system displays the list of suggestions provided by the Cursor.</li>
</ol>

<p>Once the recent query suggestions are displayed, the following might happen:</p>

<ul>
  <li>If the user types another key, or changes the query in any way, the aforementioned steps are
repeated and the suggestion list is updated.</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, an
{@link android.content.Intent#ACTION_SEARCH} intent is delivered to your searchable activity using
the suggested text as the query.</li>
</ul>

<p>The {@link android.content.SearchRecentSuggestionsProvider} class that
you extend for your content provider automatically does the work described above, so there's
actually very little code to write.</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 = "com.example.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)
setupSuggestions()} passes the name of the search authority and a
database mode. The search authority can be any unique string, but the best practice is to use a
fully qualified name for your content provider
(package name followed by the provider's class name; for example,
"com.example.MySuggestionProvider"). The database mode must include {@link
android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_QUERIES} and can optionally include
{@link
android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_2LINES}, which adds another column
to the suggestions table that allows you to provide a second line of text with each suggestion. For
example, if you want to provide two lines in each suggestion:</p>

<pre>
public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;
</pre>

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

<pre>
&lt;application>
    &lt;provider android:name=".MySuggestionProvider"
              android:authorities="com.example.MySuggestionProvider" />
    ...
&lt;/application>
</pre>



<h2 id="RecentQuerySearchableConfiguration">Modifying the Searchable Configuration</h2>

<p>To configure the system to use your suggestions provider, 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"
    <b>android:searchSuggestAuthority="com.example.MySuggestionProvider"
    android:searchSuggestSelection=" ?"</b> >
&lt;/searchable>
</pre>

<p>The value for {@code android:searchSuggestAuthority} should be a fully qualified name for
your content provider that exactly matches the authority used in the content provider (the {@code
AUTHORITY} string in the above example).
</p>

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



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

<p>To populate your collection of recent queries, add each query
received by your searchable activity to your {@link
android.content.SearchRecentSuggestionsProvider}. To do this, create an instance of {@link
android.provider.SearchRecentSuggestions} and call {@link
android.provider.SearchRecentSuggestions#saveRecentQuery(String,String) saveRecentQuery()} 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>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)
saveRecentQuery()} method takes
the search query string as the first parameter and, optionally, a second string to include as the
second line of the suggestion (or null). 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 is also matched against this second line when the system
looks for matching suggestions.</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 query history, call {@link
android.provider.SearchRecentSuggestions#clearHistory()}. For example:</p>

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

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