Como adicionar sugestões personalizadas

Ao usar a caixa ou o widget de pesquisa do Android, você pode fornecer sugestões personalizadas que são criadas a partir de dados no app. Por exemplo, se o app for um dicionário, você poderá sugerir palavras do dicionário que correspondam ao texto inserido até então. Essas são as sugestões mais valiosas, porque é possível prever com eficiência o que o usuário quer e fornecer acesso instantâneo a isso. A Figura 1 mostra um exemplo de uma caixa de pesquisa com sugestões personalizadas.

Depois de fornecer sugestões personalizadas, você também pode disponibilizá-las para a caixa de pesquisa rápida do sistema, oferecendo acesso ao seu conteúdo a partir de áreas fora do app.

Antes de começar este guia para adicionar sugestões personalizadas, é necessário ter implementado a caixa ou o widget de pesquisa do Android para pesquisas no seu app. Caso não tenha feito isso, consulte Como criar uma interface de pesquisa. Consulte também a documentação dos Provedores de conteúdo.

Noções básicas

Figura 1. Captura de tela de uma caixa de pesquisa com sugestões de pesquisa personalizadas.

Quando o usuário seleciona uma sugestão personalizada, o sistema Android envia um Intent à sua atividade de pesquisa. Como uma consulta de pesquisa normal envia um intent com a ação ACTION_SEARCH, você pode definir suas sugestões personalizadas para usar ACTION_VIEW (ou qualquer outra ação de intent), além de incluir dados relevantes para a sugestão selecionada. Ainda segundo o exemplo do dicionário, quando o usuário seleciona uma sugestão, seu app pode abrir imediatamente a definição da palavra, em vez de pesquisar correspondências no dicionário.

Para fornecer sugestões personalizadas, faça o seguinte:

  • Implemente uma atividade de pesquisa básica, conforme descrito em Como criar uma interface de pesquisa.
  • Modifique a configuração pesquisável com informações sobre o provedor de conteúdo que oferece sugestões personalizadas.
  • Crie uma tabela (como em SQLiteDatabase) para suas sugestões e formate-a com as colunas obrigatórias.
  • Crie um Provedor de conteúdo com acesso à sua tabela de sugestões e declare-o no seu manifesto.
  • Declare o tipo de Intent a ser enviado quando o usuário selecionar uma sugestão (incluindo uma ação personalizada e dados personalizados).

Além de exibir a caixa de pesquisa, o Android também mostra suas sugestões de pesquisa. Você só precisa de um provedor de conteúdo de onde o sistema possa recuperar suas sugestões. Se você não sabe como criar provedores de conteúdo, leia o guia do desenvolvedor Provedores de conteúdo antes de continuar.

Quando o sistema identifica que sua atividade é pesquisável e fornece sugestões de pesquisa, o procedimento a seguir ocorre quando o usuário digita uma consulta:

  1. O sistema usa o texto da consulta (digitado até então) para consultar o provedor de conteúdo que processa suas sugestões.
  2. Seu provedor de conteúdo retorna um Cursor que aponta para todas as sugestões que são relevantes para o texto da consulta de pesquisa.
  3. O sistema exibe a lista de sugestões fornecidas pelo cursor.

Depois que as sugestões personalizadas são exibidas, pode ocorrer o seguinte:

  • Se o usuário digitar outra tecla ou mudar a consulta de alguma forma, as etapas acima serão repetidas, e a lista de sugestões será atualizada conforme apropriado.
  • Se o usuário executar a pesquisa, as sugestões serão ignoradas, e a pesquisa será entregue à sua atividade pesquisável usando o intent ACTION_SEARCH normal.
  • Se o usuário selecionar uma sugestão, um intent será enviado à sua atividade de pesquisa, com uma ação personalizada e dados personalizados, para que o app possa abrir o conteúdo sugerido.

Como modificar a configuração pesquisável

Para adicionar compatibilidade com sugestões personalizadas, adicione o atributo android:searchSuggestAuthority ao elemento <searchable> no seu arquivo de configuração pesquisável. Exemplo:

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

Você pode precisar de alguns outros atributos, dependendo do tipo de intent que você anexa a cada sugestão e de como pretende formatar consultas para seu provedor de conteúdo. Os outros atributos opcionais são discutidos nas seções a seguir.

Como criar um provedor de conteúdo

Criar um provedor de conteúdo para sugestões personalizadas exige conhecimento prévio sobre provedores de conteúdo, que é abordado no guia do desenvolvedor Provedores de conteúdo. Na maior parte, um provedor de conteúdo para sugestões personalizadas é igual a qualquer outro provedor de conteúdo. No entanto, para cada sugestão oferecida, a respectiva linha no Cursor precisa incluir colunas específicas que o sistema entenda e use para formatar as sugestões.

Quando o usuário começa a digitar na caixa ou no widget de pesquisa, o sistema consulta seu provedor de conteúdo para buscar sugestões, chamando query() cada vez que uma letra é digitada. Na implementação de query(), seu provedor de conteúdo precisa pesquisar seus dados de sugestão e retornar um Cursor que aponte para as linhas que você definiu como boas sugestões.

Detalhes sobre a criação de um provedor de conteúdo para sugestões personalizadas são discutidos nestas duas seções:

Como processar a consulta de sugestões
Como o sistema envia solicitações para seu provedor de conteúdo e como processá-las
Como criar uma tabela de sugestões
Como definir as colunas que o sistema espera em Cursor, retornadas com cada consulta

Como processar a consulta de sugestões

Quando o sistema solicita sugestões do seu provedor de conteúdo, ele chama o método query() do provedor de conteúdo. É necessário implementar esse método para pesquisar seus dados de sugestão e retornar um Cursor que aponte para as sugestões consideradas relevantes.

Este é um resumo dos parâmetros que o sistema transmite para o método query() (listado em ordem):

uri
Sempre um Uri de conteúdo, formatado como:
    content://your.authority/optional.suggest.path/SUGGEST_URI_PATH_QUERY
    

O comportamento padrão para o sistema é transmitir esse URI e anexá-lo ao texto da consulta. Exemplo:

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

O texto da consulta no final é codificado usando regras de codificação de URI. Por isso, talvez seja necessário decodificá-lo antes de realizar uma pesquisa.

A parte optional.suggest.path só será incluída no URI se esse caminho tiver sido definido no arquivo de configuração pesquisável com o atributo android:searchSuggestPath. Isso só será necessário se você usar o mesmo provedor de conteúdo para várias atividades de pesquisa. Nesse caso, será necessário diferenciar a origem da consulta de sugestão.

Observação:SUGGEST_URI_PATH_QUERY não é a string literal fornecida no URI, mas uma constante a ser usada caso você precise se referir a esse caminho.

projection
Sempre nulo
selection
Valor fornecido no atributo android:searchSuggestSelection do seu arquivo de configuração pesquisável ou nulo caso você não tenha declarado o atributo android:searchSuggestSelection. Saiba mais sobre como usar isso para conseguir a consulta abaixo.
selectionArgs
Contém a consulta de pesquisa como o primeiro (e único) elemento da matriz se você declarou o atributo android:searchSuggestSelection na configuração pesquisável. Caso você não tenha declarado android:searchSuggestSelection, esse parâmetro será nulo. Saiba mais sobre como usar isso para conseguir a consulta abaixo.
sortOrder
Sempre nulo

O sistema pode enviar o texto da consulta de pesquisa de duas maneiras. A maneira padrão é incluir o texto da consulta como o último caminho do URI de conteúdo transmitido no parâmetro uri. No entanto, se você incluir um valor de seleção no atributo android:searchSuggestSelection da sua configuração pesquisável, o texto da consulta será transmitido como o primeiro elemento da matriz de strings selectionArgs. As duas opções estão resumidas a seguir.

Conseguir a consulta no URI

Por padrão, a consulta é anexada como o último segmento do parâmetro uri (um objeto Uri). Para recuperar o texto da consulta nesse caso, basta usar getLastPathSegment(). Exemplo:

Kotlin

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

Java

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

Isso retorna o último segmento do Uri, que é o texto de consulta inserido pelo usuário.

Conseguir a consulta nos argumentos de seleção

Em vez de usar o URI, você pode preferir que seu método query() receba tudo o que ele precisa para realizar a pesquisa e que os parâmetros selection e selectionArgs carreguem os valores adequados. Nesse caso, adicione o atributo android:searchSuggestSelection à sua configuração pesquisável com sua string de seleção SQLite. Na string de seleção, inclua um ponto de interrogação ("?") como marcador para a consulta de pesquisa. O sistema chama query() com a string de seleção como o parâmetro selection e a consulta de pesquisa como o primeiro elemento na matriz selectionArgs.

Por exemplo, veja como você pode formar o atributo android:searchSuggestSelection para criar uma afirmação de pesquisa de 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>
    

Com essa configuração, seu método query() entrega o parâmetro selection como "word MATCH ?" e o parâmetro selectionArgs como a consulta de pesquisa. Quando esses parâmetros são transmitidos para um método query() SQLite, como seus respectivos argumentos, eles são sintetizados juntos (o ponto de interrogação é substituído pelo texto da consulta). Se você optar por receber consultas de sugestão dessa maneira e precisar adicionar caracteres curingas ao texto da consulta, anexe-os (e/ou use-os como prefixo) ao parâmetro selectionArgs, porque esse valor é colocado entre aspas e inserido no lugar do ponto de interrogação.

Outro novo atributo no exemplo acima é android:searchSuggestIntentAction, que define a ação de intent enviada com cada intent quando o usuário seleciona uma sugestão. Ele é mais discutido na seção sobre Como declarar um intent para sugestões.

Dica: se você não quiser definir uma cláusula de seleção no atributo android:searchSuggestSelection, mas ainda quiser receber o texto da consulta no parâmetro selectionArgs, forneça um valor não nulo para o atributo android:searchSuggestSelection. Isso aciona a consulta a ser transmitida em selectionArgs, e você pode ignorar o parâmetro selection. Dessa forma, você pode definir a cláusula de seleção real em um nível inferior para que o provedor de conteúdo não precise processá-la.

Como criar uma tabela de sugestões

Quando você retorna sugestões para o sistema com um Cursor, ele espera colunas específicas em cada linha. Portanto, independentemente de você decidir armazenar seus dados de sugestão em um banco de dados SQLite no dispositivo, um banco de dados em um servidor da Web ou outro formato no dispositivo ou na Web, é necessário formatar as sugestões como linhas em uma tabela e apresentá-las com um Cursor.

Observação: se suas sugestões de pesquisa não estiverem armazenadas em um formato de tabela (como uma tabela SQLite) usando as colunas exigidas pelo sistema, pesquise os dados de sugestões para buscar correspondências e formate-as na tabela necessária para cada solicitação. Para fazer isso, crie um MatrixCursor usando os nomes de coluna exigidos e, em seguida, adicione uma linha para cada sugestão usando addRow(Object[]). Retorne o produto final do método query() do seu provedor de conteúdo.

O sistema entende várias colunas, mas só duas são obrigatórias:

_ID
Um ID único de linha de números inteiros para cada sugestão. O sistema exige isso para apresentar sugestões em uma ListView.
SUGGEST_COLUMN_TEXT_1
A string que é apresentada como uma sugestão.

As colunas a seguir são todas opcionais; a maioria delas é discutida nas próximas seções:

SUGGEST_COLUMN_TEXT_2
Uma string. Se o cursor incluir essa coluna, todas as sugestões serão fornecidas em um formato de duas linhas. A string nessa coluna é exibida como uma segunda linha menor de texto, abaixo do texto de sugestão principal. Ela pode ser nula ou vazia para indicar que não há texto secundário.
SUGGEST_COLUMN_ICON_1
Uma string de recurso drawable, de conteúdo ou de URI de arquivo. Se o cursor incluir essa coluna, todas as sugestões serão fornecidas em um formato de ícone mais texto, com o ícone do drawable ao lado esquerdo. Ela pode ser nula ou zero para indicar que não há ícone nessa linha.
SUGGEST_COLUMN_ICON_2
Uma string de recurso drawable, de conteúdo ou de URI de arquivo. Se o cursor incluir essa coluna, todas as sugestões serão fornecidas em um formato de ícone mais texto, com o ícone ao lado direito. Ela pode ser nula ou zero para indicar que não há ícone nessa linha.
SUGGEST_COLUMN_INTENT_ACTION
Uma string de ação de intent. Se essa coluna existir e incluir um valor na linha especificada, a ação definida aqui será usada ao formar o intent da sugestão. Se o elemento não for fornecido, a ação será extraída do campo android:searchSuggestIntentAction na sua configuração pesquisável. Se sua ação for a mesma para todas as sugestões, é mais eficiente especificar a ação usando android:searchSuggestIntentAction e omitir essa coluna.
SUGGEST_COLUMN_INTENT_DATA
String de URI de dados. Se essa coluna existir e incluir um valor na linha especificada, esses serão os dados usados ao formar o intent da sugestão. Se o elemento não for fornecido, os dados serão extraídos do campo android:searchSuggestIntentData na sua configuração pesquisável. Se nenhuma das origens for fornecida, o campo de dados do intent será nulo. Se os dados forem os mesmos para todas as sugestões ou puderem ser descritos usando uma parte constante e um ID específico, será mais eficiente especificá-los usando android:searchSuggestIntentData e omitir essa coluna.
SUGGEST_COLUMN_INTENT_DATA_ID
String de caminho de URI. Se essa coluna existir e incluir um valor na linha especificada, "/" e esse valor serão anexados ao campo de dados no intent. Isso só poderá ser usado se o campo de dados especificado pelo atributo android:searchSuggestIntentData na configuração pesquisável já tiver sido definido como uma string base adequada.
SUGGEST_COLUMN_INTENT_EXTRA_DATA
Dados arbitrários. Se essa coluna existir e incluir um valor em uma determinada linha, esses serão os dados extras usados ao formar o intent da sugestão. Se não for fornecido, o campo de dados extra do intent será nulo. Essa coluna permite que as sugestões forneçam dados complementares incluídos como um extra na chave EXTRA_DATA_KEY do intent.
SUGGEST_COLUMN_QUERY
Se essa coluna existir e esse elemento existir na linha especificada, esses serão os dados usados ao formar a consulta da sugestão, incluídos como um extra na chave QUERY do intent. Obrigatória se a ação da sugestão é ACTION_SEARCH, caso contrário, é opcional.
SUGGEST_COLUMN_SHORTCUT_ID
Só é usada ao fornecer sugestões para a Caixa de pesquisa rápida. Essa coluna indica se uma sugestão de pesquisa deve ser armazenada como um atalho e se ela deve ser validada. Os atalhos geralmente são formados quando o usuário clica em uma sugestão da caixa de pesquisa rápida. Se estiver faltando, o resultado será armazenado como um atalho e nunca será atualizado. Se definida como SUGGEST_NEVER_MAKE_SHORTCUT, o resultado não será armazenado como um atalho. Caso contrário, o ID do atalho será usado para verificar se há uma sugestão atualizada usando SUGGEST_URI_PATH_SHORTCUT.
SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING
Só é usada ao fornecer sugestões para a caixa de pesquisa rápida. Essa coluna especifica que um ícone de carregamento será exibido, em vez de um ícone de SUGGEST_COLUMN_ICON_2, enquanto o atalho dessa sugestão estiver sendo atualizado na Caixa de pesquisa rápida.

Algumas dessas colunas são discutidas em mais detalhes nas seções a seguir.

Como declarar um intent de sugestões

Quando o usuário seleciona uma sugestão na lista exibida abaixo da caixa ou do widget de pesquisa, o sistema envia um Intent personalizado à sua atividade de pesquisa. É necessário definir a ação e os dados para o intent.

Como declarar a ação de intent

A ação de intent mais comum para uma sugestão personalizada é ACTION_VIEW, que é adequada quando você quer abrir algo, como a definição de uma palavra, as informações de contato de uma pessoa ou uma página da Web. No entanto, a ação de intent pode ser qualquer outra ação e pode até ser diferente para cada sugestão.

Dependendo se você quer ou não que todas as sugestões usem a mesma ação de intent, é possível definir a ação de duas maneiras:

  1. Use o atributo android:searchSuggestIntentAction do seu arquivo de configuração pesquisável para definir a ação para todas as sugestões.

    Exemplo:

        <?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. Use a coluna SUGGEST_COLUMN_INTENT_ACTION para definir a ação para sugestões individuais.

    Adicione a coluna SUGGEST_COLUMN_INTENT_ACTION à tabela de sugestões e, em cada sugestão, coloque a ação a ser usada (por exemplo, "android.intent.action.VIEW").

Você também pode combinar essas duas técnicas. Por exemplo, é possível incluir o atributo android:searchSuggestIntentAction com uma ação a ser usada com todas as sugestões por padrão e, em seguida, substituir essa ação por algumas sugestões declarando uma ação diferente na coluna SUGGEST_COLUMN_INTENT_ACTION. Se você não incluir um valor na coluna SUGGEST_COLUMN_INTENT_ACTION, será usado o intent fornecido no atributo android:searchSuggestIntentAction.

Observação: se você não incluir o atributo android:searchSuggestIntentAction na sua configuração pesquisável, será necessário incluir um valor na coluna SUGGEST_COLUMN_INTENT_ACTION para cada sugestão; caso contrário, o intent falhará.

Como declarar dados de intent

Quando o usuário seleciona uma sugestão, sua atividade de pesquisa recebe o intent com a ação definida (conforme discutido na seção anterior). Contudo, o intent também precisa transportar dados para identificar qual sugestão foi selecionada. Especificamente, os dados precisam ser algo exclusivo para cada sugestão, como o ID da linha da sugestão na tabela SQLite. Quando o intent for recebido, você poderá recuperar os dados anexados com getData() ou getDataString().

É possível definir os dados incluídos no intent de duas maneiras:

  1. Defina os dados para cada sugestão dentro da coluna SUGGEST_COLUMN_INTENT_DATA da sua tabela de sugestões.

    Forneça todas as informações de dados necessárias para cada intent na tabela de sugestões incluindo a coluna SUGGEST_COLUMN_INTENT_DATA e preenchendo-a com dados exclusivos para cada linha. Os dados dessa coluna são anexados ao intent exatamente conforme definido nessa coluna. É possível recuperá-los com getData() ou getDataString().

    Dica: geralmente é mais fácil usar o ID da linha da tabela como os dados do intent, porque ele é sempre exclusivo. Adicionalmente, a maneira mais fácil de fazer isso é usando o nome da coluna SUGGEST_COLUMN_INTENT_DATA como um alias para a coluna de IDs de linhas. Consulte o app de amostra Searchable Dictionary para ver um exemplo em que SQLiteQueryBuilder cria um mapa de projeção de nomes de coluna para aliases.

  2. Fragmente um URI de dados em duas partes: a parte comum a todas as sugestões e a parte exclusiva de cada sugestão. Coloque essas partes no atributo android:searchSuggestintentData da configuração pesquisável e na coluna SUGGEST_COLUMN_INTENT_DATA_ID da sua tabela de sugestões, respectivamente.

    Declare a parte do URI que é comum a todas as sugestões no atributo android:searchSuggestIntentData da sua configuração pesquisável. Exemplo:

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

    Em seguida, inclua o caminho final de cada sugestão (a parte exclusiva) na coluna SUGGEST_COLUMN_INTENT_DATA_ID da sua tabela de sugestões. Quando o usuário seleciona uma sugestão, o sistema toma a string de android:searchSuggestIntentData, anexa uma barra ("/") e, em seguida, adiciona o respectivo valor da coluna SUGGEST_COLUMN_INTENT_DATA_ID para formar um URI de conteúdo completo. Então, você pode recuperar Uri com getData().

Adicionar mais dados

Se você precisar expressar ainda mais informações com seu intent, adicione outra coluna da tabela, SUGGEST_COLUMN_INTENT_EXTRA_DATA, que pode armazenar informações complementares sobre a sugestão. Os dados salvos nessa coluna são colocados em EXTRA_DATA_KEY do pacote extra do intent.

Como processar o intent

Agora que você fornece sugestões de pesquisa personalizadas com intents personalizados, você precisa da sua atividade de pesquisa para processar esses intents quando o usuário seleciona uma sugestão. É necessário também processar o intent ACTION_SEARCH, o que já é feito pela atividade de pesquisa. Veja um exemplo de como é possível processar os intents durante o callback onCreate() da sua atividade:

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

Nesse exemplo, a ação de intent é ACTION_VIEW, e os dados transportam um URI completo que aponta para o item sugerido, como sintetizado pela string android:searchSuggestIntentData e coluna SUGGEST_COLUMN_INTENT_DATA_ID. O URI é então transferido para o método showResult() local, que consulta o provedor de conteúdo para buscar o item especificado pelo URI.

Observação: não é necessário adicionar um filtro de intent ao arquivo de manifesto do Android para a ação de intent definida com o atributo android:searchSuggestIntentAction ou a coluna SUGGEST_COLUMN_INTENT_ACTION. O sistema abre sua atividade de pesquisa por nome para exibir o intent da sugestão. Portanto, a atividade não precisa declarar a ação aceita.

Como reescrever o texto da consulta

Se o usuário navegar pela lista de sugestões usando os controles direcionais (como um trackball ou botão direcional), por padrão, o texto da consulta não será atualizado. No entanto, é possível reescrever temporariamente o texto de consulta do usuário conforme ele aparece na caixa de texto com uma consulta que corresponde à sugestão em foco no momento. Isso permite que o usuário veja qual consulta está sendo sugerida (se adequada) e, em seguida, selecione a caixa de pesquisa e edite a consulta antes de enviá-la como uma pesquisa.

Você pode reescrever o texto da consulta das seguintes maneiras:

  1. Adicione o atributo android:searchMode à sua configuração pesquisável com o valor "queryRewriteFromText". Nesse caso, o conteúdo da coluna SUGGEST_COLUMN_TEXT_1 da sugestão é usado para reescrever o texto da consulta.
  2. Adicione o atributo android:searchMode à sua configuração pesquisável com o valor "queryRewriteFromData". Nesse caso, o conteúdo da coluna SUGGEST_COLUMN_INTENT_DATA da sugestão é usado para reescrever o texto da consulta. Isso é usado somente com URIs ou outros formatos de dados que sejam visíveis ao usuário, como URLs HTTP. Esquemas URI internos não podem ser usados para reescrever a consulta dessa maneira.
  3. Forneça uma string de texto de consulta única na coluna SUGGEST_COLUMN_QUERY da sua tabela de sugestões. Se essa coluna estiver presente e contiver um valor para a sugestão atual, ela será usada para reescrever o texto da consulta e substituir qualquer uma das implementações anteriores.

Como expor sugestões de pesquisa para a caixa de pesquisa rápida

Depois de configurar seu app para fornecer sugestões de pesquisa personalizadas, disponibilizá-las para a caixa de pesquisa rápida acessível globalmente é tão fácil quanto modificar sua configuração pesquisável para incluir android:includeInGlobalSearch como "true".

O único cenário mais trabalhoso é quando seu provedor de conteúdo exige uma permissão de leitura. Nesse caso, é necessário adicionar um elemento <path-permission> especial ao provedor para conceder acesso de leitura da caixa de pesquisa rápida ao seu provedor de conteúdo. Exemplo:

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

Nesse exemplo, o provedor restringe o acesso de leitura e gravação ao conteúdo. O elemento <path-permission> corrige a restrição concedendo acesso de leitura ao conteúdo dentro do prefixo de caminho "/search_suggest_query" quando a permissão "android.permission.GLOBAL_SEARCH" existe. Isso concede acesso à Caixa de pesquisa rápida para que seja possível consultar sugestões do seu provedor de conteúdo.

Se o provedor de conteúdo não impõe permissões de leitura, por padrão, a caixa de pesquisa rápida tem permissão de leitura.

Como ativar sugestões em um dispositivo

Quando seu app está configurado para fornecer sugestões na Caixa de pesquisa rápida, ele não está realmente ativado para fornecer sugestões na caixa de pesquisa rápida por padrão. É o usuário que decide se quer incluir sugestões do seu app na caixa de pesquisa rápida. Para ativar as sugestões de pesquisa do app, o usuário precisa abrir "Itens pesquisáveis" (em "Configurações" > "Pesquisa") e ativar o app como um item pesquisável.

Cada app disponível para a caixa de pesquisa rápida tem uma entrada na página de configurações dos itens pesquisáveis. A entrada inclui o nome do app e uma breve descrição do conteúdo que pode ser pesquisado no app e disponibilizado para sugestões na caixa de pesquisa rápida. Para definir o texto da descrição do seu app pesquisável, adicione o atributo android:searchSettingsDescription à sua configuração pesquisável. Exemplo:

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

A string de android:searchSettingsDescription precisa ser o mais concisa possível e indicar o conteúdo pesquisável. Por exemplo, "Artistas, álbuns e faixas" para um app de música ou "Notas salvas" para um app de bloco de notas. Fornecer essa descrição é importante para que o usuário saiba que tipo de sugestões é fornecido. Sempre inclua esse atributo quando android:includeInGlobalSearch for "true".

Lembre-se de que o usuário precisa visitar o menu de configurações para ativar as sugestões de pesquisa do seu app antes que elas apareçam na caixa de pesquisa rápida. Desse modo, se a pesquisa for um aspecto importante do seu app, convém considerar uma forma de transmitir isso aos usuários. Você pode exibir uma observação na primeira vez que o app for iniciado, instruindo como ativar as sugestões de pesquisa para a caixa de pesquisa rápida.

Como gerenciar atalhos de sugestões da caixa de pesquisa rápida

Sugestões que o usuário seleciona na caixa de pesquisa rápida podem ser transformadas automaticamente em atalhos. Essas são as sugestões que o sistema copiou do seu provedor de conteúdo para poder acessar rapidamente a sugestão sem precisar consultar novamente o provedor de conteúdo.

Por padrão, isso é ativado para todas as sugestões recuperadas pela caixa de pesquisa rápida, mas se os dados de sugestões forem alterados com o tempo, você poderá solicitar que os atalhos sejam atualizados. Por exemplo, se suas sugestões se referem a dados dinâmicos, como o status de presença de um contato, solicite que os atalhos de sugestão sejam atualizados quando exibidos ao usuário. Para isso, inclua SUGGEST_COLUMN_SHORTCUT_ID na tabela de sugestões. Usando essa coluna, é possível configurar o comportamento de atalho para cada sugestão, de uma das seguintes maneiras:

  1. Peça à Caixa de pesquisa rápida que consulte novamente seu provedor de conteúdo para conseguir uma nova versão do atalho de sugestão.

    Forneça um valor na coluna SUGGEST_COLUMN_SHORTCUT_ID e a sugestão será consultada novamente para buscar uma nova versão sempre que o atalho for exibido. O atalho é exibido rapidamente com os dados disponíveis mais recentemente até que a consulta de atualização retorne. Nesse momento, a sugestão é atualizada com as novas informações. A consulta de atualização é enviada para seu provedor de conteúdo com um caminho de URI de SUGGEST_URI_PATH_SHORTCUT, em vez de SUGGEST_URI_PATH_QUERY.

    Os Cursor retornados precisam conter uma sugestão usando as mesmas colunas da sugestão original ou estar vazios, indicando que o atalho não é mais válido. Nesse caso, a sugestão desaparece e o atalho é removido.

    Se uma sugestão referenciar dados que podem levar mais tempo para serem atualizados, como uma atualização com base na rede, também é possível adicionar a coluna SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING às sugestões com o valor "true" para exibir um ícone de carregamento de progresso do ícone do lado direito até que a atualização seja concluída. Qualquer valor diferente de "true" não mostra o ícone de carregamento de progresso.

  2. Impeça que a sugestão seja copiada em um atalho.

    Forneça um valor de SUGGEST_NEVER_MAKE_SHORTCUT na coluna SUGGEST_COLUMN_SHORTCUT_ID. Nesse caso, a sugestão nunca é copiada em um atalho. Isso só será necessário se você realmente não quiser que a sugestão copiada anteriormente apareça. Lembre-se de que, se você fornecer um valor normal para a coluna, o atalho de sugestão aparecerá somente até que a consulta de atualização retorne.

  3. Permita que o comportamento de atalho padrão seja aplicado.

    Deixe SUGGEST_COLUMN_SHORTCUT_ID em branco para cada sugestão que não será alterada e que pode ser salva como um atalho.

Se nenhuma das duas sugestões mudar, você não precisará da coluna SUGGEST_COLUMN_SHORTCUT_ID.

Observação: a caixa de pesquisa rápida decide se cria ou não um atalho para uma sugestão, considerando esses valores como uma forte solicitação do seu app. Não há garantia de que o comportamento solicitado para seus atalhos de sugestão será honrado.

Sobre a classificação de sugestões da caixa de pesquisa rápida

Depois de disponibilizar as sugestões de pesquisa do app para a caixa de pesquisa rápida, a classificação da caixa de pesquisa rápida determinará como as sugestões serão exibidas ao usuário para uma consulta específica. Isso pode depender de quantos outros apps têm resultados para essa consulta e com que frequência o usuário selecionou seus resultados em comparação com os de outros apps. Não existe nenhuma garantia sobre a forma como suas sugestões serão classificadas ou se as sugestões do seu app serão exibidas para uma determinada consulta. Em geral, fornecer resultados de qualidade aumenta a probabilidade de que as sugestões do seu app sejam fornecidas em uma posição de destaque. Apps que fornecem sugestões de baixa qualidade são mais propensos a ter uma classificação inferior ou a não exibi-la.

Consulte o app de amostra do Searchable Dictionary para ver uma demonstração completa das sugestões de pesquisa personalizadas.