显示可浏览的搜索结果

所有应用都必须支持语音搜索。本页介绍了如何通过支持在没有语音的情况下发起搜索以及显示搜索结果列表来进一步提升搜索体验,以便用户可以选择其他结果。例如,如果建议的结果不是最相关的结果。

您的媒体应用可以在 Android Auto 和 Android Automotive OS (AAOS) 中提供情境搜索结果。当用户发起搜索查询或查看最近一次搜索的结果时,系统会显示这些结果。

如需启用并提供这些搜索结果,请执行以下操作:

  • 在服务的 onGetRoot 方法中声明搜索支持。

  • 替换媒体浏览器服务中的 onSearch 方法,以处理用户搜索字词。

  • 使用标题项整理搜索结果,以提高浏览体验。

您的应用可以提供在用户开始搜索查询时显示的上下文搜索结果。Android Auto 和 AAOS 将通过搜索查询接口或通过基于之前进行的查询的功能显示这些结果。如需了解详情,请参阅支持语音操作

一个播放视图,包含 **搜索结果** 选项,用于查看与用户的语音搜索相关的媒体项

图 1. 一个播放视图,包含搜索结果选项,用于查看与用户的语音搜索相关的媒体项。

如需表明您的应用支持显示搜索结果,请在您服务的 onGetRoot 方法返回的 extra 包中添加常量键 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)
}

Java

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