Cómo agregar sugerencias personalizadas

Cuando usas el widget o el diálogo de búsqueda de Android, puedes proporcionar sugerencias de búsqueda personalizadas que se crean a partir de los datos de tu aplicación. Por ejemplo, si la aplicación es un diccionario, puedes sugerir palabras del diccionario que coincidan con el texto ingresado. Esas son las sugerencias más valiosas, porque puedes predecir de manera efectiva lo que el usuario quiere y proporcionarle acceso instantáneo. En la figura 1, se muestra un ejemplo de un diálogo de búsqueda con sugerencias personalizadas.

Una vez que proporcionas sugerencias personalizadas, también puedes ponerlas en el cuadro de búsqueda rápida de todo el sistema y, así, brindar acceso al contenido desde fuera de la aplicación.

Antes de comenzar a leer esta guía para agregar sugerencias personalizadas, debes haber implementado el diálogo de búsqueda de Android o un widget de búsqueda para las búsquedas en tu aplicación. Si no lo hiciste, consulta Cómo crear una interfaz de búsqueda. También deberías consultar la documentación de los proveedores de contenido.

Conceptos básicos

Figura 1: Captura de pantalla de un diálogo de búsqueda con sugerencias personalizadas

Cuando el usuario selecciona una sugerencia personalizada, el sistema Android envía un Intent a la actividad de búsqueda. Mientras que una búsqueda normal envía un intent con la acción ACTION_SEARCH, puedes definir tus sugerencias personalizadas para usar ACTION_VIEW (o cualquier otra acción de intent), además de incluir datos que sean relevantes para la sugerencia seleccionada. Siguiendo con el ejemplo del diccionario, cuando el usuario selecciona una sugerencia, la aplicación puede abrir inmediatamente la definición de esa palabra en lugar de buscar coincidencias en el diccionario.

Para proporcionar sugerencias personalizadas, haz lo siguiente:

  • Implementa una actividad básica de búsqueda, como se describe en Cómo crear una interfaz de búsqueda.
  • Modifica la configuración de búsqueda con información sobre el proveedor de contenido que proporciona sugerencias personalizadas.
  • Crea una tabla (como en un SQLiteDatabase) para las sugerencias y formatea la tabla con las columnas requeridas.
  • Crea un proveedor de contenido que tenga acceso a tu tabla de sugerencias y declara al proveedor en tu manifiesto.
  • Declara el tipo de Intent que se enviará cuando el usuario seleccione una sugerencia (incluidos una acción personalizada y datos personalizados).

Así como el sistema Android muestra el diálogo de búsqueda, también muestra las sugerencias de búsqueda. Todo lo que necesitas es un proveedor de contenido desde el cual el sistema pueda recuperar tus sugerencias. Si no sabes cómo crear proveedores de contenido, lee la guía para desarrolladores sobre proveedores de contenido antes de continuar.

Si el sistema identifica que la actividad se puede buscar y proporciona sugerencias de búsqueda, se lleva a cabo el siguiente procedimiento cuando el usuario escribe una consulta:

  1. El sistema toma el texto de la búsqueda (lo que se escribió hasta el momento) y realiza una consulta al proveedor de contenido que administra tus sugerencias.
  2. Tu proveedor de contenido muestra un Cursor que apunta a todas las sugerencias relevantes para el texto de la búsqueda.
  3. El sistema muestra la lista de sugerencias que proporciona el cursor.

Una vez que se muestran las sugerencias personalizadas, puede ocurrir lo siguiente:

  • Si el usuario escribe otra palabra clave o cambia la consulta de alguna forma, se repiten los pasos anteriores y se actualiza la lista de sugerencias de manera correspondiente.
  • 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 normal ACTION_SEARCH.
  • Si el usuario selecciona una sugerencia, se envía un intent a tu actividad de búsqueda, que tiene una acción personalizada y datos personalizados para que tu aplicación pueda abrir el contenido sugerido.

Cómo modificar la configuración de búsqueda

Para admitir las sugerencias personalizadas, agrega el atributo android:searchSuggestAuthority al elemento <searchable> en el 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.MyCustomSuggestionProvider">
    </searchable>
    

Según el tipo de intent que adjuntes a cada sugerencia y cómo desees formatear las consultas para el proveedor de contenido, es posible que necesites algunos atributos adicionales. Los otros atributos opcionales se analizan en las secciones incluidas a continuación.

Cómo crear un proveedor de contenido

Crear un proveedor de contenido para las sugerencias personalizadas requiere conocimientos previos sobre los proveedores de contenido. Estos se describen en la guía para desarrolladores de proveedores de contenido. En términos generales, un proveedor de contenido para sugerencias personalizadas es igual que cualquier otro proveedor de contenido. Sin embargo, para cada sugerencia que proporciones, la fila respectiva en Cursor debe incluir columnas específicas que el sistema comprende y utiliza para formatear las sugerencias.

Cuando el usuario comienza a escribir en el diálogo o widget de búsqueda, el sistema consulta al proveedor de contenido para solicitar sugerencias. Para ello, llama a query() cada vez que se escribe una letra. En la implementación de query(), el proveedor de contenido debe buscar tus datos de sugerencias y mostrar un Cursor que apunte a las filas que consideres buenas sugerencias.

Los detalles sobre la creación de un proveedor de contenido para sugerencias personalizadas se analizan en las siguientes dos secciones:

Cómo manejar la consulta de sugerencias
Cómo envía el sistema solicitudes a tu proveedor de contenido y cómo manejarlas
Cómo crear una tabla de sugerencias
Cómo definir las columnas que el sistema espera en el Cursor que se muestra con cada consulta

Cómo manejar la consulta de sugerencias

Cuando el sistema solicita sugerencias del proveedor de contenido, llama al método query() del proveedor de contenido. Debes implementar este método para buscar en los datos de sugerencias y mostrar un Cursor que apunte a las sugerencias que consideres relevantes.

A continuación, se incluye un resumen de los parámetros que el sistema pasa a tu método query() (enumerados en orden):

uri
Siempre un contenido Uri, formateado como:
    content://your.authority/optional.suggest.path/SUGGEST_URI_PATH_QUERY
    

El comportamiento predeterminado es que el sistema pase este URI y lo agregue con el texto de la consulta. Por ejemplo:

    content://your.authority/optional.suggest.path/SUGGEST_URI_PATH_QUERY/puppies
    

El texto de consulta al final está codificado mediante reglas de codificación de URI, por lo que es posible que debas decodificarlo antes de realizar una búsqueda.

La parte optional.suggest.path solo se incluye en el URI si definiste dicha ruta en el archivo de configuración de búsqueda con el atributo android:searchSuggestPath. Esto solo es necesario si usas el mismo proveedor de contenido para múltiples actividades de búsqueda. En ese caso, debes desambiguar la fuente de la consulta de sugerencia.

Nota: SUGGEST_URI_PATH_QUERY no es la string literal proporcionada en el URI, sino una constante que deberías usar si necesitas hacer referencia a esta ruta.

projection
Siempre nula
selection
Es el valor proporcionado en el atributo android:searchSuggestSelection del archivo de configuración de búsqueda, o nulo si no declaraste el atributo android:searchSuggestSelection. Obtén más información para usar esta función y obtener la consulta a continuación.
selectionArgs
Contiene la búsqueda como el primer (y único) elemento del arreglo si declaraste el atributo android:searchSuggestSelection en tu configuración de búsqueda. Si no declaraste android:searchSuggestSelection, este parámetro es nulo. Obtén más información para usar esta función y obtener la consulta a continuación.
sortOrder
Siempre nulo

El sistema puede enviar el texto de la búsqueda de dos maneras. La manera predeterminada es que el texto de la consulta se incluya como la última ruta del URI de contenido que se pasa en el parámetro uri. Sin embargo, si incluyes un valor de selección en el atributo android:searchSuggestSelection de la configuración de búsqueda, el texto de la consulta se pasa como el primer elemento del arreglo de string selectionArgs. A continuación, se resumen ambas opciones.

Obtén la consulta en el URI

De manera predeterminada, la consulta se anexa como el último segmento del parámetro uri (un objeto Uri). Para recuperar el texto de la consulta en este caso, simplemente usa getLastPathSegment(). Por ejemplo:

Kotlin

    val query: String = uri.lastPathSegment.toLowerCase()
    

Java

    String query = uri.getLastPathSegment().toLowerCase();
    

Esto muestra el último segmento del Uri, que es el texto de consulta que ingresa el usuario.

Obtén la consulta en los argumentos de selección

En lugar de usar el URI, puedes decidir que tiene más sentido que el método query() reciba todo lo que necesita para realizar la búsqueda y que los parámetros selection y selectionArgs lleven los valores apropiados. En ese caso, agrega el atributo android:searchSuggestSelection a la configuración de búsqueda con tu string de selección de SQLite. En la string de selección, incluye un signo de interrogación ("?") como marcador de posición para la búsqueda real. El sistema llama a query() con la string de selección como el parámetro selection y la búsqueda como el primer elemento del arreglo selectionArgs.

Por ejemplo, a continuación, se muestra cómo puedes formar el atributo android:searchSuggestSelection para crear una instrucción de búsqueda en el texto completo:

    <?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.MyCustomSuggestionProvider"
        android:searchSuggestIntentAction="android.intent.action.VIEW"
        android:searchSuggestSelection="word MATCH ?">
    </searchable>
    

Con esta configuración, el método query() entrega el parámetro selection como "word MATCH ?" y el parámetro selectionArgs como la búsqueda. Cuando pasas estos a un método query() de SQLite, como sus respectivos argumentos, se sintetizan juntos (el signo de interrogación se reemplaza con el texto de la consulta). Si eliges recibir consultas de sugerencias de esta manera y necesitas agregar comodines al texto de la consulta, anéxalos (y/o agrégalos como prefijos) en el parámetro selectionArgs, ya que este valor se une entre comillas y se inserta en lugar del signo de interrogación.

Otro atributo nuevo en el ejemplo anterior es android:searchSuggestIntentAction, que define la acción de intent enviada con cada intent cuando el usuario selecciona una sugerencia. Se analiza más a fondo en la sección sobre Cómo declarar un intent de sugerencias.

Sugerencia: Si no quieres definir una cláusula de selección en el atributo android:searchSuggestSelection, pero deseas recibir el texto de la consulta en el parámetro selectionArgs, simplemente proporciona un valor no nulo para el atributo android:searchSuggestSelection. Eso activa la consulta que se pasará en selectionArgs y te permite ignorar el parámetro selection. De esta manera, puedes definir la cláusula de selección real en un nivel inferior para que tu proveedor de contenido no tenga que manejarla.

Cómo crear una tabla de sugerencias

Cuando muestras sugerencias al sistema con un Cursor, el sistema espera columnas específicas en cada fila. Por lo tanto, independientemente de si decides almacenar los datos de la sugerencia en una base de datos SQLite en el dispositivo, una base de datos en un servidor web u otro formato en el dispositivo o la Web, debes formatear las sugerencias como filas en una tabla y presentarlas con un Cursor.

Nota: Si tus sugerencias de búsqueda no se almacenan en un formato de tabla (como una tabla SQLite) con las columnas requeridas por el sistema, puedes buscar coincidencias en los datos de las sugerencias y, luego, formatearlos en la tabla necesaria en cada solicitud. Para ello, crea un MatrixCursor usando los nombres de columna requeridos y, luego, agrega una fila para cada sugerencia usando addRow(Object[]). Muestra el producto final a partir del método query() de tu proveedor de contenido.

El sistema comprende varias columnas, pero solo se requieren dos de ellas:

_ID
Un ID de fila de número entero único para cada sugerencia. El sistema requiere esto para presentar sugerencias en una ListView.
SUGGEST_COLUMN_TEXT_1
La string que se presenta como una sugerencia.

Las siguientes columnas son opcionales (y la mayoría de ellas se analizarán con más detalle en las siguientes secciones):

SUGGEST_COLUMN_TEXT_2
Una string. Si tu cursor incluye esta columna, todas las sugerencias se proporcionan en un formato de dos líneas. La string en esta columna se muestra como una segunda línea de texto más pequeña debajo del texto de sugerencia principal. Puede ser nula o vacía para indicar que no hay texto secundario.
SUGGEST_COLUMN_ICON_1
Una string de URI de elemento de diseño de recurso, contenido o archivo. Si tu cursor incluye esta columna, todas las sugerencias se proporcionan en un formato de ícono más texto con el ícono de elemento de diseño en el lado izquierdo. Puede ser nulo o cero para indicar que no hay ícono en esta fila.
SUGGEST_COLUMN_ICON_2
Una string de URI de elemento de diseño de recurso, contenido o archivo. Si tu cursor incluye esta columna, todas las sugerencias se proporcionan en un formato de ícono más texto con el ícono en el lado derecho. Puede ser nulo o cero para indicar que no hay ícono en esta fila.
SUGGEST_COLUMN_INTENT_ACTION
Una string de acción de intent. Si esta columna existe y contiene un valor en la fila dada, la acción definida aquí se usa cuando se forma el intent de la sugerencia. Si no se proporciona el elemento, la acción se toma del campo android:searchSuggestIntentAction de la configuración de búsqueda. Si la acción es la misma para todas las sugerencias, es más eficiente especificar la acción usando android:searchSuggestIntentAction y omitir esta columna.
SUGGEST_COLUMN_INTENT_DATA
Una string de URI de datos. Si esta columna existe y contiene un valor en la fila dada, estos son los datos que se utilizan para formar el intent de la sugerencia. Si no se proporciona el elemento, los datos se toman del campo android:searchSuggestIntentData en la configuración de búsqueda. Si no se proporciona ninguna de esas fuentes, el campo de datos del intent es nulo. Si los datos son iguales para todas las sugerencias o se pueden describir con una parte constante y un ID específico, es más eficiente especificarlo con android:searchSuggestIntentData y omitir esta columna.
SUGGEST_COLUMN_INTENT_DATA_ID
Una string de ruta de URI. Si esta columna existe y contiene un valor en la fila dada, entonces "/" y este valor se agregan al campo de datos en el intent. Esto solo debe usarse si el campo de datos especificado por el atributo android:searchSuggestIntentData en la configuración de búsqueda ya se estableció en una string de base apropiada.
SUGGEST_COLUMN_INTENT_EXTRA_DATA
Datos arbitrarios. Si esta columna existe y contiene un valor en una fila dada, estos son los datos adicionales utilizados para formar el intent de la sugerencia. Si no se proporciona, el campo de datos adicionales del intent es nulo. Esta columna permite que las sugerencias proporcionen datos adicionales que se incluyen como un valor adicional en la clave EXTRA_DATA_KEY del intent.
SUGGEST_COLUMN_QUERY
Si esta columna existe y este elemento existe en la fila dada, estos son los datos que se utilizan para formar la consulta de la sugerencia, incluidos como valores adicionales en la clave QUERY del intent. Se requiere si la acción de la sugerencia es ACTION_SEARCH. De lo contrario, es opcional.
SUGGEST_COLUMN_SHORTCUT_ID
Solo se utiliza cuando se proporcionan sugerencias para el cuadro de búsqueda rápida. Esta columna indica si una sugerencia de búsqueda debe almacenarse como un acceso directo y si debe validarse. En general, los accesos directos se forman cuando el usuario hace clic en una sugerencia del cuadro de búsqueda rápida. Si falta, el resultado se almacena como un acceso directo y no se actualiza nunca. Si se configura como SUGGEST_NEVER_MAKE_SHORTCUT, el resultado no se almacena como un acceso directo. De lo contrario, el ID del acceso directo se usa para comprobar si hay una sugerencia actualizada mediante SUGGEST_URI_PATH_SHORTCUT.
SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING
Solo se utiliza cuando se proporcionan sugerencias para el cuadro de búsqueda rápida. Esta columna especifica que se debe mostrar un ícono giratorio en lugar de un ícono de SUGGEST_COLUMN_ICON_2 mientras se actualiza el acceso directo de esta sugerencia en el cuadro de búsqueda rápida.

Algunas de estas columnas se describen con más detalle en las siguientes secciones.

Cómo declarar un intent para sugerencias

Cuando el usuario selecciona una sugerencia de la lista que aparece debajo del diálogo o widget de búsqueda, el sistema envía un Intent personalizado a tu actividad de búsqueda. Debes definir la acción y los datos para el intent.

Cómo declarar la acción de intent

La acción de intent más común para una sugerencia personalizada es ACTION_VIEW, que es apropiada cuando deseas abrir algo, como la definición de una palabra, la información de contacto de una persona o una página web. Sin embargo, la acción de intent puede ser cualquier otra acción y hasta puede ser diferente para cada sugerencia.

Dependiendo de si quieres que todas las sugerencias utilicen la misma acción de intent, puedes definir la acción de dos maneras:

  1. Usa el atributo android:searchSuggestIntentAction del archivo de configuración de búsqueda a fin de definir la acción para todas las sugerencias.

    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.MyCustomSuggestionProvider"
            android:searchSuggestIntentAction="android.intent.action.VIEW" >
        </searchable>
        
  2. Usa la columna SUGGEST_COLUMN_INTENT_ACTION para definir la acción de las sugerencias individuales.

    Agrega la columna SUGGEST_COLUMN_INTENT_ACTION a la tabla de sugerencias y coloca en cada sugerencia la acción que desees usar (como "android.intent.action.VIEW").

También puedes combinar estas dos técnicas. Por ejemplo, puedes incluir el atributo android:searchSuggestIntentAction con una acción que se utilizará con todas las sugerencias de forma predeterminada y, luego, anular esa acción para algunas sugerencias declarando una acción diferente en la columna SUGGEST_COLUMN_INTENT_ACTION. Si no incluyes un valor en la columna SUGGEST_COLUMN_INTENT_ACTION, se utilizará el intent proporcionado en el atributo android:searchSuggestIntentAction.

Nota: Si no incluyes el atributo android:searchSuggestIntentAction en tu configuración de búsqueda, debes incluir un valor en la columna SUGGEST_COLUMN_INTENT_ACTION para cada sugerencia; de lo contrario, el intent fallará.

Cómo declarar datos de intent

Cuando el usuario selecciona una sugerencia, tu actividad de búsqueda recibe el intent con la acción que definiste (como se analizó en la sección anterior), pero el intent también debe llevar datos para que tu actividad identifique qué sugerencia se seleccionó. Específicamente, los datos deben ser únicos para cada sugerencia, como el ID de fila para la sugerencia en la tabla de SQLite. Cuando se recibe el intent, puedes recuperar los datos adjuntos con getData() o getDataString().

Puedes definir los datos incluidos con el intent de dos maneras:

  1. Define los datos para cada sugerencia dentro de la columna SUGGEST_COLUMN_INTENT_DATA de la tabla de sugerencias.

    Proporciona toda la información de datos necesaria para cada intent en la tabla de sugerencias. Para ello, incluye la columna SUGGEST_COLUMN_INTENT_DATA y, luego, propágala con datos únicos para cada fila. Los datos de esta columna se adjuntan al intent exactamente como lo definiste en esta columna. Luego puedes recuperarlos con getData() o getDataString().

    Sugerencia: Por lo general, lo más fácil es usar el ID de fila de la tabla como datos de intent, ya que siempre es único. Y la forma más sencilla de hacerlo es usar el nombre de la columna SUGGEST_COLUMN_INTENT_DATA como un alias para la columna de ID de fila. Consulta la app de ejemplo de diccionario de búsqueda para ver un ejemplo en el que SQLiteQueryBuilder crea alias a partir de un mapa de proyección de nombres de columnas.

  2. Fragmenta un URI de datos en dos partes: la parte común a todas las sugerencias y la parte única de cada sugerencia. Coloca esas partes en el atributo android:searchSuggestintentData de la configuración de búsqueda y en la columna SUGGEST_COLUMN_INTENT_DATA_ID de la tabla de sugerencias, respectivamente.

    Declara el fragmento del URI que es común a todas las sugerencias en el atributo android:searchSuggestIntentData de tu 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.MyCustomSuggestionProvider"
            android:searchSuggestIntentAction="android.intent.action.VIEW"
            android:searchSuggestIntentData="content://com.example/datatable" >
        </searchable>
        

    Luego, incluye la ruta final para cada sugerencia (la parte única) en la columna SUGGEST_COLUMN_INTENT_DATA_ID de la tabla de sugerencias. Cuando el usuario selecciona una sugerencia, el sistema toma la string de android:searchSuggestIntentData, agrega una barra ("/") y luego agrega el valor respectivo de la columna SUGGEST_COLUMN_INTENT_DATA_ID para formar un URI de contenido completo. Luego, puedes recuperar Uri con getData().

Agrega más datos

Si necesitas expresar aún más información con tu intent, puedes agregar otra columna de tabla, SUGGEST_COLUMN_INTENT_EXTRA_DATA, que puede almacenar información adicional sobre la sugerencia. Los datos guardados en esta columna se colocan en EXTRA_DATA_KEY del paquete adicional del intent.

Cómo manejar el intent

Ahora que proporcionas sugerencias de búsqueda personalizadas con intents personalizados, necesitas que tu actividad de búsqueda maneje estos intents cuando el usuario seleccione una sugerencia. Esto se suma a manejar el intent ACTION_SEARCH, algo que la actividad de búsqueda ya hace. A continuación, se incluye un ejemplo de cómo puedes manejar los intents durante tu devolución de llamada onCreate() de actividad:

Kotlin

    when(intent.action) {
        Intent.ACTION_SEARCH -> {
            // Handle the normal search query case
            intent.getStringExtra(SearchManager.QUERY)?.also { query ->
                doSearch(query)
            }
        }
        Intent.ACTION_VIEW -> {
            // Handle a suggestions click (because the suggestions all use ACTION_VIEW)
            showResult(intent.data)
        }
    }
    

Java

    Intent intent = getIntent();
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        // Handle the normal search query case
        String query = intent.getStringExtra(SearchManager.QUERY);
        doSearch(query);
    } else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
        // Handle a suggestions click (because the suggestions all use ACTION_VIEW)
        Uri data = intent.getData();
        showResult(data);
    }
    

En este ejemplo, la acción de intent es ACTION_VIEW y los datos llevan un URI completo que apunta al elemento sugerido, como resumen la string android:searchSuggestIntentData y la columna SUGGEST_COLUMN_INTENT_DATA_ID. El URI luego se pasa al método local showResult() que consulta al proveedor de contenido por el elemento que especifica el URI.

Nota: No es necesario agregar un filtro de intent al archivo de manifiesto de Android para la acción de intent que definiste con el atributo android:searchSuggestIntentAction o la columna SUGGEST_COLUMN_INTENT_ACTION. El sistema abre la actividad de búsqueda por nombre para entregar el intent de la sugerencia. Por eso, la actividad no necesita declarar la acción aceptada.

Cómo reescribir el texto de la consulta

Si el usuario navega por la lista de sugerencias utilizando los controles direccionales (como con una bola de seguimiento o un pad direccional), de manera predeterminada, el texto de consulta no se actualiza. Sin embargo, puedes reescribir de forma temporal el texto de consulta del usuario como aparece en el cuadro de texto con una consulta que coincida con la sugerencia actualmente enfocada. Esto le permite al usuario ver qué consulta se sugiere (si corresponde), seleccionar el cuadro de búsqueda y editar la consulta antes de enviarla como búsqueda.

Puedes reescribir el texto de la consulta de las siguientes maneras:

  1. Agrega el atributo android:searchMode a la configuración de búsqueda con el valor "queryRewriteFromText". En este caso, el contenido de la columna SUGGEST_COLUMN_TEXT_1 de la sugerencia se utiliza para reescribir el texto de la consulta.
  2. Agrega el atributo android:searchMode a la configuración de búsqueda con el valor "queryRewriteFromData". En este caso, el contenido de la columna SUGGEST_COLUMN_INTENT_DATA de la sugerencia se usa para reescribir el texto de la consulta. Esto solo debe usarse con URI u otros formatos de datos que vayan a ser visibles para el usuario, como las URL HTTP. Los esquemas de URI internos no deben usarse para reescribir la consulta de esta manera.
  3. Proporciona una cadena de texto de consulta única en la columna SUGGEST_COLUMN_QUERY de la tabla de sugerencias. Si esta columna está presente y contiene un valor para la sugerencia actual, se utiliza para reescribir el texto de la consulta (y anular cualquiera de las implementaciones anteriores).

Cómo exponer sugerencias de búsqueda al cuadro de búsqueda rápida

Una vez que configuras la aplicación para proporcionar sugerencias de búsqueda personalizadas, ponerlas a disposición del cuadro de búsqueda rápida accesible a nivel mundial es tan fácil como modificar la configuración de búsqueda para incluir android:includeInGlobalSearch como "true".

El único escenario en el que se necesita trabajo adicional es cuando el proveedor de contenido exige un permiso de lectura. En ese caso, debes agregar un elemento especial <path-permission> para que el proveedor otorgue acceso de lectura del cuadro de búsqueda rápida al proveedor de contenido. Por ejemplo:

    <provider android:name="MySuggestionProvider"
              android:authorities="com.example.MyCustomSuggestionProvider"
              android:readPermission="com.example.provider.READ_MY_DATA"
              android:writePermission="com.example.provider.WRITE_MY_DATA">
      <path-permission android:pathPrefix="/search_suggest_query"
                       android:readPermission="android.permission.GLOBAL_SEARCH" />
    </provider>
    

En este ejemplo, el proveedor restringe el acceso de lectura y escritura al contenido. El elemento <path-permission> modifica la restricción al otorgar acceso de lectura al contenido dentro del prefijo de ruta "/search_suggest_query" cuando existe el permiso "android.permission.GLOBAL_SEARCH". Esto otorga acceso al cuadro de búsqueda rápida para que pueda consultar sugerencias al proveedor de contenido.

Si el proveedor de contenido no impone permisos de lectura, el cuadro de búsqueda rápida puede leerlo de manera predeterminada.

Cómo habilitar sugerencias en un dispositivo

Cuando tu aplicación está configurada para proporcionar sugerencias en el cuadro de búsqueda rápida, en realidad, de manera predeterminada, no está habilitada para proporcionar sugerencias en el cuadro de búsqueda rápida. El usuario decide si quiere incluir sugerencias de tu aplicación en el cuadro de búsqueda rápida. Para habilitar las sugerencias de búsqueda desde tu aplicación, el usuario debe abrir "Elementos de búsqueda" (en Configuración > Búsqueda) y habilitar tu aplicación como elemento de búsqueda.

Cada aplicación que está disponible para el cuadro de búsqueda rápida tiene una entrada en la página de configuración de elementos de búsqueda. La entrada incluye el nombre de la aplicación y una descripción breve de qué contenido se puede buscar desde la aplicación y poner a disposición para sugerencias en el cuadro de búsqueda rápida. Para definir el texto descriptivo de la aplicación de búsqueda, agrega el atributo android:searchSettingsDescription a la 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.MyCustomSuggestionProvider"
        android:searchSuggestIntentAction="android.intent.action.VIEW"
        android:includeInGlobalSearch="true"
        android:searchSettingsDescription="@string/search_description" >
    </searchable>
    

La string de android:searchSettingsDescription debe ser lo más concisa posible y establecer el contenido que se puede buscar. Por ejemplo, "Artistas, álbumes y pistas" para una aplicación de música, o "Notas guardadas" para una aplicación de bloc de notas. Proporcionar esta descripción es importante para que el usuario sepa qué tipo de sugerencias se proporcionan. Siempre debes incluir este atributo cuando android:includeInGlobalSearch sea "true".

Recuerda que el usuario debe visitar el menú de configuración a fin de habilitar las sugerencias de búsqueda para tu aplicación antes de que las sugerencias de búsqueda aparezcan en el cuadro de búsqueda rápida. Por eso, si la búsqueda es un aspecto importante de la aplicación, es posible que desees considerar una forma de transmitir eso a los usuarios (puedes proporcionar una nota la primera vez que inicien la app, que les indique cómo habilitar las sugerencias de búsqueda para el cuadro de búsqueda rápida).

Cómo administrar accesos directos a sugerencias de cuadro de búsqueda rápida

Las sugerencias que el usuario selecciona del cuadro de búsqueda rápida se pueden convertir de manera automática en accesos directos. Estas son sugerencias que el sistema copió del proveedor de contenido para que pueda acceder rápidamente a la sugerencia sin la necesidad de volver a consultar al proveedor de contenido.

De manera predeterminada, esta opción está habilitada para todas las sugerencias que recupera el cuadro de búsqueda rápida. Sin embargo, si tus datos de sugerencias cambian con el tiempo, puedes solicitar que se actualicen. Por ejemplo, si tus sugerencias hacen referencia a datos dinámicos, como el estado de presencia de un contacto, debes solicitar que se actualicen las combinaciones de sugerencias cuando se muestren al usuario. Para ello, incluye el SUGGEST_COLUMN_SHORTCUT_ID en tu tabla de sugerencias. Con esta columna, puedes configurar el comportamiento del acceso directo para cada sugerencia de una de las siguientes maneras:

  1. Haz que el cuadro de búsqueda rápida vuelva a consultar al proveedor de contenido para obtener una versión nueva del acceso directo de sugerencia.

    Proporciona un valor en la columna SUGGEST_COLUMN_SHORTCUT_ID y la sugerencia se vuelve a consultar para obtener una versión nueva cada vez que se muestra el acceso directo. El acceso directo se muestra rápido con los datos disponibles más recientemente hasta que se muestra la consulta de actualización. En ese momento, se actualiza la sugerencia con la información nueva. La consulta de actualización se envía a tu proveedor de contenido con una ruta de URI de SUGGEST_URI_PATH_SHORTCUT (en lugar de SUGGEST_URI_PATH_QUERY).

    El Cursor que muestres deberá contener una sugerencia con las mismas columnas que la sugerencia original o deberá estar vacío, lo cual indica que el acceso directo ya no es válido (en ese caso, la sugerencia desaparece y se quita el acceso directo).

    Si una sugerencia se refiere a datos que podrían tardar más en actualizarse, como una actualización basada en red, también puedes agregar la columna SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING a la tabla de sugerencias con el valor "true" para mostrar un ícono giratorio de progreso para el ícono de la derecha hasta que se complete la actualización. Cualquier valor que no sea "true" no mostrará el ícono giratorio de progreso.

  2. Evita que la sugerencia se copie en un acceso directo.

    Proporciona un valor de SUGGEST_NEVER_MAKE_SHORTCUT en la columna SUGGEST_COLUMN_SHORTCUT_ID. En este caso, la sugerencia nunca se copia en un acceso directo. Esto solo debería ser necesario si no deseas que aparezca la sugerencia que se copió anteriormente. (Recuerda que, si proporcionas un valor normal para la columna, el acceso directo para sugerencias solo aparece hasta que se muestre la consulta de actualización).

  3. Permite que se aplique el comportamiento de acceso directo predeterminado.

    Deja el SUGGEST_COLUMN_SHORTCUT_ID vacío para cada sugerencia que no vaya a cambiar y se pueda guardar como un acceso directo.

Si ninguna de tus sugerencias cambia, no necesitas la columna SUGGEST_COLUMN_SHORTCUT_ID.

Nota: El cuadro de búsqueda rápida decide si crear o no un acceso directo para una sugerencia. Para ello, considera esos valores como una solicitud sólida de la aplicación; no hay garantía de que el comportamiento que solicitaste para los accesos directos de sugerencias vaya a proporcionarse.

Acerca de la clasificación de sugerencias del cuadro de búsqueda rápida

Una vez que las sugerencias de búsqueda de la aplicación están disponibles para el cuadro de búsqueda rápida, la clasificación del cuadro de búsqueda rápida determina cómo se muestran las sugerencias al usuario para una consulta en particular. Esto podría depender de cuántas otras aplicaciones tengan resultados para esa consulta y con qué frecuencia el usuario haya seleccionado tus resultados en comparación con los de otras apps. No hay garantía de cómo se clasifican tus sugerencias ni de que las sugerencias de tu app se muestren para una consulta determinada. En general, puedes esperar que proporcionar resultados de calidad aumente la probabilidad de que las sugerencias de la app se presenten en una posición destacada y que las apps que brindan sugerencias de baja calidad tengan más probabilidades de tener una clasificación inferior o no mostrarse.

Consulta la app de muestra del diccionario de búsqueda para obtener una demostración completa de las sugerencias de búsqueda personalizadas.