Добавить предложения пользовательского поиска

Вы можете предоставлять поисковые предложения на основе недавних поисковых запросов в диалоговом окне поиска Android или виджете поиска. Например, если пользователь запрашивает «щенки», этот запрос отображается в виде предложения, когда он снова вводит тот же запрос. На рис. 1 показан пример диалогового окна поиска с предложениями последних запросов.

Прежде чем начать, реализуйте в своем приложении диалоговое окно поиска или виджет поиска для базового поиска. Подробную информацию см. в разделе Создание интерфейса поиска .

Основы

Рисунок 1. Снимок экрана диалогового окна поиска с предложениями последних запросов.

Недавние предложения запросов — это сохраненные поисковые запросы. Когда пользователь выбирает предложение, ваша активность поиска получает намерение ACTION_SEARCH с предложением в качестве поискового запроса, который уже обрабатывается вашей активностью поиска.

Чтобы предоставить предложения по последним запросам, вам необходимо:

  • Реализуйте поисковую деятельность.
  • Создайте поставщика контента, расширяющего SearchRecentSuggestionsProvider , и объявите его в манифесте приложения.
  • Измените конфигурацию с возможностью поиска, указав информацию о поставщике контента, который предоставляет предложения по поиску.
  • Сохраняйте запросы своему поставщику контента каждый раз, когда выполняется поиск.

Точно так же, как система Android отображает диалоговое окно поиска, она отображает предложения поиска под диалоговым окном или виджетом поиска. Вы указываете источник, из которого система получает предложения.

Когда система определяет, что ваши действия доступны для поиска, и предлагает варианты поиска, когда пользователь вводит запрос, происходит следующее:

  1. Система берет текст поискового запроса — независимо от того, что пользователь начинает вводить — и выполняет запрос поставщику контента, который содержит ваши предложения.
  2. Ваш поставщик контента возвращает Cursor , указывающий на все предложения, соответствующие тексту поискового запроса.
  3. Система отображает список предложений, предоставленных Cursor .

После отображения последних предложений запроса может произойти следующее:

  • Если пользователь вводит другой ключ или каким-либо образом меняет запрос, предыдущие шаги повторяются, а список предложений обновляется.
  • Если пользователь выполняет поиск, предложения игнорируются, и поиск передается в вашу активность поиска с использованием обычного намерения ACTION_SEARCH .
  • Если пользователь выбирает предложение, намерение ACTION_SEARCH доставляется в вашу активность поиска с использованием предложенного текста в качестве запроса.

Класс SearchRecentSuggestionsProvider , который вы расширяете для своего поставщика контента, автоматически выполняет работу, описанную в предыдущих шагах, поэтому кода для написания мало.

Создайте поставщика контента

Поставщик контента, который вам нужен для последних предложений по запросам, является реализацией SearchRecentSuggestionsProvider . Этот класс сделает все за вас. Вам просто нужно написать конструктор класса, который выполняет одну строку кода.

Например, вот полная реализация поставщика контента для последних предложений по запросам:

Котлин

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

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

Ява

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

При вызове setupSuggestions() передается имя органа поиска и режим базы данных. Центром поиска может быть любая уникальная строка, но лучше всего использовать полное имя поставщика контента, например имя пакета, за которым следует имя класса поставщика. Например, "com.example.MySuggestionProvider" .

Режим базы данных должен включать DATABASE_MODE_QUERIES и дополнительно может включать DATABASE_MODE_2LINES , который добавляет столбец в таблицу предложений, чтобы вы могли предоставить вторую строку текста для каждого предложения. Если вы хотите предоставить две строки в каждом предложении, см. следующий пример:

Котлин

const val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES

Ява

public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;

Объявите поставщика контента в манифесте приложения с той же строкой полномочий, которая используется в вашем классе SearchRecentSuggestionsProvider и в конфигурации с возможностью поиска. Например:

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

Измените конфигурацию поиска

Чтобы настроить систему на использование поставщика предложений, добавьте атрибуты android:searchSuggestAuthority и android:searchSuggestSelection к элементу <searchable> в файле конфигурации с возможностью поиска. Например:

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

Значением android:searchSuggestAuthority должно быть полное имя вашего поставщика контента, которое точно соответствует полномочиям, используемым в поставщике контента, например "com.example.MySuggestionProvider" в предыдущих примерах.

Значением android:searchSuggestSelection должен быть один вопросительный знак, которому предшествует пробел: " ?" . Это заполнитель для аргумента выбора SQLite, который автоматически заменяется текстом запроса, введенным пользователем.

Сохранить запросы

Чтобы пополнить коллекцию недавних запросов, добавьте каждый запрос, полученный в результате вашей активности поиска, в свой SearchRecentSuggestionsProvider . Для этого создайте экземпляр SearchRecentSuggestions и вызывайте saveRecentQuery() каждый раз, когда ваша активность поиска получает запрос. Например, вот как вы можете сохранить запрос во время метода onCreate() вашей активности:

Котлин

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

Ява

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

Конструктору SearchRecentSuggestionsProvider требуются те же права доступа и режим базы данных, которые объявлены вашим поставщиком контента.

Метод saveRecentQuery() принимает строку поискового запроса в качестве первого параметра и, при необходимости, вторую строку для включения в качестве второй строки предложения или значения null. Второй параметр используется только в том случае, если вы включаете двухстрочный режим для поисковых предложений с помощью DATABASE_MODE_2LINES . Если вы включите двухстрочный режим, то текст запроса будет сопоставляться со второй строкой, когда система ищет подходящие предложения.

Очистить данные предложений

Чтобы защитить конфиденциальность пользователя, всегда предоставляйте пользователю возможность удалить последние предложения по запросам. Чтобы очистить историю запросов, вызовитеcleHistory clearHistory() . Например:

Котлин

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

Ява

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

Выполните это, выбрав пункт меню «Очистить историю поиска», элемент предпочтений или кнопку. Предоставьте диалоговое окно подтверждения, чтобы убедиться, что пользователь хочет удалить свою историю поиска.