Como adicionar sugestões recentes de consulta

Ao usar a caixa de diálogo de pesquisa ou o widget de pesquisa do Android, você pode oferecer sugestões de pesquisa com base nas consultas recentes. Por exemplo, se um usuário já pesquisou "filhotes", essa consulta aparecerá como uma sugestão quando ele começar a digitar a mesma consulta. A Figura 1 mostra um exemplo de uma caixa de diálogo de pesquisa com sugestões de consultas recentes.

Antes de começar, é necessário implementar a caixa de diálogo ou um widget de pesquisa para pesquisas básicas no seu app. Caso não tenha feito isso, consulte Como criar uma interface de pesquisa.

Noções básicas

Figura 1. Captura de tela de uma caixa de diálogo de pesquisa com sugestões de consulta recentes.

Sugestões de consulta recentes são apenas pesquisas salvas. Quando o usuário seleciona uma das sugestões, sua atividade de pesquisa recebe um intent ACTION_SEARCH com a sugestão como uma consulta, que é processada por sua atividade de pesquisa. Isso é explicado em Como criar uma interface de pesquisa.

Para fornecer sugestões de consultas recentes, você precisa:

  • implementar uma atividade de pesquisa, conforme descrito em Como criar uma interface de pesquisa;
  • criar um provedor de conteúdo que estenda SearchRecentSuggestionsProvider e declará-lo no manifesto do app;
  • modificar a configuração pesquisável com informações sobre o provedor de conteúdo que fornece sugestões de pesquisa;
  • salvar consultas no seu provedor de conteúdo sempre que uma pesquisa é realizada.

Além de exibir a caixa de diálogo de pesquisa, o Android também mostra as sugestões de pesquisa abaixo da caixa de diálogo ou do widget de pesquisa. Você só precisa fornecer uma fonte de onde o sistema possa recuperar sugestões.

Quando o sistema identifica que sua atividade é pesquisável e fornece sugestões de pesquisa, o procedimento a seguir ocorre assim que o usuário começa a digitar uma consulta.

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

Depois que as sugestões de consulta recentes são exibidas, pode ocorrer o seguinte:

  • Se o usuário digitar outra tecla ou mudar a consulta de alguma forma, as etapas mencionadas anteriormente serão repetidas, e a lista de sugestões será atualizada.
  • 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 de ACTION_SEARCH será entregue à sua atividade de pesquisa usando o texto sugerido como a consulta.

A classe SearchRecentSuggestionsProvider que você estende para seu provedor de conteúdo faz o trabalho descrito acima automaticamente. Portanto, há pouco código a criar.

Como criar um provedor de conteúdo

O provedor de conteúdo necessário para sugestões de consulta recentes é uma implementação de SearchRecentSuggestionsProvider. Essa classe faz praticamente tudo para você. Você só precisa criar um construtor de classe que execute uma linha de código.

Veja um exemplo de implementação completa de um provedor de conteúdo para sugestões de consulta recentes:

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

A chamada para setupSuggestions() transmite o nome da autoridade de pesquisa e um modo de banco de dados. A autoridade de pesquisa pode ser qualquer string única, mas a prática recomendada é usar um nome totalmente qualificado para seu provedor de conteúdo (nome do pacote seguido pelo nome da classe do provedor, por exemplo: com.example.MySuggestionProvider). O modo de banco de dados precisa incluir DATABASE_MODE_QUERIES e, opcionalmente, DATABASE_MODE_2LINES, que adiciona outra coluna à tabela de sugestões que permite fornecer uma segunda linha de texto com cada sugestão. Por exemplo, se você quiser fornecer duas linhas em cada sugestão:

Kotlin

    const val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES
    

Java

    public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;
    

Em seguida, declare o provedor de conteúdo no manifesto do app com a mesma string de autoridade usada na classe SearchRecentSuggestionsProvider (e na configuração pesquisável). Exemplo:

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

Como modificar a configuração pesquisável

Para configurar o sistema para usar seu provedor de sugestões, é necessário adicionar os atributos android:searchSuggestAuthority e android:searchSuggestSelection ao elemento <searchable> no 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.MySuggestionProvider"
        android:searchSuggestSelection=" ?" >
    </searchable>
    

O valor de android:searchSuggestAuthority precisa ser um nome totalmente qualificado para seu provedor de conteúdo que corresponda exatamente à autoridade usada no provedor de conteúdo (a string AUTHORITY no exemplo acima).

O valor de android:searchSuggestSelection precisa ser um único ponto de interrogação, precedido por um espaço (" ?"), que é simplesmente um marcador para o argumento de seleção SQLite (que é substituído automaticamente pelo texto de consulta inserido pelo usuário).

Como salvar consultas

Para preencher sua coleção de consultas recentes, adicione cada consulta recebida pela atividade de pesquisa ao seu SearchRecentSuggestionsProvider. Para fazer isso, crie uma instância de SearchRecentSuggestions e chame saveRecentQuery() sempre que sua atividade de pesquisa receber uma consulta. Por exemplo, veja como salvar a consulta durante o método onCreate() da atividade:

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

O construtor SearchRecentSuggestionsProvider exige a mesma autoridade e o mesmo modo de banco de dados declarado pelo provedor de conteúdo.

O método saveRecentQuery() usa a string de consulta de pesquisa como o primeiro parâmetro e, opcionalmente, uma segunda string para incluir como a segunda linha da sugestão (ou nula). O segundo parâmetro será usado somente se o modo de duas linhas estiver ativado para as sugestões de pesquisa com DATABASE_MODE_2LINES. Caso você tenha ativado o modo de duas linhas, o texto da consulta também corresponderá a essa segunda linha quando o sistema procurar sugestões correspondentes.

Como limpar os dados de sugestões

Para proteger a privacidade do usuário, sempre forneça uma forma de limpar as sugestões de consulta recentes. Para limpar o histórico de consultas, chame clearHistory(). Exemplo:

Kotlin

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

Java

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

Você pode executar esse procedimento a partir do item de menu, do item de preferência ou botão "Limpar histórico de pesquisa". Você também precisa fornecer uma caixa de diálogo de confirmação para verificar se o usuário quer excluir o histórico de pesquisa.