Kanäle auf dem Startbildschirm

Der Startbildschirm von Android TV bietet eine Benutzeroberfläche, auf der empfohlene Inhalte als Tabelle mit Kanälen und Programmen angezeigt werden. Jede Zeile entspricht einem Channel. Ein Kanal enthält Karten für jedes Programm, das auf diesem Kanal verfügbar ist:

Android TV-Startbildschirm
Android TV-Startbildschirm

In diesem Dokument wird gezeigt, wie du Kanäle und Programme zum Startbildschirm hinzufügst, Inhalte aktualisierst, Nutzeraktionen verarbeitest und Nutzern die bestmögliche Erfahrung bietest. (Wenn du dich näher mit der API beschäftigen möchtest, probiere das Codelab für den Startbildschirm aus und sieh dir die Android TV-Session der I/O 2017 an.)

Die Benutzeroberfläche des Startbildschirms

Apps können neue Kanäle erstellen, die Programme in einem Kanal hinzufügen, entfernen und aktualisieren sowie die Reihenfolge der Programme in einem Kanal steuern. Eine App kann beispielsweise einen Kanal namens „Neuigkeiten“ erstellen und Karten für neu verfügbare Programme anzeigen.

Apps können die Reihenfolge, in der Kanäle auf dem Startbildschirm angezeigt werden, nicht steuern. Wenn deine App einen neuen Kanal erstellt, wird er auf dem Startbildschirm am Ende der Kanalliste hinzugefügt. Der Nutzer kann Kanäle neu anordnen, ausblenden und einblenden.

Der Kanal „Empfohlene Videos“

Der Kanal „Empfohlene Videos“ ist die zweite Zeile, die auf dem Startbildschirm nach der App-Zeile angezeigt wird. Der Kanal wird vom System erstellt und verwaltet. Deine App kann dem Kanal „Empfohlene Videos“ Programme hinzufügen. Weitere Informationen findest du unter Empfohlene Videos zum Kanal „Als Nächstes ansehen“ hinzufügen.

App-Channels

Die von Ihrer App erstellten Kanäle durchlaufen alle diesen Lebenszyklus:

  1. Der Nutzer entdeckt einen Kanal in deiner App und fordert an, ihn dem Startbildschirm hinzuzufügen.
  2. Die App erstellt den Kanal und fügt ihn dem TvProvider hinzu. Zu diesem Zeitpunkt ist der Kanal nicht sichtbar.
  3. Die App fordert das System auf, den Kanal anzuzeigen.
  4. Das System fordert den Nutzer auf, den neuen Kanal zu genehmigen.
  5. Der neue Kanal wird in der letzten Zeile des Startbildschirms angezeigt.

Der Standardkanal

Deine App kann beliebig viele Kanäle anbieten, die der Nutzer dem Startbildschirm hinzufügen kann. Der Nutzer muss in der Regel jeden Kanal auswählen und genehmigen, bevor er auf dem Startbildschirm angezeigt wird. Für jede App kann ein Standardkanal erstellt werden. Der Standardkanal ist etwas Besonderes, da er automatisch auf dem Startbildschirm angezeigt wird. Der Nutzer muss ihn nicht explizit anfordern.

Vorbereitung

Der Android TV-Startbildschirm verwendet die TvProvider-APIs von Android, um die von deiner App erstellten Kanäle und Programme zu verwalten. Füge dem Manifest deiner App die folgende Berechtigung hinzu, um auf die Daten des Anbieters zuzugreifen:

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

Die Supportbibliothek TvProvider erleichtert die Verwendung des Anbieters. Fügen Sie sie den Abhängigkeiten in der Datei build.gradle hinzu:

Groovy

implementation 'androidx.tvprovider:tvprovider:1.0.0'

Kotlin

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

Wenn du mit Kanälen und Programmen arbeiten möchtest, musst du die folgenden Support-Bibliotheken in dein Programm importieren:

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;

Kanäle

Der erste Kanal, den Ihre App erstellt, wird zum Standardkanal. Der Standardkanal wird automatisch auf dem Startbildschirm angezeigt. Alle anderen von dir erstellten Kanäle müssen vom Nutzer ausgewählt und akzeptiert werden, bevor sie auf dem Startbildschirm angezeigt werden können.

Kanal erstellen

Ihre App sollte das System nur dann auffordern, neu hinzugefügte Kanäle anzuzeigen, wenn sie im Vordergrund ausgeführt wird. Dadurch wird verhindert, dass in deiner App ein Dialogfeld angezeigt wird, in dem der Nutzer um die Genehmigung zum Hinzufügen deines Kanals gebeten wird, während er eine andere App verwendet. Wenn du versuchst, einen Kanal hinzuzufügen, während die App im Hintergrund ausgeführt wird, gibt die Methode onActivityResult() der Aktivität den Statuscode RESULT_CANCELED zurück.

So erstellen Sie einen Kanal:

  1. Erstellen Sie einen Channel-Builder und legen Sie seine Attribute fest. Der Kanaltyp muss TYPE_PREVIEW sein. Fügen Sie nach Bedarf weitere Attribute hinzu.

    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. Fügen Sie den Kanal in den Anbieter ein:

    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. Du musst die Kanal-ID speichern, um dem Kanal später Programme hinzuzufügen. Extrahieren Sie die Kanal-ID aus dem zurückgegebenen URI:

    Kotlin

    var channelId = ContentUris.parseId(channelUri)
    

    Java

    long channelId = ContentUris.parseId(channelUri);
    
  4. Sie müssen ein Logo für Ihren Kanal hinzufügen. Verwenden Sie einen Uri oder Bitmap. Das Logo-Symbol muss 80 dp × 80 dp groß und undurchsichtig sein. Es wird unter einer kreisförmigen Maske angezeigt:

    Symbolmaske für den Startbildschirm des Fernsehers

    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. Standardkanal erstellen (optional): Wenn deine App den ersten Kanal erstellt, kannst du ihn als Standardkanal festlegen, damit er sofort auf dem Startbildschirm angezeigt wird, ohne dass der Nutzer etwas tun muss. Alle anderen von Ihnen erstellten Kanäle sind erst sichtbar, wenn der Nutzer sie explizit auswählt.

    Kotlin

    TvContractCompat.requestChannelBrowsable(context, channelId)
    

    Java

    TvContractCompat.requestChannelBrowsable(context, channelId);
    
  6. Legen Sie fest, dass Ihr Standardkanal angezeigt wird, bevor Ihre App geöffnet wird. Dieses Verhalten können Sie erreichen, indem Sie einen BroadcastReceiver hinzufügen, der auf die Aktion android.media.tv.action.INITIALIZE_PROGRAMS wartet, die der Startbildschirm nach der Installation der App sendet:

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

    Wenn Sie Ihre App während der Entwicklung per Sideloading installieren, können Sie diesen Schritt testen, indem Sie den Intent über adb auslösen, wobei your.package.name/.YourReceiverName der BroadcastReceiver Ihrer App ist:

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

    In seltenen Fällen empfängt deine App die Übertragung möglicherweise gleichzeitig mit dem Start der App durch den Nutzer. Achte darauf, dass dein Code nicht versucht, den Standardkanal mehr als einmal hinzuzufügen.

Kanal aktualisieren

Das Aktualisieren von Kanälen funktioniert ähnlich wie das Erstellen.

Verwenden Sie ein weiteres Channel.Builder, um die Attribute festzulegen, die geändert werden müssen.

Verwenden Sie ContentResolver, um den Kanal zu aktualisieren. Verwenden Sie die Kanal-ID, die Sie beim ursprünglichen Hinzufügen des Kanals gespeichert haben:

Kotlin

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

Java

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

Verwenden Sie storeChannelLogo(), um das Logo eines Kanals zu aktualisieren.

Kanal löschen

Kotlin

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

Java

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

Programme

Programme sind die einzelnen Inhaltskarten, die in einem Kanal angezeigt werden. Du kannst Programme sowohl in den benutzerdefinierten Channels deiner App als auch im vom System verwalteten Channel „Empfohlene Videos“ veröffentlichen.

Programme zu einem App-Kanal hinzufügen

Erstellen Sie ein PreviewProgram.Builder und legen Sie die Attribute fest:

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

Fügen Sie je nach Programmtyp weitere Attribute hinzu. Die für die einzelnen Programmtypen verfügbaren Attribute finden Sie in den Tabellen unten.

Fügen Sie das Programm in den Anbieter ein:

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());

Rufen Sie die Programm-ID zur späteren Verwendung ab:

Kotlin

val programId = ContentUris.parseId(programUri)

Java

long programId = ContentUris.parseId(programUri);

Programme zum Kanal „Empfohlene Videos“ hinzufügen

Informationen zum Einfügen von Programmen in den Kanal „Empfohlene Videos“ findest du unter Programme zum Kanal „Empfohlene Videos“ hinzufügen.

Programm aktualisieren

Sie können die Informationen zu einem Programm ändern. Beispielsweise kannst du den Mietpreis für einen Film oder eine Fortschrittsanzeige aktualisieren, die zeigt, wie viel von einem Programm der Nutzer angesehen hat.

Verwenden Sie ein PreviewProgram.Builder, um die Attribute festzulegen, die Sie ändern möchten, und rufen Sie dann getContentResolver().update auf, um das Programm zu aktualisieren. Geben Sie die Programm-ID an, die Sie beim ursprünglichen Hinzufügen des Programms gespeichert haben:

Kotlin

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

Java

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

Programm löschen

Kotlin

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

Java

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

Nutzeraktionen verarbeiten

Deine App kann Nutzern helfen, Inhalte zu entdecken, indem sie eine Benutzeroberfläche zum Anzeigen und Hinzufügen von Kanälen bereitstellt. Deine App sollte auch Interaktionen mit deinen Kanälen verarbeiten, nachdem sie auf dem Startbildschirm angezeigt wurden.

Kanäle entdecken und hinzufügen

Deine App kann ein UI-Element bereitstellen, über das der Nutzer die Kanäle auswählen und hinzufügen kann (z. B. eine Schaltfläche, über die der Nutzer aufgefordert wird, den Kanal hinzuzufügen).

Nachdem der Nutzer einen bestimmten Kanal angefordert hat, führe diesen Code aus, um die Berechtigung des Nutzers zum Hinzufügen des Kanals zur Startbildschirm-UI zu erhalten:

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
}

Das System zeigt ein Dialogfeld an, in dem der Nutzer aufgefordert wird, den Kanal zu genehmigen. Verarbeiten Sie das Ergebnis der Anfrage in der Methode onActivityResult Ihrer Aktivität (Activity.RESULT_CANCELED oder Activity.RESULT_OK).

Ereignisse auf dem Android TV-Startbildschirm

Wenn der Nutzer mit den von der App veröffentlichten Programmen und Kanälen interagiert, sendet der Startbildschirm Intents an die App:

  • Der Startbildschirm sendet den im Attribut APP_LINK_INTENT_URI eines Kanals gespeicherten Uri an die App, wenn der Nutzer das Logo des Kanals auswählt. Die App sollte nur die Haupt-UI oder eine Ansicht starten, die sich auf den ausgewählten Kanal bezieht.
  • Der Startbildschirm sendet den im INTENT_URI-Attribut eines Programms gespeicherten Uri an die App, wenn der Nutzer ein Programm auswählt. Die App sollte den ausgewählten Inhalt abspielen.
  • Der Nutzer kann angeben, dass er nicht mehr an einem Programm interessiert ist und es von der Benutzeroberfläche des Startbildschirms entfernt werden soll. Das System entfernt das Programm aus der Benutzeroberfläche und sendet einen Intent (android.media.tv.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED oder android.media.tv.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED) mit der ID des Programms an die App, zu der das Programm gehört. Die App sollte das Programm vom Anbieter entfernen und NICHT wieder einfügen.

Erstelle Intent-Filter für alle Uris, die der Startbildschirm für Nutzerinteraktionen sendet, z. B.:

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

Weitere Überlegungen

  • Bei vielen TV-Apps müssen sich Nutzer anmelden. In diesem Fall sollte der BroadcastReceiver, der auf android.media.tv.action.INITIALIZE_PROGRAMS wartet, Kanalinhalte für nicht authentifizierte Nutzer vorschlagen. Ihre App kann beispielsweise zuerst die besten oder aktuell beliebte Inhalte anzeigen. Nachdem sich der Nutzer angemeldet hat, können personalisierte Inhalte angezeigt werden. Das ist eine gute Gelegenheit, Nutzern vor der Anmeldung ein Upgrade anzubieten.
  • Wenn sich deine App nicht im Vordergrund befindet und du einen Kanal oder ein Programm aktualisieren musst, verwende den JobScheduler, um die Arbeit zu planen (siehe JobScheduler und JobService).
  • Das System kann die Anbieterberechtigungen deiner App widerrufen, wenn sie sich nicht ordnungsgemäß verhält (z. B. wenn sie den Anbieter kontinuierlich mit Daten überflutet). Achten Sie darauf, den Code, der auf den Anbieter zugreift, mit try-catch-Klauseln zu umschließen, um Sicherheitsausnahmen zu verarbeiten.
  • Bevor du Programme und Kanäle aktualisierst, frage den Anbieter nach den Daten, die du aktualisieren musst, und gleiche die Daten ab. Es ist beispielsweise nicht erforderlich, ein Programm zu aktualisieren, das der Nutzer aus der Benutzeroberfläche entfernen möchte. Verwenden Sie einen Hintergrundjob, der Ihre Daten in den Anbieter einfügt oder aktualisiert, nachdem die vorhandenen Daten abgefragt wurden und die Genehmigung für Ihre Kanäle angefordert wurde. Sie können diesen Job ausführen, wenn die App gestartet wird und wenn die App ihre Daten aktualisieren muss.

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 &amp;&amp; cursor.moveToNext()) {
                      Channel channel = Channel.fromCursor(cursor);
                      if (channel.isBrowsable()) {
                          //update channel's programs
                      }
                  }
              }
  • Verwenden Sie für alle Bilder (Logos, Symbole, Inhaltsbilder) eindeutige URIs. Verwenden Sie beim Aktualisieren eines Images einen anderen URI. Alle Bilder werden im Cache gespeichert. Wenn Sie die URI beim Ändern des Bildes nicht ändern, wird weiterhin das alte Bild angezeigt.

  • Denken Sie daran, dass WHERE-Klauseln nicht zulässig sind und Aufrufe an die Anbieter mit WHERE-Klauseln eine Sicherheitsausnahme auslösen.

Attribute

In diesem Abschnitt werden die Kanal- und Programmattribute separat beschrieben.

Kanalattribute

Sie müssen diese Attribute für jeden Kanal angeben:

Attribut Hinweise
TYP auf TYPE_PREVIEW festgelegt.
DISPLAY_NAME auf den Namen des Kanals festgelegt ist.
APP_LINK_INTENT_URI Wenn der Nutzer das Logo des Kanals auswählt, sendet das System einen Intent, um eine Aktivität zu starten, die für den Kanal relevante Inhalte präsentiert. Legen Sie dieses Attribut auf den URI fest, der im Intent-Filter für diese Aktivität verwendet wird.

Darüber hinaus hat ein Kanal sechs Felder, die für die interne App-Nutzung reserviert sind. In diesen Feldern können Schlüssel oder andere Werte gespeichert werden, mit denen die App den Kanal der internen Datenstruktur zuordnen kann:

  • INTERNAL_PROVIDER_ID
  • INTERNAL_PROVIDER_DATA
  • INTERNAL_PROVIDER_FLAG1
  • INTERNAL_PROVIDER_FLAG2
  • INTERNAL_PROVIDER_FLAG3
  • INTERNAL_PROVIDER_FLAG4

Programmattribute

Auf den einzelnen Seiten finden Sie die Attribute für die verschiedenen Programmtypen:

Beispielcode

Weitere Informationen zum Erstellen von Apps, die mit dem Startbildschirm interagieren, und zum Hinzufügen von Kanälen und Programmen zum Android TV-Startbildschirm findest du in unserem Codelab zum Startbildschirm.