맞춤 검색 추천 추가

Android 검색 대화상자 또는 검색 위젯에서 최근 검색어를 기반으로 추천 검색어를 제공할 수 있습니다. 예를 들어 사용자가 '강아지'를 쿼리하는 경우 같은 쿼리를 다시 입력하면 쿼리가 추천 검색어로 표시됩니다. 그림 1은 최근 쿼리 추천이 있는 검색 대화상자의 예를 보여줍니다.

시작하기 전에 애플리케이션에서 기본 검색을 위한 검색 대화상자나 검색 위젯을 구현합니다. 자세한 방법은 검색 인터페이스 만들기를 참고하세요.

기본사항

그림 1. 최근 쿼리 추천이 표시된 검색 대화상자의 스크린샷

최근 추천 검색어는 저장된 검색어입니다. 사용자가 추천 검색어를 선택하면 검색 가능 활동이 이미 처리 중인 추천 검색어가 포함된 ACTION_SEARCH 인텐트를 수신합니다.

최근 추천 검색어를 제공하려면 다음을 따라야 합니다.

  • 검색 가능 활동을 구현합니다.
  • SearchRecentSuggestionsProvider를 확장하는 콘텐츠 제공자를 만들어 애플리케이션 매니페스트에서 선언합니다.
  • 추천 검색어를 제공하는 콘텐츠 제공자에 관한 정보로 검색 가능한 구성을 수정합니다.
  • 검색이 실행될 때마다 콘텐츠 제공자에 쿼리를 저장합니다.

Android 시스템은 검색 대화상자를 표시하는 것처럼 대화상자 또는 검색 위젯 아래에 추천 검색어를 표시합니다. 시스템에서 추천을 가져오는 소스를 제공해야 합니다.

시스템에서 활동이 검색 가능한 것으로 식별하고 추천 검색어를 제공하면 사용자가 쿼리를 입력할 때 다음 상황이 발생합니다.

  1. 시스템은 검색어 텍스트(사용자가 입력을 시작하는 모든 내용)를 가져와 추천 검색어가 포함된 콘텐츠 제공자에 쿼리를 실행합니다.
  2. 콘텐츠 제공자가 검색어 텍스트와 일치하는 모든 추천 검색어를 가리키는 Cursor를 반환합니다.
  3. 시스템은 Cursor에서 제공하는 추천 목록을 표시합니다.

최근 추천 검색어가 표시되면 다음과 같은 결과가 발생할 수 있습니다.

  • 사용자가 다른 키를 입력하거나 어떤 식으로든 쿼리를 변경하면 이전 단계가 반복되고 추천 검색어 목록이 업데이트됩니다.
  • 사용자가 검색을 실행하면 추천 검색어가 무시되고 검색이 일반 ACTION_SEARCH 인텐트를 사용하여 검색 가능 활동에 전달됩니다.
  • 사용자가 추천 검색어를 선택하면 추천된 텍스트를 쿼리로 사용하여 ACTION_SEARCH 인텐트가 검색 활동에 전달됩니다.

콘텐츠 제공자를 위해 확장하는 SearchRecentSuggestionsProvider 클래스가 이전 단계의 작업을 자동으로 실행하므로 작성할 코드가 거의 없습니다.

콘텐츠 제공자 만들기

최근 쿼리 추천에 필요한 콘텐츠 제공자는 SearchRecentSuggestionsProvider의 구현입니다. 이 클래스에서 모든 작업을 처리합니다. 코드 한 줄을 실행하는 클래스 생성자를 작성하기만 하면 됩니다.

예를 들어 다음은 최근 쿼리 추천을 위한 콘텐츠 제공자의 전체 구현입니다.

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

setupSuggestions() 호출은 검색 권한 및 데이터베이스 모드의 이름을 전달합니다. 검색 권한은 모든 고유한 문자열일 수 있지만 콘텐츠 제공자의 정규화된 이름을 사용하는 것이 좋습니다. 예를 들어 패키지 이름 뒤에 제공자의 클래스 이름이 나오는 것을 예로 들 수 있습니다. 예: "com.example.MySuggestionProvider"

데이터베이스 모드는 DATABASE_MODE_QUERIES를 포함해야 하며 개발자가 각 추천과 함께 두 번째 텍스트 줄을 제공할 수 있도록 추천 검색어 표에 열을 추가하는 DATABASE_MODE_2LINES를 선택적으로 포함할 수 있습니다. 각 추천에 두 줄을 제공하려면 다음 예를 참고하세요.

Kotlin

const val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES

Java

public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;

SearchRecentSuggestionsProvider 클래스와 검색 가능한 구성에 사용된 것과 동일한 권한 문자열을 사용하여 애플리케이션 매니페스트에서 콘텐츠 제공자를 선언합니다. 예를 들면 다음과 같습니다.

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

검색 가능한 구성 수정하기

추천 제공자를 사용하도록 시스템을 구성하려면 검색 가능한 구성 파일의 <searchable> 요소에 android:searchSuggestAuthority 속성과 android:searchSuggestSelection 속성을 추가합니다. 예를 들면 다음과 같습니다.

<?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() 메서드 중에 쿼리를 저장하는 방법은 다음과 같습니다.

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

SearchRecentSuggestionsProvider 생성자에는 콘텐츠 제공자가 선언한 동일한 권한과 데이터베이스 모드가 필요합니다.

saveRecentQuery() 메서드는 검색어 문자열을 첫 번째 매개변수로 사용하고, 선택적으로 두 번째 문자열을 추천 검색어 또는 null로 포함할 두 번째 문자열을 사용합니다. 두 번째 매개변수는 DATABASE_MODE_2LINES로 추천 검색어에 두 줄 모드를 사용 설정한 경우에만 사용됩니다. 두 줄 모드를 사용 설정하면 시스템에서 일치하는 추천을 찾을 때 쿼리 텍스트가 두 번째 줄과 일치합니다.

추천 데이터 삭제

사용자의 개인 정보를 보호하려면 항상 사용자가 최근 쿼리 추천을 지울 수 있는 방법을 제공해야 합니다. 쿼리 기록을 지우려면 clearHistory()를 호출합니다. 예:

Kotlin

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

Java

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

'검색 기록 지우기' 메뉴 항목, 환경설정 항목 또는 버튼에서 이 작업을 실행합니다. 사용자가 검색 기록을 삭제하기를 원하는지 확인하는 확인 대화상자를 제공합니다.