Tăng khả năng tìm kiếm được ứng dụng trên TV

Android TV sử dụng giao diện tìm kiếm của Android để truy xuất dữ liệu nội dung từ các ứng dụng đã cài đặt và cung cấp kết quả tìm kiếm cho người dùng. Bạn có thể đưa dữ liệu nội dung của ứng dụng vào các kết quả này để cho phép người dùng truy cập tức thì vào nội dung trong ứng dụng.

Ứng dụng của bạn phải cung cấp cho Android TV các trường dữ liệu mà từ đó Android TV có thể tạo kết quả tìm kiếm đề xuất khi người dùng nhập các ký tự vào hộp thoại tìm kiếm. Để làm được điều đó, ứng dụng của bạn phải triển khai một Trình cung cấp nội dung nhằm đưa ra các đề xuất cùng với tệp cấu hình searchable.xml mô tả trình cung cấp nội dung và các thông tin quan trọng khác cho Android TV. Bạn cũng cần một hoạt động xử lý ý định sẽ kích hoạt khi người dùng chọn kết quả tìm kiếm đề xuất. Để biết thêm thông tin chi tiết, vui lòng xem phần Thêm cụm từ tìm kiếm tuỳ chỉnh được đề xuất. Hướng dẫn này trình bày các điểm chính dành riêng cho ứng dụng Android TV.

Trước khi đọc hướng dẫn này, hãy đảm bảo bạn đã nắm rõ các khái niệm được giải thích trong hướng dẫn về API Tìm kiếm. Ngoài ra, hãy tham khảo bài viết Thêm chức năng tìm kiếm.

Mã mẫu trong hướng dẫn này được lấy từ ứng dụng mẫu Leanback.

Xác định cột

SearchManager mô tả các trường dữ liệu mà nó dự kiến bằng cách biểu thị các trường đó dưới dạng cột của cơ sở dữ liệu cục bộ. Bất kể định dạng dữ liệu là gì, bạn phải liên kết các trường dữ liệu với các cột này, thường là trong lớp truy cập vào dữ liệu nội dung của bạn. Để biết thông tin về cách tạo một lớp ánh xạ dữ liệu hiện có của bạn tới các trường bắt buộc, hãy xem phần Xây dựng bảng đề xuất.

Lớp SearchManager bao gồm một số cột cho Android TV. Một số cột quan trọng hơn được mô tả trong bảng sau.

Giá trị Nội dung mô tả
SUGGEST_COLUMN_TEXT_1 Tên nội dung của bạn (bắt buộc)
SUGGEST_COLUMN_TEXT_2 Phần mô tả bằng văn bản về nội dung của bạn
SUGGEST_COLUMN_RESULT_CARD_IMAGE Hình ảnh, áp phích hoặc bìa cho nội dung của bạn
SUGGEST_COLUMN_CONTENT_TYPE Loại MIME của nội dung đa phương tiện
SUGGEST_COLUMN_VIDEO_WIDTH Chiều rộng độ phân giải của nội dung nghe nhìn
SUGGEST_COLUMN_VIDEO_HEIGHT Chiều cao độ phân giải của nội dung nghe nhìn
SUGGEST_COLUMN_PRODUCTION_YEAR Năm sản xuất nội dung của bạn (bắt buộc)
SUGGEST_COLUMN_DURATION Thời lượng tính bằng mili giây của nội dung nghe nhìn (bắt buộc)

Khung tìm kiếm cần có các cột sau:

Khi giá trị của những cột này cho nội dung của bạn khớp với giá trị của cùng một nội dung từ những nhà cung cấp khác mà máy chủ của Google tìm thấy, hệ thống sẽ cung cấp một đường liên kết sâu đến ứng dụng của bạn trong chế độ xem chi tiết cho nội dung, cùng với các đường liên kết đến ứng dụng của các nhà cung cấp khác. Vấn đề này sẽ được thảo luận thêm trong phần Đường liên kết sâu đến ứng dụng trong màn hình chi tiết.

Lớp cơ sở dữ liệu của ứng dụng có thể xác định các cột như sau:

Kotlin

class VideoDatabase {
    companion object {
        // The columns we'll include in the video database table
        val KEY_NAME = SearchManager.SUGGEST_COLUMN_TEXT_1
        val KEY_DESCRIPTION = SearchManager.SUGGEST_COLUMN_TEXT_2
        val KEY_ICON = SearchManager.SUGGEST_COLUMN_RESULT_CARD_IMAGE
        val KEY_DATA_TYPE = SearchManager.SUGGEST_COLUMN_CONTENT_TYPE
        val KEY_IS_LIVE = SearchManager.SUGGEST_COLUMN_IS_LIVE
        val KEY_VIDEO_WIDTH = SearchManager.SUGGEST_COLUMN_VIDEO_WIDTH
        val KEY_VIDEO_HEIGHT = SearchManager.SUGGEST_COLUMN_VIDEO_HEIGHT
        val KEY_AUDIO_CHANNEL_CONFIG = SearchManager.SUGGEST_COLUMN_AUDIO_CHANNEL_CONFIG
        val KEY_PURCHASE_PRICE = SearchManager.SUGGEST_COLUMN_PURCHASE_PRICE
        val KEY_RENTAL_PRICE = SearchManager.SUGGEST_COLUMN_RENTAL_PRICE
        val KEY_RATING_STYLE = SearchManager.SUGGEST_COLUMN_RATING_STYLE
        val KEY_RATING_SCORE = SearchManager.SUGGEST_COLUMN_RATING_SCORE
        val KEY_PRODUCTION_YEAR = SearchManager.SUGGEST_COLUMN_PRODUCTION_YEAR
        val KEY_COLUMN_DURATION = SearchManager.SUGGEST_COLUMN_DURATION
        val KEY_ACTION = SearchManager.SUGGEST_COLUMN_INTENT_ACTION
        ...
    }
    ...
}

Java

public class VideoDatabase {
    // The columns we'll include in the video database table
    public static final String KEY_NAME = SearchManager.SUGGEST_COLUMN_TEXT_1;
    public static final String KEY_DESCRIPTION = SearchManager.SUGGEST_COLUMN_TEXT_2;
    public static final String KEY_ICON = SearchManager.SUGGEST_COLUMN_RESULT_CARD_IMAGE;
    public static final String KEY_DATA_TYPE = SearchManager.SUGGEST_COLUMN_CONTENT_TYPE;
    public static final String KEY_IS_LIVE = SearchManager.SUGGEST_COLUMN_IS_LIVE;
    public static final String KEY_VIDEO_WIDTH = SearchManager.SUGGEST_COLUMN_VIDEO_WIDTH;
    public static final String KEY_VIDEO_HEIGHT = SearchManager.SUGGEST_COLUMN_VIDEO_HEIGHT;
    public static final String KEY_AUDIO_CHANNEL_CONFIG =
            SearchManager.SUGGEST_COLUMN_AUDIO_CHANNEL_CONFIG;
    public static final String KEY_PURCHASE_PRICE = SearchManager.SUGGEST_COLUMN_PURCHASE_PRICE;
    public static final String KEY_RENTAL_PRICE = SearchManager.SUGGEST_COLUMN_RENTAL_PRICE;
    public static final String KEY_RATING_STYLE = SearchManager.SUGGEST_COLUMN_RATING_STYLE;
    public static final String KEY_RATING_SCORE = SearchManager.SUGGEST_COLUMN_RATING_SCORE;
    public static final String KEY_PRODUCTION_YEAR = SearchManager.SUGGEST_COLUMN_PRODUCTION_YEAR;
    public static final String KEY_COLUMN_DURATION = SearchManager.SUGGEST_COLUMN_DURATION;
    public static final String KEY_ACTION = SearchManager.SUGGEST_COLUMN_INTENT_ACTION;
...

Khi tạo bản đồ từ cột SearchManager đến các trường dữ liệu, bạn cũng phải chỉ định _ID để cung cấp cho mỗi hàng một mã nhận dạng duy nhất.

Kotlin


companion object {
    ....
    private fun buildColumnMap(): Map<String, String> {
        return mapOf(
          KEY_NAME to KEY_NAME,
          KEY_DESCRIPTION to KEY_DESCRIPTION,
          KEY_ICON to KEY_ICON,
          KEY_DATA_TYPE to KEY_DATA_TYPE,
          KEY_IS_LIVE to KEY_IS_LIVE,
          KEY_VIDEO_WIDTH to KEY_VIDEO_WIDTH,
          KEY_VIDEO_HEIGHT to KEY_VIDEO_HEIGHT,
          KEY_AUDIO_CHANNEL_CONFIG to KEY_AUDIO_CHANNEL_CONFIG,
          KEY_PURCHASE_PRICE to KEY_PURCHASE_PRICE,
          KEY_RENTAL_PRICE to KEY_RENTAL_PRICE,
          KEY_RATING_STYLE to KEY_RATING_STYLE,
          KEY_RATING_SCORE to KEY_RATING_SCORE,
          KEY_PRODUCTION_YEAR to KEY_PRODUCTION_YEAR,
          KEY_COLUMN_DURATION to KEY_COLUMN_DURATION,
          KEY_ACTION to KEY_ACTION,
          BaseColumns._ID to ("rowid AS " + BaseColumns._ID),
          SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID to ("rowid AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID),
          SearchManager.SUGGEST_COLUMN_SHORTCUT_ID to ("rowid AS " + SearchManager.SUGGEST_COLUMN_SHORTCUT_ID)
        )
    }
}

Java

...
  private static HashMap<String, String> buildColumnMap() {
    HashMap<String, String> map = new HashMap<String, String>();
    map.put(KEY_NAME, KEY_NAME);
    map.put(KEY_DESCRIPTION, KEY_DESCRIPTION);
    map.put(KEY_ICON, KEY_ICON);
    map.put(KEY_DATA_TYPE, KEY_DATA_TYPE);
    map.put(KEY_IS_LIVE, KEY_IS_LIVE);
    map.put(KEY_VIDEO_WIDTH, KEY_VIDEO_WIDTH);
    map.put(KEY_VIDEO_HEIGHT, KEY_VIDEO_HEIGHT);
    map.put(KEY_AUDIO_CHANNEL_CONFIG, KEY_AUDIO_CHANNEL_CONFIG);
    map.put(KEY_PURCHASE_PRICE, KEY_PURCHASE_PRICE);
    map.put(KEY_RENTAL_PRICE, KEY_RENTAL_PRICE);
    map.put(KEY_RATING_STYLE, KEY_RATING_STYLE);
    map.put(KEY_RATING_SCORE, KEY_RATING_SCORE);
    map.put(KEY_PRODUCTION_YEAR, KEY_PRODUCTION_YEAR);
    map.put(KEY_COLUMN_DURATION, KEY_COLUMN_DURATION);
    map.put(KEY_ACTION, KEY_ACTION);
    map.put(BaseColumns._ID, "rowid AS " +
            BaseColumns._ID);
    map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " +
            SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
    map.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, "rowid AS " +
            SearchManager.SUGGEST_COLUMN_SHORTCUT_ID);
    return map;
  }
...

Trong ví dụ trước, hãy chú ý đến mối liên kết với trường SUGGEST_COLUMN_INTENT_DATA_ID. Đây là phần URI trỏ đến nội dung dành riêng cho dữ liệu trong hàng này – phần cuối cùng của URI, mô tả nơi lưu trữ nội dung. Phần đầu tiên của URI (thường là đối với tất cả các hàng trong bảng) sẽ được đặt trong tệp searchable.xml làm thuộc tính android:searchSuggestIntentData, như mô tả trong phần Xử lý các cụm từ tìm kiếm được đề xuất.

Nếu phần đầu tiên của URI là khác nhau đối với mỗi hàng trong bảng, hãy ánh xạ giá trị đó với trường SUGGEST_COLUMN_INTENT_DATA. Khi người dùng chọn nội dung này, ý định kích hoạt sẽ cung cấp dữ liệu ý định từ tổ hợp SUGGEST_COLUMN_INTENT_DATA_ID và thuộc tính android:searchSuggestIntentData hoặc giá trị trường SUGGEST_COLUMN_INTENT_DATA.

Cung cấp dữ liệu cụm từ tìm kiếm được đề xuất

Triển khai Content Provider để trả về các đề xuất cụm từ tìm kiếm vào hộp thoại tìm kiếm của Android TV. Hệ thống sẽ truy vấn trình cung cấp nội dung của bạn để nhận các đề xuất bằng cách gọi phương thức query() mỗi khi nhập một chữ cái. Trong quá trình triển khai query(), trình cung cấp nội dung của bạn sẽ tìm kiếm dữ liệu đề xuất và trả về Cursor trỏ đến các hàng bạn đã chỉ định cho các đề xuất.

Kotlin

fun query(uri: Uri, projection: Array<String>, selection: String, selectionArgs: Array<String>,
        sortOrder: String): Cursor {
    // Use the UriMatcher to see what kind of query we have and format the db query accordingly
    when (URI_MATCHER.match(uri)) {
        SEARCH_SUGGEST -> {
            Log.d(TAG, "search suggest: ${selectionArgs[0]} URI: $uri")
            if (selectionArgs == null) {
                throw IllegalArgumentException(
                        "selectionArgs must be provided for the Uri: $uri")
            }
            return getSuggestions(selectionArgs[0])
        }
        else -> throw IllegalArgumentException("Unknown Uri: $uri")
    }
}

private fun getSuggestions(query: String): Cursor {
    val columns = arrayOf<String>(
            BaseColumns._ID,
            VideoDatabase.KEY_NAME,
            VideoDatabase.KEY_DESCRIPTION,
            VideoDatabase.KEY_ICON,
            VideoDatabase.KEY_DATA_TYPE,
            VideoDatabase.KEY_IS_LIVE,
            VideoDatabase.KEY_VIDEO_WIDTH,
            VideoDatabase.KEY_VIDEO_HEIGHT,
            VideoDatabase.KEY_AUDIO_CHANNEL_CONFIG,
            VideoDatabase.KEY_PURCHASE_PRICE,
            VideoDatabase.KEY_RENTAL_PRICE,
            VideoDatabase.KEY_RATING_STYLE,
            VideoDatabase.KEY_RATING_SCORE,
            VideoDatabase.KEY_PRODUCTION_YEAR,
            VideoDatabase.KEY_COLUMN_DURATION,
            VideoDatabase.KEY_ACTION,
            SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID
    )
    return videoDatabase.getWordMatch(query.toLowerCase(), columns)
}

Java

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
        String sortOrder) {
    // Use the UriMatcher to see what kind of query we have and format the db query accordingly
    switch (URI_MATCHER.match(uri)) {
        case SEARCH_SUGGEST:
            Log.d(TAG, "search suggest: " + selectionArgs[0] + " URI: " + uri);
            if (selectionArgs == null) {
                throw new IllegalArgumentException(
                        "selectionArgs must be provided for the Uri: " + uri);
            }
            return getSuggestions(selectionArgs[0]);
        default:
            throw new IllegalArgumentException("Unknown Uri: " + uri);
    }
}

private Cursor getSuggestions(String query) {
    query = query.toLowerCase();
    String[] columns = new String[]{
        BaseColumns._ID,
        VideoDatabase.KEY_NAME,
        VideoDatabase.KEY_DESCRIPTION,
        VideoDatabase.KEY_ICON,
        VideoDatabase.KEY_DATA_TYPE,
        VideoDatabase.KEY_IS_LIVE,
        VideoDatabase.KEY_VIDEO_WIDTH,
        VideoDatabase.KEY_VIDEO_HEIGHT,
        VideoDatabase.KEY_AUDIO_CHANNEL_CONFIG,
        VideoDatabase.KEY_PURCHASE_PRICE,
        VideoDatabase.KEY_RENTAL_PRICE,
        VideoDatabase.KEY_RATING_STYLE,
        VideoDatabase.KEY_RATING_SCORE,
        VideoDatabase.KEY_PRODUCTION_YEAR,
        VideoDatabase.KEY_COLUMN_DURATION,
        VideoDatabase.KEY_ACTION,
        SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID
    };
    return videoDatabase.getWordMatch(query, columns);
}
...

Trong tệp kê khai của bạn, nhà cung cấp nội dung được xử lý đặc biệt. Thay vì được gắn thẻ là một hoạt động, nó được mô tả là <provider>. Trình cung cấp này bao gồm thuộc tính android:authorities để cho hệ thống biết không gian tên của trình cung cấp nội dung. Ngoài ra, bạn phải đặt thuộc tính android:exported thành "true" để tính năng tìm kiếm toàn cầu trên Android có thể sử dụng các kết quả được trả về.

<provider android:name="com.example.android.tvleanback.VideoContentProvider"
    android:authorities="com.example.android.tvleanback"
    android:exported="true" />

Xử lý cụm từ tìm kiếm được đề xuất

Ứng dụng của bạn phải bao gồm một tệp res/xml/searchable.xml để định cấu hình chế độ cài đặt cụm từ tìm kiếm được đề xuất.

Trong tệp res/xml/searchable.xml, hãy thêm thuộc tính android:searchSuggestAuthority để cho hệ thống biết không gian tên của trình cung cấp nội dung. Giá trị này phải khớp với giá trị chuỗi mà bạn chỉ định trong thuộc tính android:authorities của phần tử <provider> trong tệp AndroidManifest.xml.

Ngoài ra, hãy bao gồm một nhãn, là tên của ứng dụng. Chế độ cài đặt tìm kiếm trên hệ thống sử dụng nhãn này khi liệt kê các ứng dụng có thể tìm kiếm.

Tệp searchable.xml cũng phải bao gồm android:searchSuggestIntentAction với giá trị "android.intent.action.VIEW" để xác định thao tác theo ý định nhằm cung cấp một đề xuất tuỳ chỉnh. Hành động này khác với thao tác theo ý định để cung cấp cụm từ tìm kiếm, như mô tả trong phần sau. Để biết các cách khác nhằm khai báo thao tác theo ý định cho các đề xuất, hãy xem phần Khai báo thao tác theo ý định.

Cùng với thao tác theo ý định, ứng dụng của bạn phải cung cấp dữ liệu ý định mà bạn chỉ định bằng thuộc tính android:searchSuggestIntentData. Đây là phần đầu tiên của URI trỏ đến nội dung, mô tả phần URI chung cho tất cả các hàng trong bảng liên kết cho nội dung đó. Phần URI dành riêng cho mỗi hàng được thiết lập bằng trường SUGGEST_COLUMN_INTENT_DATA_ID, như mô tả trong phần Xác định cột. Để biết các cách khác nhằm khai báo dữ liệu ý định cho các đề xuất, hãy xem phần Khai báo dữ liệu ý định.

Thuộc tính android:searchSuggestSelection=" ?" chỉ định giá trị được chuyển dưới dạng tham số selection của phương thức query(). Giá trị dấu chấm hỏi (?) được thay thế bằng văn bản truy vấn.

Cuối cùng, bạn cũng phải thêm thuộc tính android:includeInGlobalSearch với giá trị "true". Dưới đây là tệp searchable.xml mẫu:

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/search_label"
    android:hint="@string/search_hint"
    android:searchSettingsDescription="@string/settings_description"
    android:searchSuggestAuthority="com.example.android.tvleanback"
    android:searchSuggestIntentAction="android.intent.action.VIEW"
    android:searchSuggestIntentData="content://com.example.android.tvleanback/video_database_leanback"
    android:searchSuggestSelection=" ?"
    android:searchSuggestThreshold="1"
    android:includeInGlobalSearch="true">
</searchable>

Xử lý cụm từ tìm kiếm

Ngay khi hộp thoại tìm kiếm có từ khớp với giá trị trong một trong các cột của ứng dụng, như mô tả trong phần Xác định cột, hệ thống sẽ kích hoạt ý định ACTION_SEARCH. Hoạt động trong ứng dụng xử lý ý định đó sẽ tìm kiếm các cột có từ đã cho trong giá trị trong kho lưu trữ và trả về danh sách các mục nội dung có các cột đó. Trong tệp AndroidManifest.xml, bạn chỉ định hoạt động xử lý ý định ACTION_SEARCH như trong ví dụ sau:

...
  <activity
      android:name="com.example.android.tvleanback.DetailsActivity"
      android:exported="true">

      <!-- Receives the search request. -->
      <intent-filter>
          <action android:name="android.intent.action.SEARCH" />
          <!-- No category needed, because the Intent will specify this class component -->
      </intent-filter>

      <!-- Points to searchable meta data. -->
      <meta-data android:name="android.app.searchable"
          android:resource="@xml/searchable" />
  </activity>
...
  <!-- Provides search suggestions for keywords against video meta data. -->
  <provider android:name="com.example.android.tvleanback.VideoContentProvider"
      android:authorities="com.example.android.tvleanback"
      android:exported="true" />
...

Hoạt động cũng phải mô tả cấu hình có thể tìm kiếm bằng cách tham chiếu đến tệp searchable.xml. Để sử dụng hộp thoại tìm kiếm chung, tệp kê khai phải mô tả hoạt động nào sẽ nhận được cụm từ tìm kiếm. Tệp kê khai cũng phải mô tả phần tử <provider> , đúng như mô tả trong tệp searchable.xml.

Đường liên kết sâu đến ứng dụng của bạn trong màn hình chi tiết

Nếu bạn đã thiết lập cấu hình tìm kiếm như mô tả trong phần Xử lý các cụm từ tìm kiếm được đề xuất và liên kết các trường SUGGEST_COLUMN_TEXT_1, SUGGEST_COLUMN_PRODUCTION_YEARSUGGEST_COLUMN_DURATION như mô tả trong phần Xác định cột, thì đường liên kết sâu đến một thao tác xem dành cho nội dung của bạn sẽ xuất hiện trên màn hình chi tiết sẽ chạy khi người dùng chọn một kết quả tìm kiếm:

Đường liên kết sâu trong màn hình chi tiết

Khi người dùng chọn đường liên kết cho ứng dụng của bạn, được xác định bằng nút **Có sẵn** trên màn hình chi tiết, hệ thống sẽ khởi chạy hoạt động xử lý ACTION_VIEW được đặt là android:searchSuggestIntentAction với giá trị "android.intent.action.VIEW" trong tệp searchable.xml.

Bạn cũng có thể thiết lập một đối tượng có ý định tuỳ chỉnh để chạy hoạt động của mình. Điều này được minh hoạ trong ứng dụng mẫu Leanback. Xin lưu ý rằng ứng dụng mẫu sẽ chạy LeanbackDetailsFragment riêng để hiển thị thông tin chi tiết về nội dung nghe nhìn đã chọn; trong các ứng dụng của bạn, hãy khởi chạy ngay hoạt động phát nội dung nghe nhìn để lưu người dùng thêm một hoặc hai lần nhấp.

Hành vi tìm kiếm

Tính năng tìm kiếm sẽ xuất hiện trên Android TV từ màn hình chính và từ bên trong ứng dụng. Kết quả tìm kiếm trong 2 trường hợp này là khác nhau.

Tìm kiếm từ màn hình chính

Khi người dùng tìm kiếm từ màn hình chính, kết quả đầu tiên sẽ xuất hiện trong thẻ thực thể. Nếu có ứng dụng có thể phát nội dung đó, thì một đường liên kết đến từng ứng dụng sẽ xuất hiện ở cuối thẻ:

Phát lại kết quả tìm kiếm TV

Bạn không thể lập trình để đặt ứng dụng vào thẻ thực thể. Để được đưa vào dưới dạng tuỳ chọn phát, kết quả tìm kiếm của ứng dụng phải khớp với tiêu đề, năm và thời lượng của nội dung được tìm kiếm.

Bạn có thể xem thêm kết quả tìm kiếm bên dưới thẻ này. Để xem các biểu tượng này, người dùng phải nhấn và giữ điều khiển từ xa rồi cuộn xuống. Kết quả cho mỗi ứng dụng sẽ xuất hiện trong một hàng riêng. Bạn không thể kiểm soát thứ tự hàng. Những ứng dụng hỗ trợ hành động trên đồng hồ được liệt kê trước.

Kết quả tìm kiếm trên TV

Tìm kiếm trong ứng dụng của bạn

Người dùng cũng có thể bắt đầu tìm kiếm từ trong ứng dụng của bạn bằng cách khởi động micrô từ điều khiển từ xa hoặc tay điều khiển trò chơi. Kết quả tìm kiếm được hiển thị trong một hàng ở đầu nội dung của ứng dụng. Ứng dụng của bạn tạo kết quả tìm kiếm bằng cách sử dụng nhà cung cấp dịch vụ tìm kiếm toàn cầu riêng của ứng dụng.

Kết quả tìm kiếm trong ứng dụng trên TV

Tìm hiểu thêm

Để tìm hiểu thêm về cách tìm kiếm trong ứng dụng dành cho TV, hãy đọc bài viết Tích hợp tính năng tìm kiếm của Android vào ứng dụngThêm chức năng tìm kiếm.

Để biết thêm thông tin về cách tuỳ chỉnh trải nghiệm tìm kiếm trong ứng dụng bằng SearchFragment, hãy đọc bài viết Tìm kiếm trong ứng dụng TV.