Using Android Search Dialog. Recent Query Suggestions. (part 2)


image

Article essential reading for those who mastered the first part . The article explains how to modify your application so that added to the dialogue hints at a recent search queries. To understand the code and theory (beyond what was required in the first part) requires knowledge of the content providers. It can be gleaned from official Gajda .



A bit of theory


In fact, hints of the recent searches are simply saved queries. When the user selects one of the tips, the Activity, which is responsible for search, type Search gets Intent with a hint of a line, it is already treated before. For displaying tooltips, as well as for the whole dialogue, responds Search Manager, and is used to store the content provider.

When the Search Manager determines our Activity as responsible for finding and providing clues to the search, the following sequence of actions occurs:
  1. When the Search Manager receives the search request, it sends a request to the content provider, provides tips.
  2. Content provider returns a cursor that points to clues that coincide with the text search.
  3. Search Manager displays a prompt, using the cursor

Once a list of tips has been mapped, it may be the following:
  • If the user changes the text of the query, then all of the above steps are repeated.
  • If the user starts the search, the hints are ignored.
  • If the user selects a clue what to Activity Intent is delivered with the text that prompts the query.

So, to implement the tips we need the following:
  • Create a content provider, which will inherit from SearchRecentSuggestionsProvider and declare it in the manifesto
  • Change the configuration xml file dialog to add the information about the content provider
  • Change Activty so that it retained searches every time we run search

Create a content provider


All we need is a content provider that inherits SearchRecentSuggestionsProvider . This class makes for virtually all of the developer and all that is required of us - is to write a constructor.

File SuggestionProvider.java
package com.example.search;

import android.content.SearchRecentSuggestionsProvider;

public class SuggestionProvider extends SearchRecentSuggestionsProvider {
public final static String AUTHORITY = "com.example.search.SuggestionProvider" ;
public final static int MODE = DATABASE_MODE_QUERIES;

public SuggestionProvider() {
setupSuggestions(AUTHORITY, MODE);
}
}


* This source code was highlighted with Source Code Highlighter .

Method setupSuggestions () takes a string and the authorization mode of the database content provider. The string can be any authorization, the only requirement - is unique. However, official documentation is recommended to use the full name of the content provider, including the name of the package. Mode database should include DATABASE_MODE_QUERIES , and optionally you can add DATABASE_MODE_2LINES . In the second case to the table hint is added to the column that allows you to display hints for each of the second row. Look in the code is as follows:
public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;

* This source code was highlighted with Source Code Highlighter .

Now do not forget that you must declare our content provider in the manifest.

File AndroidManifest.xml
<? xml version ="1.0" encoding ="utf-8" ? >
< manifest xmlns:android ="http://schemas.android.com/apk/res/android"
package ="com.example.search"
android:versionCode ="1"
android:versionName ="1.0" >
< application android:icon ="@drawable/icon" android:label ="@string/app_name" >
< activity android:name =".Main"
android:label ="@string/app_name" >
< intent-filter >
< action android:name ="android.intent.action.MAIN" />
< category android:name ="android.intent.category.LAUNCHER" />
</ intent-filter >
< intent-filter >
< action android:name ="android.intent.action.SEARCH" />
</ intent-filter >
< meta-data
android:name ="android.app.searchable"
android:resource ="@xml/searchable"
/>
</ activity >
< provider android:name =".SuggestionProvider"
android:authorities ="com.example.search.SuggestionProvider" />
</ application >
< uses-sdk android:minSdkVersion ="5" />

</ manifest >


* This source code was highlighted with Source Code Highlighter .


Changing the configuration file



To use our dialogue content provider for tips to add to his options android: searchSuggestAuthority and android: searchSuggestSelection

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


* This source code was highlighted with Source Code Highlighter .

The value of android: searchSuggestAuthority must exactly match the string authorize the content provider.
The value of android: searchSuggestSelection must be a question mark placed after a space, because this is an argument from a sample database and the question mark is automatically replaced with the text typed by the user.

Change Activity



All we need - is to save the query text for this class is instantiated SearchRecentSuggestions and callssaveRecentQuery () . This happens every time the Activity Intent comes with a request for search data. In the method saveRecentQuery () takes two parameters, the first is mandatory and is a string search query, the second - optional, required if you use DATABASE_MODE_2LINES to display the second line of text on the tooltip.

The official documentation is also recommended to provide an interface for clearing the entire table hints.Apparently, it is necessary to ensure user's privacy. We just add another menu item, when clicked, will be called clearing the entire history of requests.

File Main.java
package com.example.search;

import android.app.ListActivity;
import android.app.SearchManager;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.SearchRecentSuggestions;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SimpleCursorAdapter;

public class Main extends ListActivity {
private EditText text;
private Button add;
private RecordsDbHelper mDbHelper;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Создаем экземпляр БД
mDbHelper = new RecordsDbHelper( this );
//Открываем БД для записи
mDbHelper.open();
//Получаем Intent
Intent intent = getIntent();
//Проверяем тип Intent
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
//Берем строку запроса из экстры
String query = intent.getStringExtra(SearchManager.QUERY);
//Создаем экземпляр SearchRecentSuggestions
SearchRecentSuggestions suggestions = new SearchRecentSuggestions( this ,
SuggestionProvider.AUTHORITY, SuggestionProvider.MODE);
//Сохраняем запрос
suggestions.saveRecentQuery(query, null );
//Выполняем поиск
showResults(query);
}

add = (Button) findViewById(R.id.add);
text = (EditText) findViewById(R.id.text);
add.setOnClickListener( new View.OnClickListener() {
public void onClick(View view) {
String data = text.getText().toString();
if (!data.equals( "" )) {
saveTask(data);
text.setText( "" );
}
}
});
}

private void saveTask( String data) {
mDbHelper.createRecord(data);
}

private void showResults( String query) {
//Ищем совпадения
Cursor cursor = mDbHelper.fetchRecordsByQuery(query);
startManagingCursor(cursor);
String [] from = new String [] { RecordsDbHelper.KEY_DATA };
int [] to = new int [] { R.id.text1 };

SimpleCursorAdapter records = new SimpleCursorAdapter( this ,
R.layout.record, cursor, from , to);
//Обновляем адаптер
setListAdapter(records);
}
//Создаем меню для вызова поиска (интерфейс в res/menu/main_menu.xml)
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true ;
}

public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.search_record:
//Вызываем поиск
onSearchRequested();
return true ;
case R.id.clear_recent_suggestions:
//Очищаем историю
SearchRecentSuggestions suggestions = new SearchRecentSuggestions( this ,
SuggestionProvider.AUTHORITY, SuggestionProvider.MODE);
suggestions.clearHistory();
return true ;
default :
return super.onOptionsItemSelected(item);
}
}
}


* This source code was highlighted with Source Code Highlighter .


Conclusion

This article used the documentation from developer.android.com
The entire project is modified to code.google.com