모든 앱은 음성 검색을 지원해야 합니다. 이 페이지에서는 음성 없이 검색을 시작하도록 지원하고 사용자가 다른 결과를 선택할 수 있도록 검색 결과 목록을 표시하여 검색 환경을 더욱 개선하는 방법을 설명합니다. 예를 들어 추천 결과가 가장 관련성이 없는 경우입니다.
미디어 앱은 Android Auto 및 Android Automotive OS (AAOS)에서 컨텍스트 검색 결과를 제공할 수 있습니다. 이러한 결과는 사용자가 검색어를 시작하거나 가장 최근 검색 결과를 볼 때 표시됩니다.
이러한 검색 결과를 사용 설정하고 제공하려면 다음 단계를 따르세요.
서비스의
onGetRoot
메서드에서 검색 지원을 선언합니다.미디어 브라우저 서비스에서
onSearch
메서드를 재정의하여 사용자 검색어를 처리합니다.제목 항목을 사용하여 검색 결과를 정리하여 탐색 가능성을 개선합니다.
앱은 검색어가 시작될 때 표시되는 문맥 검색 결과를 제공할 수 있습니다. Android Auto 및 AAOS에서는 이러한 결과를 검색어 인터페이스나 이전에 한 검색어에 기반한 어포던스를 통해 표시합니다. 자세한 내용은 음성 작업 지원을 참고하세요.
그림 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<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<MediaItem> resultsToFill) {
// Implement this method.
}