탐색 가능한 검색결과 표시

모든 앱은 음성 검색을 지원해야 합니다. 이 페이지에서는 음성 없이 검색을 시작하도록 지원하고 사용자가 다른 결과를 선택할 수 있도록 검색 결과 목록을 표시하여 검색 환경을 더욱 개선하는 방법을 설명합니다. 예를 들어 추천 결과가 가장 관련성이 없는 경우입니다.

미디어 앱은 Android Auto 및 Android Automotive OS (AAOS)에서 컨텍스트 검색 결과를 제공할 수 있습니다. 이러한 결과는 사용자가 검색어를 시작하거나 가장 최근 검색 결과를 볼 때 표시됩니다.

이러한 검색 결과를 사용 설정하고 제공하려면 다음 단계를 따르세요.

  • 서비스의 onGetRoot 메서드에서 검색 지원을 선언합니다.

  • 미디어 브라우저 서비스에서 onSearch 메서드를 재정의하여 사용자 검색어를 처리합니다.

  • 제목 항목을 사용하여 검색 결과를 정리하여 탐색 가능성을 개선합니다.

앱은 검색어가 시작될 때 표시되는 문맥 검색 결과를 제공할 수 있습니다. Android Auto 및 AAOS에서는 이러한 결과를 검색어 인터페이스나 이전에 한 검색어에 기반한 어포던스를 통해 표시합니다. 자세한 내용은 음성 작업 지원을 참고하세요.

사용자의 음성 검색과 관련된 미디어 항목을 볼 수 있는 **Google 검색 결과** 옵션이 포함된 재생 뷰

그림 1. 사용자의 음성 검색과 관련된 미디어 항목을 볼 수 있는 Google 검색 결과 옵션이 포함된 재생 뷰

앱이 검색 결과 표시를 지원한다고 나타내려면 서비스의 onGetRoot 메서드에서 반환된 추가 번들에 상수 키 BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED를 포함하여 불리언 true에 매핑합니다.

Kotlin

import androidx.media.utils.MediaConstants

@Nullable
override fun onGetRoot(
    @NonNull clientPackageName: String,
    clientUid: Int,
    @Nullable rootHints: Bundle
): BrowserRoot {
    val extras = Bundle()
    extras.putBoolean(
        MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true)
    return BrowserRoot(ROOT_ID, extras)
}

자바

import androidx.media.utils.MediaConstants;

@Nullable
@Override
public BrowserRoot onGetRoot(
    @NonNull String clientPackageName,
    int clientUid,
    @Nullable Bundle rootHints) {
    Bundle extras = new Bundle();
    extras.putBoolean(
        MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true);
    return new BrowserRoot(ROOT_ID, extras);
}

검색 결과를 제공하려면 미디어 브라우저 서비스에서 onSearch 메서드를 재정의하세요. Android Auto 및 AAOS는 사용자가 검색어 인터페이스나 검색 결과 어포던스를 호출할 때 사용자의 검색어를 이 메서드로 전달합니다.

제목 항목을 사용하면 검색 결과를 더 쉽게 탐색할 수 있습니다. 예를 들어 앱에서 음악을 재생하는 경우 앨범, 아티스트, 노래를 기준으로 검색 결과를 구성할 수 있습니다. 이 코드 스니펫은 onSearch 메서드의 구현을 보여줍니다.

Kotlin

fun onSearch(query: String, extras: Bundle) {
  // Detach from results to unblock the caller (if a search is expensive).
  result.detach()
  object:AsyncTask() {
    internal var searchResponse:ArrayList
    internal var succeeded = false
    protected fun doInBackground(vararg params:Void):Void {
      searchResponse = ArrayList()
      if (doSearch(query, extras, searchResponse))
      {
        succeeded = true
      }
      return null
    }
    protected fun onPostExecute(param:Void) {
      if (succeeded)
      {
        // Sending an empty List informs the caller that there were no results.
        result.sendResult(searchResponse)
      }
      else
      {
        // This invokes onError() on the search callback.
        result.sendResult(null)
      }
      return null
    }
  }.execute()
}
// Populates resultsToFill with search results. Returns true on success or false on error.
private fun doSearch(
    query: String,
    extras: Bundle,
    resultsToFill: ArrayList
): Boolean {
  // Implement this method.
}

Java

@Override
public void onSearch(final String query, final Bundle extras,
                        Result<List<MediaItem>> result) {

  // Detach from results to unblock the caller (if a search is expensive).
  result.detach();

  new AsyncTask<Void, Void, Void>() {
    List>MediaItem> searchResponse;
    boolean succeeded = false;
    @Override
    protected Void doInBackground(Void... params) {
      searchResponse = new ArrayList&lt;MediaItem>();
      if (doSearch(query, extras, searchResponse)) {
        succeeded = true;
      }
      return null;
    }

    @Override
    protected void onPostExecute(Void param) {
      if (succeeded) {
       // Sending an empty List informs the caller that there were no results.
       result.sendResult(searchResponse);
      } else {
        // This invokes onError() on the search callback.
        result.sendResult(null);
      }
    }
  }.execute()
}

/** Populates resultsToFill with search results. Returns true on success or false on error. */
private boolean doSearch(String query, Bundle extras, ArrayList&lt;MediaItem> resultsToFill) {
    // Implement this method.
}