Cómo agregar sugerencias de búsqueda personalizadas

Puedes proporcionar sugerencias de búsqueda basadas en búsquedas recientes en el diálogo o el widget de búsqueda de Android. Por ejemplo, si un usuario consulta "cachorros", la consulta aparece como una sugerencia cuando vuelve a escribir la misma consulta. En la Figura 1, se muestra un ejemplo de un diálogo de búsqueda con sugerencias de consulta recientes.

Antes de comenzar, implementa el diálogo o un widget de búsqueda para búsquedas básicas en tu aplicación. Para aprender a hacerlo, consulta Cómo crear una interfaz de búsqueda.

Conceptos básicos

Figura 1: Captura de pantalla de un diálogo de búsqueda con sugerencias de consultas recientes.

Las sugerencias de consultas recientes son búsquedas guardadas. Cuando el usuario selecciona una sugerencia, la actividad de búsqueda recibe un intent ACTION_SEARCH con la sugerencia como la búsqueda que la actividad de búsqueda ya controla.

Para proporcionar sugerencias de consultas recientes, debes hacer lo siguiente:

  • Implementa una actividad de búsqueda.
  • Crea un proveedor de contenido que extienda SearchRecentSuggestionsProvider y decláralo en el manifiesto de tu aplicación.
  • Modifica la configuración de búsqueda con información sobre el proveedor de contenido que proporciona sugerencias de búsqueda.
  • Guarda consultas en tu proveedor de contenido cada vez que se ejecute una búsqueda.

Así como el sistema Android muestra el diálogo de búsqueda, muestra las sugerencias de búsqueda debajo del diálogo o widget de búsqueda. Debes proporcionar la fuente de la que el sistema recupera las sugerencias.

Si el sistema identifica que tu actividad se puede buscar y proporciona sugerencias de búsqueda, ocurre lo siguiente cuando el usuario escribe una consulta:

  1. El sistema toma el texto de la búsqueda (lo que sea que el usuario comience a escribir) y realiza una consulta al proveedor de contenido que contiene tus sugerencias.
  2. Tu proveedor de contenido muestra un Cursor que apunta a todas las sugerencias que coinciden con el texto de la búsqueda.
  3. El sistema muestra la lista de sugerencias proporcionadas por Cursor.

Una vez que se muestran las sugerencias de consultas recientes, puede ocurrir lo siguiente:

  • Si el usuario escribe otra clave o cambia la consulta de cualquier manera, se repiten los pasos anteriores y se actualiza la lista de sugerencias.
  • Si el usuario ejecuta la búsqueda, se ignoran las sugerencias y se entrega la búsqueda a la actividad de búsqueda con el intent ACTION_SEARCH normal.
  • Si el usuario selecciona una sugerencia, se entrega un intent ACTION_SEARCH a la actividad de búsqueda usando el texto sugerido como la consulta.

La clase SearchRecentSuggestionsProvider que extiendes para tu proveedor de contenido realiza automáticamente el trabajo de los pasos anteriores, por lo que hay poco código para escribir.

Cómo crear un proveedor de contenido

El proveedor de contenido que necesitas para las sugerencias de consultas recientes es una implementación de SearchRecentSuggestionsProvider. Esta clase hace todo por ti. Solo necesitas escribir un constructor de clase que ejecute una línea de código.

Por ejemplo, a continuación, se incluye una implementación completa de un proveedor de contenido para sugerencias de consultas recientes:

Kotlin

class MySuggestionProvider : SearchRecentSuggestionsProvider() {
    init {
        setupSuggestions(AUTHORITY, MODE)
    }

    companion object {
        const val AUTHORITY = "com.example.MySuggestionProvider"
        const val MODE: Int = SearchRecentSuggestionsProvider.DATABASE_MODE_QUERIES
    }
}

Java

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);
    }
}

La llamada a setupSuggestions() pasa el nombre de la autoridad de búsqueda y un modo de base de datos. La autoridad de búsqueda puede ser cualquier string única, pero la práctica recomendada es usar un nombre completamente calificado para tu proveedor de contenido, como el nombre del paquete seguido del nombre de clase del proveedor. Por ejemplo, "com.example.MySuggestionProvider".

El modo de base de datos debe incluir DATABASE_MODE_QUERIES y, de manera opcional, puede incluir DATABASE_MODE_2LINES, que agrega una columna a la tabla de sugerencias para que puedas proporcionar una segunda línea de texto con cada sugerencia. Si deseas proporcionar dos líneas en cada sugerencia, consulta el siguiente ejemplo:

Kotlin

const val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES

Java

public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;

Declara el proveedor de contenido en el manifiesto de tu aplicación con la misma string de autoridad que se usa en tu clase SearchRecentSuggestionsProvider y en la configuración de búsqueda. Por ejemplo:

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

Modifica la configuración de búsqueda

Para configurar el sistema a fin de que use tu proveedor de sugerencias, agrega los atributos android:searchSuggestAuthority y android:searchSuggestSelection al elemento <searchable> en tu archivo de configuración de búsqueda. Por ejemplo:

<?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>

El valor de android:searchSuggestAuthority debe ser un nombre completamente calificado para tu proveedor de contenido que coincida exactamente con la autoridad utilizada en el proveedor de contenido, como "com.example.MySuggestionProvider" en los ejemplos anteriores.

El valor de android:searchSuggestSelection debe ser un solo signo de interrogación precedido por un espacio: " ?". Este es un marcador de posición para el argumento de selección de SQLite y se reemplaza automáticamente por el texto de la consulta que ingresó el usuario.

Guardar consultas

Para propagar la colección de consultas recientes, agrega cada consulta recibida por la actividad de búsqueda a tu SearchRecentSuggestionsProvider. Para ello, crea una instancia de SearchRecentSuggestions y llama a saveRecentQuery() cada vez que tu actividad de búsqueda reciba una consulta. Por ejemplo, así puedes guardar la consulta durante el método onCreate() de tu actividad:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main)

    if (Intent.ACTION_SEARCH == intent.action) {
        intent.getStringExtra(SearchManager.QUERY)?.also { query ->
            SearchRecentSuggestions(this, MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE)
                    .saveRecentQuery(query, null)
        }
    }
}

Java

@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);
    }
}

El constructor SearchRecentSuggestionsProvider requiere la misma autoridad y el mismo modo de base de datos declarados por tu proveedor de contenido.

El método saveRecentQuery() toma la cadena de búsqueda como primer parámetro y, de forma opcional, una segunda cadena para incluir como segunda línea de la sugerencia o nula. El segundo parámetro solo se usa si habilitas el modo de dos líneas para las sugerencias de búsqueda con DATABASE_MODE_2LINES. Si habilitas el modo de dos líneas, el texto de la consulta coincidirá con la segunda línea cuando el sistema busque sugerencias coincidentes.

Borrar los datos de las sugerencias

Para proteger la privacidad del usuario, siempre proporciona una forma para que borre las sugerencias de consultas recientes. Para borrar el historial de consultas, llama a clearHistory(). Por ejemplo:

Kotlin

SearchRecentSuggestions(this, HelloSuggestionsProvider.AUTHORITY, HelloSuggestionsProvider.MODE)
        .clearHistory()

Java

SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
        HelloSuggestionProvider.AUTHORITY, HelloSuggestionProvider.MODE);
suggestions.clearHistory();

Ejecuta esto desde un elemento de menú, elemento de preferencia o botón de "Borrar el historial de búsqueda". Proporciona un diálogo de confirmación para verificar si el usuario desea borrar su historial de búsqueda.