Kanały na ekranie głównym

Ekran główny Androida TV (lub po prostu ekran główny) ma interfejs, który umożliwia wyświetla polecane treści w formie tabeli kanałów i programów. Każdy wiersz to kanał. Kanał zawiera karty wszystkich programów dostępnych na tym kanale:

Ekran główny telewizora

Ten dokument pokazuje, jak dodawać kanały i programy do ekranu głównego, aktualizować treści, wykonywać działania użytkowników i zapewniać im najlepsze wrażenia. (Jeśli chcesz dokładniej poznać interfejs API, wypróbuj ćwiczenia z programowania na ekranie głównym i obejrzyj sesję I/O na Androidzie TV).

Uwaga: kanały rekomendacji są dostępne tylko w tych krajach: Android 8.0 (poziom interfejsu API 26) i nowsze. Należy ich używać do przesyłania zalecenia dotyczące aplikacji działających w Androidzie 8.0 (poziom interfejsu API 26) i nowszych. Do zalecenia dotyczące aplikacji działających na starszych wersjach Androida, musi użyć funkcji wiersz rekomendacji .

Interfejs ekranu głównego

Aplikacje mogą tworzyć nowe kanały, dodawać, usuwać i aktualizować programy na kanale oraz kontrolować ich kolejność. Na przykład aplikacja może utworzyć kanał o nazwie „Co nowego”. i wyświetlać karty nowych programów.

Aplikacje nie mogą kontrolować kolejności, w jakiej kanały pojawiają się na ekranie głównym. Gdy Twoja aplikacja utworzy nowy kanał, na ekranie głównym będzie się on pojawiać u dołu listy kanałów. Użytkownik może zmieniać kolejność, ukrywać i pokazywać kanały.

Kanał Warte obejrzenia

Kanał Warte obejrzenia to drugi rząd na ekranie głównym, w wierszu aplikacji. System tworzy i utrzymuje ten kanał. Aplikacja może dodawać na kanale Warte obejrzenia. Więcej informacji znajdziesz w artykule Dodawanie programów do kanał „Warte obejrzenia”.

Kanały aplikacji

Kanały tworzone przez aplikację podlegają temu cyklowi życia:

  1. Użytkownik znajduje kanał w Twojej aplikacji i prosi o dodanie go do ekranu głównego.
  2. Aplikacja utworzy kanał i doda go do TvProvider (w tym momencie kanał nie jest widoczny).
  3. Aplikacja prosi system o wyświetlenie kanału.
  4. System prosi użytkownika o zatwierdzenie nowego kanału.
  5. Nowy kanał pojawi się w ostatnim wierszu ekranu głównego.

Kanał domyślny

Aplikacja może oferować dowolną liczbę kanałów, które użytkownik może dodać do ekranu głównego. Zwykle użytkownik musi wybierz i zatwierdź każdy kanał, zanim pojawi się na ekranie głównym. Każda aplikacja ma możliwość utworzenia jednego domyślnego kanału. Kanał domyślny jest wyjątkowy, ponieważ automatycznie pojawia się na ekranie głównym. użytkownik nie musi wyraźnie o to prosić.

Wymagania wstępne

Ekran główny Androida TV używa interfejsów API Androida TvProvider do zarządzania kanałami i programami tworzonymi przez Twoją aplikację. Aby uzyskać dostęp do danych dostawcy, dodaj do pliku manifestu aplikacji te uprawnienia:

<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />

Biblioteka pomocy TvProvider ułatwia korzystanie z usług dostawcy. Dodaj ją do zależności w pliku build.gradle:

Odlotowe

implementation 'androidx.tvprovider:tvprovider:1.0.0'

Kotlin

implementation("androidx.tvprovider:tvprovider:1.0.0")

Aby móc pracować z kanałami i programami, uwzględnij w programie te zaimportowane biblioteki pomocnicze:

Kotlin

import android.support.media.tv.Channel
import android.support.media.tv.TvContractCompat
import android.support.media.tv.ChannelLogoUtils
import android.support.media.tv.PreviewProgram
import android.support.media.tv.WatchNextProgram

Java

import android.support.media.tv.Channel;
import android.support.media.tv.TvContractCompat;
import android.support.media.tv.ChannelLogoUtils;
import android.support.media.tv.PreviewProgram;
import android.support.media.tv.WatchNextProgram;

Kanały

Pierwszy kanał utworzony przez aplikację staje się kanałem domyślnym. Kanał domyślny pojawi się automatycznie na ekranie głównym. Wszystkie inne utworzone przez Ciebie kanały muszą zostać wybrane i zaakceptowane przez użytkownika, zanim pojawią się na ekranie głównym.

Tworzenie kanału

Aplikacja powinna prosić system o wyświetlenie nowo dodanych kanałów tylko wtedy, gdy działa na pierwszym planie. Dzięki temu aplikacja nie będzie wyświetlać okna z prośbą o zatwierdzenie dodania kanału, gdy użytkownik korzysta z innej aplikacji. Jeśli spróbujesz dodać kanał, gdy działasz w tle, metoda onActivityResult() aktywności zwróci kod stanu RESULT_CANCELED.

Aby utworzyć kanał, wykonaj te czynności:

  1. Utwórz kreator kanałów i ustaw jego atrybuty. Pamiętaj, że parametr Typ kanału musi być ustawiony na TYPE_PREVIEW. Dodaj więcej atrybuty.

    Kotlin

    val builder = Channel.Builder()
    // Every channel you create must have the type TYPE_PREVIEW
    builder.setType(TvContractCompat.Channels.TYPE_PREVIEW)
            .setDisplayName("Channel Name")
            .setAppLinkIntentUri(uri)
    

    Java

    Channel.Builder builder = new Channel.Builder();
    // Every channel you create must have the type TYPE_PREVIEW
    builder.setType(TvContractCompat.Channels.TYPE_PREVIEW)
            .setDisplayName("Channel Name")
            .setAppLinkIntentUri(uri);
    
  2. Wstaw kanał do dostawcy:

    Kotlin

    var channelUri = context.contentResolver.insert(
            TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues())
    

    Java

    Uri channelUri = context.getContentResolver().insert(
            TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues());
    
  3. Musisz zapisać identyfikator kanału, aby móc dodać do niego programy później. Wyodrębnij identyfikator kanału ze zwróconego identyfikatora URI:

    Kotlin

    var channelId = ContentUris.parseId(channelUri)
    

    Java

    long channelId = ContentUris.parseId(channelUri);
    
  4. Musisz dodać logo kanału. Użyj pola Uri lub Bitmap. Logo ikona powinna mieć wymiary 80 dp x 80 dp i być nieprzezroczysta. Jest wyświetlany pod okrągła maska:

    Maska ikony ekranu głównego telewizora

    Kotlin

    // Choose one or the other
    storeChannelLogo(context: Context, channelId: Long, logoUri: Uri) // also works if logoUri is a URL
    storeChannelLogo(context: Context, channelId: Long, logo: Bitmap)
    

    Java

    // Choose one or the other
    storeChannelLogo(Context context, long channelId, Uri logoUri); // also works if logoUri is a URL
    storeChannelLogo(Context context, long channelId, Bitmap logo);
    
  5. Utwórz kanał domyślny (opcjonalnie): gdy aplikacja utworzy po raz pierwszy Twój kanał może być kanału domyślnego, dzięki czemu będzie widoczny na stronie głównej. ekran bez żadnego działania ze strony użytkownika. Inne utworzone przez Ciebie kanały nie są widoczne, dopóki użytkownik nie wyrazi na to zgody wybierze je.

    Kotlin

    TvContractCompat.requestChannelBrowsable(context, channelId)
    

    Java

    TvContractCompat.requestChannelBrowsable(context, channelId);
    

  6. Spraw, aby kanał domyślny był widoczny przed otwarciem aplikacji. Dostępne opcje aby to działało, dodaj element BroadcastReceiver, który nasłuchuje android.media.tv.action.INITIALIZE_PROGRAMS, czyli działanie ekranu głównego wysyła po zainstalowaniu aplikacji:
    <receiver
      android:name=".RunOnInstallReceiver"
      android:exported="true">
        <intent-filter>
          <action android:name="android.media.tv.action.INITIALIZE_PROGRAMS" />
          <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
    
    Jeśli instalujesz aplikację z innego urządzenia w trakcie jej programowania, możesz przetestować ten krok, za pomocą narzędzia adb, który aktywuje intencję, your.package.name/.YourReceiverName to adres Twojej aplikacji BroadcastReceiver:

    adb shell am broadcast -a android.media.tv.action.INITIALIZE_PROGRAMS -n \
        your.package.name/.YourReceiverName
    

    W rzadkich przypadkach aplikacja może odbierać transmisję w tym samym czasie co użytkownik uruchomi aplikację. Upewnij się, że za pomocą kodu nie można dodać kanału domyślnego więcej niż raz.

Aktualizowanie kanału

Aktualizowanie kanałów jest bardzo podobne do ich tworzenia.

Użyj innego elementu Channel.Builder, aby ustawić atrybuty, które musisz zmienić.

Użyj aplikacji ContentResolver, aby zaktualizować kanał. Użyj identyfikatora kanału zapisanego podczas jego dodawania:

Kotlin

context.contentResolver.update(
        TvContractCompat.buildChannelUri(channelId),
        builder.build().toContentValues(),
        null,
        null
)

Java

context.getContentResolver().update(TvContractCompat.buildChannelUri(channelId),
    builder.build().toContentValues(), null, null);

Aby zaktualizować logo kanału, użyj storeChannelLogo().

Usuwanie kanału

Kotlin

context.contentResolver.delete(TvContractCompat.buildChannelUri(channelId), null, null)

Java

context.getContentResolver().delete(TvContractCompat.buildChannelUri(channelId), null, null);

Programy

Dodawanie programów do kanału aplikacji

Utwórz obiekt PreviewProgram.Builder i ustaw jego atrybuty:

Kotlin

val builder = PreviewProgram.Builder()
builder.setChannelId(channelId)
        .setType(TvContractCompat.PreviewPrograms.TYPE_CLIP)
        .setTitle("Title")
        .setDescription("Program description")
        .setPosterArtUri(uri)
        .setIntentUri(uri)
        .setInternalProviderId(appProgramId)

Java

PreviewProgram.Builder builder = new PreviewProgram.Builder();
builder.setChannelId(channelId)
        .setType(TvContractCompat.PreviewPrograms.TYPE_CLIP)
        .setTitle("Title")
        .setDescription("Program description")
        .setPosterArtUri(uri)
        .setIntentUri(uri)
        .setInternalProviderId(appProgramId);

Dodaj więcej atrybutów w zależności od typu programu. (Aby wyświetlić atrybuty w przypadku każdego typu programu znajdziesz w tabelach poniżej).

Wstaw program w systemie dostawcy:

Kotlin

var programUri = context.contentResolver.insert(TvContractCompat.PreviewPrograms.CONTENT_URI,
        builder.build().toContentValues())

Java

Uri programUri = context.getContentResolver().insert(TvContractCompat.PreviewPrograms.CONTENT_URI,
      builder.build().toContentValues());

Pobierz identyfikator programu do późniejszego wykorzystania:

Kotlin

val programId = ContentUris.parseId(programUri)

Java

long programId = ContentUris.parseId(programUri);

Dodawanie programów do kanału Warte obejrzenia

Aby wstawić programy na kanale Warte obejrzenia, przeczytaj artykuł Dodawanie programów do sekcji Obejrzyj Następny kanał.

Aktualizowanie programu

Informacje o programie możesz zmienić. Możesz na przykład zaktualizować cenę wypożyczania filmu lub zaktualizować pasek postępu pokazujący, jaką część programu obejrzał użytkownik.

Użyj PreviewProgram.Builder, aby ustawić atrybuty, które chcesz zmienić. a następnie wywołaj getContentResolver().update, aby zaktualizować program. Podaj identyfikator programu zapisany podczas dodawania programu:

Kotlin

context.contentResolver.update(
        TvContractCompat.buildPreviewProgramUri(programId),
                builder.build().toContentValues(), null, null
)

Java

context.getContentResolver().update(TvContractCompat.buildPreviewProgramUri(programId),
    builder.build().toContentValues(), null, null);

Usuwanie programu

Kotlin

context.contentResolver
        .delete(TvContractCompat.buildPreviewProgramUri(programId), null, null)

Java

context.getContentResolver().delete(TvContractCompat.buildPreviewProgramUri(programId), null, null);

Obsługa działań użytkowników

Twoja aplikacja może pomóc użytkownikom w odkrywaniu treści, udostępniając interfejs do wyświetlania i dodawania kanałów. Aplikacja powinna też obsługiwać interakcje z kanałami, gdy pojawią się one na ekranie głównym.

Odkrywanie i dodawanie kanałów

Aplikacja może zawierać element interfejsu, który umożliwia użytkownikowi wybranie i dodanie kanałów (np. przycisk umożliwiający dodanie kanału).

Gdy użytkownik poprosi o dostęp do konkretnego kanału, uruchom ten kod, aby uzyskać zgodę użytkownika na dodanie go do interfejsu użytkownika ekranu głównego:

Kotlin

val intent = Intent(TvContractCompat.ACTION_REQUEST_CHANNEL_BROWSABLE)
intent.putExtra(TvContractCompat.EXTRA_CHANNEL_ID, channelId)
try {
  activity.startActivityForResult(intent, 0)
} catch (e: ActivityNotFoundException) {
  // handle error
}

Java

Intent intent = new Intent(TvContractCompat.ACTION_REQUEST_CHANNEL_BROWSABLE);
intent.putExtra(TvContractCompat.EXTRA_CHANNEL_ID, channelId);
try {
   activity.startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
  // handle error
}

System wyświetli okno z prośbą o zatwierdzenie kanału. Przetwórz wynik żądania w metodzie onActivityResult Twojej aktywności (Activity.RESULT_CANCELED lub Activity.RESULT_OK).

Zdarzenia na ekranie głównym Androida TV

Gdy użytkownik wchodzi w interakcję z programami lub kanałami opublikowanymi przez aplikację, ekran główny wysyła do niej intencje:

  • Gdy użytkownik wybierze logo kanału, ekran główny wysyła do aplikacji Uri zapisane w atrybucie APP_LINK_INTENT_URI kanału. Aplikacja powinna po prostu uruchomić główny interfejs lub widok związany z wybranym kanałem.
  • Gdy użytkownik wybierze program, ekran główny wysyła do aplikacji Uri zapisane w atrybucie INTENT_URI programu. Aplikacja powinna odtworzyć wybrane treści.
  • Użytkownik może wskazać, że nie jest już zainteresowany programem i chce usunąć go z interfejsu na ekranie głównym. System usuwa program z interfejsu i wysyła do aplikacji będącej jego właścicielem intencję (android.media.tv.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED lub android.media.tv.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED) z identyfikatorem programu. Aplikacja powinna usunąć program od dostawcy i NIE należy go instalować ponownie.

Pamiętaj, aby utworzyć filtry intencji dla wszystkich elementów typu Uris wysyłanych przez ekran główny w przypadku interakcji użytkownika. np.:

<receiver
   android:name=".WatchNextProgramRemoved"
   android:enabled="true"
   android:exported="true">
   <intent-filter>
       <action android:name="android.media.tv.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED" />
   </intent-filter>
</receiver>

Sprawdzone metody

  • Wiele aplikacji telewizyjnych wymaga zalogowania się. W tym przypadku BroadcastReceiver który słucha przez android.media.tv.action.INITIALIZE_PROGRAMS, powinien zaproponować treści na kanale dla nieuwierzytelnionych użytkowników.Na przykład aplikacja może początkowo pokazuje najlepsze lub aktualnie popularne treści. Gdy użytkownik się zaloguje, mogą wyświetlać spersonalizowane treści. To świetna okazja, by zwiększyć sprzedaż aplikacji użytkowników przed zalogowaniem się.
  • Gdy aplikacja nie działa na pierwszym planie i musisz zaktualizować kanał lub programu, użyj JobScheduler, aby zaplanować pracę (zobacz: Harmonogram zadań i JobService).
  • System może anulować uprawnienia dostawcy aplikacji, jeśli aplikacja będzie działać nieprawidłowo (na przykład przez ciągłe spamowanie dostawcy danymi). Upewnij się, że opakuj kod uzyskujący dostęp do dostawcy za pomocą klauzul try-catch do obsługi wyjątki od zabezpieczeń.
  • Zanim zaktualizujesz programy i kanały, poproś dostawcę o dane, które trzeba zaktualizować i uzgodnić. Nie trzeba na przykład aktualizować program, który użytkownik chce usunąć z interfejsu. Użyj zadania w tle, które wstawia/aktualizuje Twoje dane u dostawcy po wysłaniu zapytania o istniejące dane z danymi, a następnie o zatwierdzenie kanału. Możesz uruchomić to zadanie, gdy Aplikacja uruchamia się i wymaga zaktualizowania danych.

    Kotlin

    context.contentResolver
      .query(
          TvContractCompat.buildChannelUri(channelId),
              null, null, null, null).use({
                  cursor-> if (cursor != null and cursor.moveToNext()) {
                               val channel = Channel.fromCursor(cursor)
                               if (channel.isBrowsable()) {
                                   //update channel's programs
                               }
                           }
              })
    

    Java

    try (Cursor cursor = context.getContentResolver()
          .query(
              TvContractCompat.buildChannelUri(channelId),
              null,
              null,
              null,
              null)) {
                  if (cursor != null && cursor.moveToNext()) {
                      Channel channel = Channel.fromCursor(cursor);
                      if (channel.isBrowsable()) {
                          //update channel's programs
                      }
                  }
              }
    
  • Używaj unikalnych identyfikatorów URI do wszystkich obrazów (logo, ikon, obrazów treści). Pamiętaj, aby podczas aktualizowania obrazu użyć innego identyfikatora URI. Wszystkie obrazy są przechowywane w pamięci podręcznej. Jeśli nie zmienisz identyfikatora URI po zmianie obrazu, stary obraz nadal będzie wyświetlany.

  • Pamiętaj, że klauzule WHERE są niedozwolone, a wywołania dostawców z klauzulami WHERE będą zgłaszać wyjątek od zabezpieczeń.

Atrybuty

W tej sekcji opisano oddzielnie atrybuty kanału i programu.

Atrybuty kanału

Musisz określić dla każdego kanału te atrybuty:

Atrybut Uwagi
TYP ustaw jako TYPE_PREVIEW.
DISPLAY_NAME musi zawierać nazwę kanału.
APP_LINK_INTENT_URI Gdy użytkownik wybierze logo kanału, system wysyła zamiar rozpoczęcia działania, które przedstawia treści pasujące do kanału. Ustaw ten atrybut na identyfikator URI używany w filtrze intencji dla tej aktywności.

Dodatkowo kanał ma 6 pól zarezerwowanych na potrzeby wewnętrznego użycia aplikacji. W tych polach możesz zapisywać klucze lub inne wartości, które pomagają aplikacji mapować kanał na wewnętrzną strukturę danych:

  • INTERNAL_PROVIDER_ID (Identyfikator_WEWNĘTRZNEGO DOSTAWCY)
  • DANE_WEWNĘTRZNE
  • DOSTAWCA_WEWNĘTRZNY_FLAG1
  • DOSTAWCA_WEWNĘTRZNY_FLAG2
  • DOSTAWCA_WEWNĘTRZNY_FLAG3
  • DOSTAWCA_WEWNĘTRZNY_FLAG4

Atrybuty programu

Szczegółowe informacje o atrybutach poszczególnych typów programów znajdziesz na stronach:

Kod demonstracyjny

Aby dowiedzieć się więcej o tworzeniu aplikacji, które wchodzą w interakcję z ekranem głównym oraz dodają kanały i programy do ekranu głównego Androida TV, zapoznaj się z ćwiczeniami z programowania dotyczącymi ekranu głównego.