TV uygulamalarını aranabilir hale getirme

Android TV, Android arama arayüzünü kullanır yüklü uygulamalardan içerik verilerini almak ve arama sonuçlarını kullanıcıya yayınlamak için kullanılır. Uygulamanızın içerik verileri, kullanıcının içeriğe anında erişmesini sağlamak için bu sonuçlara dahil edilebilir en iyi şekilde yararlanabilirsiniz.

Uygulamanız, Android TV'ye Android TV'nin önerilen aramayı oluşturabileceği veri alanlarını sağlamalıdır sonuçları gösterilir. Bunu yapmak için uygulamanızın İçerik sunan İçerik Sağlayıcı bir searchable.xml yapılandırma dosyası, içeriği açıklayan sağlayıcı ve Android TV için diğer önemli bilgileri sağlar. Ayrıca kullanıcı önerilen bir arama sonucunu seçtiğinde tetiklenen amaç Örneğin, daha fazla bilgi için Ekle özel arama önerileri. Bu kılavuzda, Android TV uygulamalarına özgü ana noktalar ele alınmaktadır.

Bu kılavuzu okumadan önce, şurada açıklanan kavramları bildiğinizden emin olun: Search API'si kılavuzu. Ayrıca, Arama işlevi ekleme makalesini inceleyin.

Bu kılavuzdaki örnek kod, Leanback örnek uygulaması ,

Sütunları tanımlama

SearchManager, beklediği veri alanlarını sütunlarının arasında yer alır. Verilerinizin biçiminden bağımsız olarak, veri alanlarınızı bu sütunlar genellikle içerik verilerinize erişen sınıfta yer alır. Uygulama geliştirme hakkında ihtiyaç duyulan alanlarla eşleyen bir sınıf oluşturmak için Öneri tablosu oluşturma.

SearchManager sınıfı, Android TV için birkaç sütun içerir. Bazı daha önemli sütunlar aşağıdaki tabloda açıklanmıştır.

Değer Açıklama
SUGGEST_COLUMN_TEXT_1 İçeriğinizin adı (zorunlu)
SUGGEST_COLUMN_TEXT_2 İçeriğinizin metin açıklaması
SUGGEST_COLUMN_RESULT_CARD_IMAGE İçeriğiniz için bir resim, poster veya kapak
SUGGEST_COLUMN_CONTENT_TYPE Medyanızın MIME türü
SUGGEST_COLUMN_VIDEO_WIDTH Medyanızın çözünürlük genişliği
SUGGEST_COLUMN_VIDEO_HEIGHT Medyanızın çözünürlük yüksekliği
SUGGEST_COLUMN_PRODUCTION_YEAR İçeriğinizin üretim yılı (zorunlu)
SUGGEST_COLUMN_DURATION Medyanızın milisaniye cinsinden süresi (gerekli)

Arama çerçevesi için aşağıdaki sütunlar gereklidir:

İçeriğinize ait bu sütunların değerleri, diğer sütunlardaki aynı içeriğin değerleriyle eşleştiğinde tarafından bulunan sağlayıcılardan birinde bulunduğunda sistem, Ayrıntılarda uygulamanızın derin bağlantısını paylaşın diğer sağlayıcıların uygulamalarına giden bağlantılarla birlikte içeriği görüntüleyin. Bu konu Ayrıntılar ekranındaki uygulamanızın derin bağlantısı bölümüne gidin.

Uygulamanızın veritabanı sınıfı, sütunları şu şekilde tanımlayabilir:

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

SearchManager sütunlarından veri alanlarınıza haritayı oluşturduğunuzda her satıra benzersiz bir kimlik vermek için _ID öğesi de belirtilmelidir.

Kotlin

companion object {
    ....
    private fun buildColumnMap(): MapS<tring, 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;
  }
...

Yukarıdaki örnekte, SUGGEST_COLUMN_INTENT_DATA_ID girin. Bu, URI'nın bu verideki verilere özgü içeriğe işaret eden kısmıdır satır: içeriğin nerede depolandığını açıklayan URI'nın son bölümü. URI'nın ilk kısmı, tüm satırlar için ortak olduğunda, searchable.xml dosyasını android:searchSuggestIntentData özelliğini, Arama önerilerini işleme bölümü.

URI'nın ilk bölümü, bu değeri SUGGEST_COLUMN_INTENT_DATA alanıyla eşleyin. Kullanıcı bu içeriği seçtiğinde etkinleşen intent, SUGGEST_COLUMN_INTENT_DATA_ID kombinasyonu ve android:searchSuggestIntentData ya da SUGGEST_COLUMN_INTENT_DATA alan değeri.

Arama önerisi verileri sağlama

Bir İçerik Sağlayıcı'yı uygulama tuşuna basarak Android TV arama iletişim kutusuna arama terimi önerileri alabilirsiniz. Sistem, içeriğinizi sorgular her seferinde query() yöntemini çağırarak öneriler için harf yazılır. query() uygulamanızda, içeriğiniz sağlayıcı öneri verilerinizi arar veCursor öneriler için belirlediğiniz satırlar.

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

Manifest dosyanızda, içerik sağlayıcıya özel muamelede bulunuluyor. Bir proje yöneticisi etkinlik olarak etiketlenmişse <provider>. İlgili içeriği oluşturmak için kullanılan sağlayıcı, sisteme bu durumu bildirmek için android:authorities özelliğini ekler. alan adı olacaktır. Ayrıca, android:exported özelliğini Android genel aramasının, kendisinden döndürülen sonuçları kullanabilmesi için "true".

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

Arama önerilerini işleme

Uygulamanız bir içermelidir res/xml/searchable.xml dosyasını kullanın.

res/xml/searchable.xml dosyasına şunları ekleyin: android:searchSuggestAuthority özelliğini kullanabilirsiniz. içerik sağlayıcı. Bu, android:authorities <provider> özelliğinin özelliği AndroidManifest.xml dosyanızda öğesi.

Ayrıca bir etiket ekleyin, Bu, uygulamanın adıdır. Sistem arama ayarları numaralandırma sırasında bu etiketi kullanır arama yapabilirsiniz.

searchable.xml dosyası şunları da içermelidir: "android.intent.action.VIEW" değerine sahip android:searchSuggestIntentAction amacına bağlı olarak kullanabilirsiniz. Bu, amaçtan farklıdır arama terimi sağlamayla ilgili işlemler şunlardır: Önerilerde intent işlemini bildirmenin diğer yolları için bkz. intent işlemidir.

Uygulamanız, intent işlemiyle birlikte android:searchSuggestIntentData özelliğini gönderin. Bu, URI'nın bunu gösteren ilk kısmıdır söz konusu öğe için eşleme tablosundaki tüm satırlarda URI'nın ortak bölümünü açıklayan içeriğe içerik. URI'nın her satır için benzersiz olan kısmı SUGGEST_COLUMN_INTENT_DATA_ID alanıyla belirlenir. Sütunları belirleme bölümünde açıklandığı gibi. Öneriler için amaç verilerini beyan etmenin diğer yolları için bkz. Beyan amaç verileri.

android:searchSuggestSelection=" ?" özelliği, iletilen değeri belirtir. query() öğesinin selection parametresi olarak yöntemidir. Soru işareti (?) değeri sorgu metniyle değiştirilir.

Son olarak, android:includeInGlobalSearch özelliği "true" değerine sahiptir. Bir örnekle açıklayalım searchable.xml dosyası:

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

Arama terimlerini işleme

Arama iletişim kutusunda, uygulamanızın sütunlarından birindeki değerle eşleşen bir kelime olduğunda Sütunları belirleme bölümünde açıklandığından, sistem Amaç ACTION_SEARCH. Uygulamanızda bunu işleyen etkinlik intent, değerlerinde belirtilen kelimenin bulunduğu sütunlar için depoyu arar ve bir liste döndürür. içerik öğelerini görebilirsiniz. AndroidManifest.xml dosyanızda, ACTION_SEARCH için nasıl bir etkinlik intent'i seçmeniz gerekir:

...
  <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" />
...

Etkinlik, aynı zamanda searchable.xml dosyası olarak kaydedin. Genel arama iletişim kutusunu kullanmak için manifesto, hangi etkinliğin arama sorgularını alması gerektiğini açıklamalıdır. Manifest dosyası ayrıca <provider> öğesi, tam olarak searchable.xml dosyasında açıklandığı gibi olmalıdır.

Ayrıntılar ekranında uygulamanıza derin bağlantı oluşturun

Arama yapılandırmasını Herkese açık kullanıcı adı arama önerileri bölümünü inceledik ve SUGGEST_COLUMN_TEXT_1 öğesini eşledik. SUGGEST_COLUMN_PRODUCTION_YEAR ve Şu şekilde açıklandığı gibi SUGGEST_COLUMN_DURATION alan: Sütunları belirleme bölümü, içeriğinizle ilişkili bir izleme işleminin derin bağlantısı, aşağıdaki işlemler gerçekleştirildiğinde açılan ayrıntılar ekranında görünür. kullanıcı bir arama sonucu seçer:

Ayrıntılar ekranında derin bağlantı

Kullanıcı uygulamanızın bağlantısını seçtiğinde, ayrıntılar ekranında, sistem, ACTION_VIEW işleyen etkinliği başlatır olarak ayarla Şu aralıkta "android.intent.action.VIEW" değerine sahip android:searchSuggestIntentAction: searchable.xml dosyası.

Etkinliğinizi başlatmak için özel amaç da oluşturabilirsiniz. Bu, Leanback örnek uygulaması , Örnek uygulamanın aşağıdaki işlemler için kendi LeanbackDetailsFragment uygulamasını başlattığını unutmayın: Seçilen medyanın ayrıntılarını gösterir; medya içeriklerini oynatan etkinliği başlatın, kullanıcının bir veya iki tıklama daha kaydetmesi için hemen harekete geçin.

Arama davranışı

Arama, Android TV'de ana ekrandan ve uygulamanızın içinden kullanılabilir. Arama sonuçları birbirinden farklıdır.

Ana ekrandan arama yapın

Kullanıcı ana ekrandan arama yaptığında varlık kartında ilk sonuç görünür. Varsa içeriği oynatabilen uygulamaların bağlantısı kartın altında her birinin bağlantısı görünür:

TV Arama Sonucunu Oynatma

Varlık kartına programlı bir şekilde uygulama yerleştiremezsiniz. Bir seçeneğini kullanmak isterseniz, uygulamanın arama sonuçları uygulamanın başlığı, yılı yardımcı olur.

Kartın altında daha fazla arama sonucu bulabilirsiniz. Bunları görmek için kullanıcı ekranın uzaktan kumanda edin ve aşağı kaydırın. Her uygulamaya ait sonuçlar ayrı bir satırda gösterilir. Bu seçeneği, satır sıralaması. Şu uygulamayı destekleyen uygulamalar: izleme işlemleri ilk sırada listelenir.

TV Arama Sonuçları

Uygulamanızdan arama

Kullanıcı uzaktan kumandadan mikrofonu başlatarak veya uygulamanın içinden de arama başlatabilir. oyun kumandası. Arama sonuçları, uygulama içeriğinin üzerinde tek bir satırda görüntülenir. Uygulamanız, arama sonuçlarını kendi genel arama sağlayıcısını kullanarak oluşturur.

TV Uygulama İçi Arama Sonuçları

Daha fazla bilgi

TV uygulamasında arama yapma hakkında daha fazla bilgi edinmek için şu makaleyi okuyun: Android arama özelliklerini uygulamanıza entegre edin ve Arama işlevi ekleyin.

SearchFragment ile uygulama içi arama deneyimini özelleştirme hakkında daha fazla bilgi için şu makaleyi okuyun: TV uygulamalarında arama yapma.