Canali nella schermata Home

La schermata Home di Android TV, o semplicemente la schermata Home, offre un'interfaccia utente che mostra i contenuti consigliati sotto forma di tabella di canali e programmi. Ogni riga rappresenta un canale. Un canale contiene schede per ogni programma disponibile su quel canale:

Schermata Home della TV

Questo documento spiega come aggiungere canali e programmi alla schermata Home, aggiornare i contenuti, gestire le azioni degli utenti e offrire agli utenti la migliore esperienza possibile. Se vuoi saperne di più sull'API, prova il codelab sulla schermata Home e guarda la sessione su Android TV I/O 2017.

Nota: i canali Consigli sono disponibili solo in Android 8.0 (livello API 26) e versioni successive. Devi utilizzarle per fornire suggerimenti per le app eseguite con Android 8.0 (livello API 26) e versioni successive. Per fornire suggerimenti per le app eseguite con versioni precedenti di Android, la tua app deve utilizzare invece la riga dei suggerimenti.

L'UI della schermata Home

Le app possono creare nuovi canali, aggiungere, rimuovere e aggiornare i programmi di un canale, nonché controllare l'ordine dei programmi al suo interno. Ad esempio, un'app può creare un canale chiamato "Novità" e mostrare schede relative ai programmi appena disponibili.

Le app non possono controllare l'ordine di visualizzazione dei canali nella schermata Home. Quando la tua app crea un nuovo canale, la schermata Home lo aggiunge in fondo all'elenco di canali. L'utente può riordinare, nascondere e mostrare i canali.

Il canale Guarda in seguito

Il canale Guarda in seguito è la seconda riga visualizzata nella schermata Home, dopo la riga delle app. Il sistema crea e gestisce questo canale. L'app può aggiungere programmi al canale Guarda in seguito. Per ulteriori informazioni, consulta la sezione Aggiungere programmi al canale Guarda in seguito.

Canali app

I canali creati dalla tua app seguono questo ciclo di vita:

  1. L'utente scopre un canale nella tua app e chiede di aggiungerlo alla schermata Home.
  2. L'app crea il canale e lo aggiunge a TvProvider (a questo punto il canale non è visibile).
  3. L'app chiede al sistema di visualizzare il canale.
  4. Il sistema chiede all'utente di approvare il nuovo canale.
  5. Il nuovo canale viene visualizzato nell'ultima riga della schermata Home.

Il canale predefinito

L'app può offrire all'utente un numero qualsiasi di canali da aggiungere alla schermata Home. Solitamente l'utente deve selezionare e approvare ciascun canale prima che questo venga visualizzato nella schermata Home. Ogni app ha la possibilità di creare un canale predefinito. Il canale predefinito è speciale perché appare automaticamente nella schermata Home; l'utente non deve richiederlo esplicitamente.

Prerequisiti

La schermata Home di Android TV utilizza le API TvProvider di Android per gestire i canali e i programmi creati dalla tua app. Per accedere ai dati del fornitore, aggiungi la seguente autorizzazione al file manifest dell'app:

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

La libreria di assistenza TvProvider semplifica l'utilizzo del provider. Aggiungilo alle dipendenze nel tuo file build.gradle:

Trendy

implementation 'androidx.tvprovider:tvprovider:1.0.0'

Kotlin

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

Per lavorare con canali e programmi, assicurati di includere nel programma le seguenti importazioni della libreria di supporto:

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;

Canali

Il primo canale creato dalla tua app diventa il canale predefinito. Il canale predefinito viene visualizzato automaticamente nella schermata Home. Tutti gli altri canali che crei devono essere selezionati e accettati dall'utente prima di poter essere visualizzati nella schermata Home.

Creazione di un canale

L'app dovrebbe chiedere al sistema di mostrare i canali appena aggiunti solo quando sono in esecuzione in primo piano. Questo impedisce alla tua app di mostrare una finestra di dialogo che richiede l'approvazione per aggiungere il tuo canale mentre l'utente utilizza un'altra app. Se provi ad aggiungere un canale mentre viene eseguito in background, il metodo onActivityResult() dell'attività restituisce il codice di stato RESULT_CANCELED.

Per creare un canale:

  1. Creare uno strumento per la creazione di canali e impostarne gli attributi. Tieni presente che il tipo di canale deve essere TYPE_PREVIEW. Aggiungi altri attributi come richiesto.

    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. Inserisci il canale nel provider:

    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. Devi salvare l'ID canale per aggiungere programmi al canale in un secondo momento. Estrai l'ID canale dall'URI restituito:

    Kotlin

    var channelId = ContentUris.parseId(channelUri)
    

    Java

    long channelId = ContentUris.parseId(channelUri);
    
  4. Devi aggiungere un logo per il tuo canale. Utilizza un Uri o un Bitmap. L'icona del logo deve essere 80 dp x 80 dp e deve essere opaca. Viene visualizzata sotto una maschera circolare:

    Maschera dell&#39;icona della schermata Home della TV

    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. (Facoltativo) Crea il canale predefinito: quando l'app crea il primo canale, puoi impostarlo come canale predefinito in modo che venga visualizzato immediatamente nella schermata Home senza alcuna azione dell'utente. Tutti gli altri canali che crei non sono visibili finché l'utente non li seleziona esplicitamente.

    Kotlin

    TvContractCompat.requestChannelBrowsable(context, channelId)
    

    Java

    TvContractCompat.requestChannelBrowsable(context, channelId);
    

  6. Mostra il tuo canale predefinito prima dell'apertura dell'app. Puoi ottenere questo comportamento aggiungendo un BroadcastReceiver che ascolti l'azione android.media.tv.action.INITIALIZE_PROGRAMS, che la schermata Home invia dopo l'installazione dell'app:
    <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>
    
    Quando esegui il sideload della tua app durante lo sviluppo, puoi testare questo passaggio attivando l'intent tramite adb, dove your.package.name/.YourReceiverName è l'BroadcastReceiver della tua app:

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

    In rari casi, la tua app potrebbe ricevere la trasmissione nello stesso momento in cui l'utente avvia l'app. Assicurati che il codice non provi ad aggiungere il canale predefinito più di una volta.

Aggiornare un canale

Aggiornare i canali è molto simile alla loro creazione.

Utilizza un altro Channel.Builder per impostare gli attributi che devono essere modificati.

Usa ContentResolver per aggiornare il canale. Utilizza l'ID canale salvato al momento dell'aggiunta iniziale del canale:

Kotlin

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

Java

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

Per aggiornare il logo di un canale, utilizza storeChannelLogo().

Eliminazione di un canale

Kotlin

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

Java

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

Programmi

Aggiunta di programmi a un canale dell'app

Crea un PreviewProgram.Builder e imposta i relativi attributi:

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

Aggiungi altri attributi a seconda del tipo di programma. Per vedere gli attributi disponibili per ciascun tipo di programma, fai riferimento alle tabelle riportate di seguito.

Inserisci il programma nel provider:

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

Recupera l'ID programma per riferimento futuro:

Kotlin

val programId = ContentUris.parseId(programUri)

Java

long programId = ContentUris.parseId(programUri);

Aggiunta di programmi al canale Guarda in seguito

Per inserire programmi nel canale Guarda in seguito, consulta Aggiungere programmi al canale Guarda successivo.

Aggiornamento di un programma

Puoi modificare le informazioni di un programma. Ad esempio, potresti voler aggiornare il prezzo di noleggio di un film o aggiornare una barra di avanzamento che mostra la durata della visione del programma.

Utilizza PreviewProgram.Builder per impostare gli attributi da modificare, quindi chiama getContentResolver().update per aggiornare il programma. Specifica l'ID programma salvato quando il programma è stato aggiunto inizialmente:

Kotlin

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

Java

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

Eliminazione di un programma

Kotlin

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

Java

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

Gestione delle azioni dell'utente

La tua app può aiutare gli utenti a scoprire contenuti fornendo una UI per visualizzare e aggiungere canali. L'app deve gestire anche le interazioni con i canali dopo che sono visualizzati nella schermata Home.

Scoprire e aggiungere canali

La tua app può fornire un elemento UI che consenta all'utente di selezionare e aggiungere i suoi canali (ad esempio, un pulsante che chiede di aggiungere il canale).

Quando l'utente richiede un canale specifico, esegui questo codice per ottenere l'autorizzazione dell'utente ad aggiungerlo all'interfaccia utente della schermata Home:

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
}

Il sistema visualizza una finestra di dialogo in cui viene chiesto all'utente di approvare il canale. Gestisci il risultato della richiesta nel metodo onActivityResult della tua attività (Activity.RESULT_CANCELED o Activity.RESULT_OK).

Eventi della schermata Home di Android TV

Quando l'utente interagisce con i programmi/canali pubblicati dall'app, la schermata Home invia intent all'app:

  • La schermata Home invia all'app i Uri memorizzati nell'attributo APP_LINK_INTENT_URI di un canale quando l'utente seleziona il logo del canale. L'app dovrebbe semplicemente avviare l'interfaccia utente principale o una visualizzazione relativa al canale selezionato.
  • La schermata Home invia all'app i Uri memorizzati nell'attributo INTENT_URI di un programma quando l'utente seleziona un programma. L'app dovrebbe riprodurre i contenuti selezionati.
  • L'utente può indicare che non è più interessato a un programma e vuole che venga rimosso dall'interfaccia utente della schermata Home. Il sistema rimuove il programma dall'interfaccia utente e invia all'app proprietaria un intent (android.media.tv.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED o android.media.tv.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED) con l'ID del programma. L'app deve rimuovere il programma dal fornitore e NON reinserirlo.

Assicurati di creare filtri per intent per tutti i Uris inviati dalla schermata Home per le interazioni degli utenti, ad esempio:

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

Best practice

  • Molte app per TV richiedono l'accesso degli utenti. In questo caso, l'BroadcastReceiver che ascolta android.media.tv.action.INITIALIZE_PROGRAMS deve suggerire contenuti del canale per gli utenti non autenticati.Ad esempio, l'app può inizialmente mostrare i contenuti migliori o i contenuti attualmente popolari. Dopo che l'utente esegue l'accesso, può mostrare contenuti personalizzati. Questa è una grande opportunità per le app di upsell per gli utenti prima che accedano.
  • Se la tua app non è in primo piano e devi aggiornare un canale o un programma, utilizza JobScheduler per programmare il lavoro (consulta JobScheduler e JobService).
  • Il sistema può revocare le autorizzazioni del provider dell'app se quest'ultima funziona in modo anomalo (ad esempio inviando spam continuamente al provider con dati). Assicurati di eseguire il wrapping del codice che accede al provider con clausole di prova-catch per gestire le eccezioni di sicurezza.
  • Prima di aggiornare programmi e canali, chiedi al fornitore i dati che devi aggiornare e riconciliare i dati. Ad esempio, non è necessario aggiornare un programma che l'utente vuole rimuovere dalla UI. Utilizza un job in background che inserisce/aggiorna i dati nel provider dopo aver eseguito query sui dati esistenti e successivamente richiedendo l'approvazione per i canali. Puoi eseguire questo job all'avvio e ogni volta che l'app deve aggiornarne i dati.

    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
                      }
                  }
              }
    
  • Utilizza URI univoci per tutte le immagini (loghi, icone, immagini di contenuti). Assicurati di utilizzare un URI diverso quando aggiorni un'immagine. Tutte le immagini vengono memorizzate nella cache. Se non cambi l'URI quando cambi l'immagine, continuerà a essere visualizzata la vecchia immagine.

  • Ricorda che le clausole WHERE non sono consentite e le chiamate ai provider con clausole WHERE generano un'eccezione di sicurezza.

Attributi

In questa sezione vengono descritti gli attributi del canale e del programma separatamente.

Attributi del canale

Devi specificare i seguenti attributi per ogni canale:

Attributo Notes
TIPO impostato su TYPE_PREVIEW.
DISPLAY_NAME sul nome del canale.
APP_LINK_INTENT_URI Quando l'utente seleziona il logo del canale, il sistema invia l'intenzione di avviare un'attività che presenta contenuti pertinenti per il canale. Imposta questo attributo sull'URI utilizzato nel filtro per intent per l'attività in questione.

Inoltre, un canale dispone di sei campi riservati all'uso interno delle app. Questi campi possono essere utilizzati per archiviare chiavi o altri valori che possono aiutare l'app a mappare il canale alla struttura di dati interna:

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

Attributi del programma

Consulta le singole pagine degli attributi per ciascun tipo di programma:

Codice di esempio

Per ulteriori informazioni sulla creazione di app che interagiscono con la schermata Home e aggiungono canali e programmi alla schermata Home di Android TV, consulta il nostro codelab sulla schermata Home.