Canali nella schermata Home

La schermata Home di Android TV fornisce un'interfaccia utente che mostra i contenuti consigliati come una tabella di canali e programmi. Ogni riga è un canale. Un canale contiene schede per ogni programma disponibile su quel canale:

Schermata Home di Android TV
Schermata Home di Android TV

Questo documento mostra come aggiungere canali e programmi alla schermata Home, aggiornare i contenuti, gestire le azioni dell'utente e offrire la migliore esperienza ai tuoi utenti. (Se vuoi approfondire l'API, prova il codelab della schermata Home e guarda la sessione di Android TV di I/O 2017)

L'interfaccia utente della schermata Home

Le app possono creare nuovi canali, aggiungere, rimuovere e aggiornare i programmi in un canale e controllare l'ordine dei programmi in un canale. Ad esempio, un'app può creare un canale chiamato "Novità" e mostrare schede per i programmi appena disponibili.

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

Il canale Cosa guardare

Il canale Cosa guardare è la seconda riga che viene visualizzata nella schermata Home, dopo la riga delle app. Il sistema crea e gestisce questo canale. La tua app può aggiungere programmi al canale Cosa guardare. Per ulteriori informazioni, vedi Aggiungere programmi a il canale Cosa guardare.

Canali app

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

  1. L'utente scopre un canale nella tua app e richiede 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

La tua app può offrire un numero qualsiasi di canali che l'utente può aggiungere alla schermata Home. In genere, l'utente deve selezionare e approvare ogni canale prima che venga visualizzato nella schermata Home. Ogni app ha la possibilità di creare un canale predefinito. Il canale predefinito è speciale perché viene visualizzato 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 provider, aggiungi la seguente autorizzazione al manifest dell'app:

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

La libreria di supporto TvProvider semplifica l'utilizzo del provider. Aggiungila alle dipendenze nel file build.gradle:

Alla moda

implementation 'androidx.tvprovider:tvprovider:1.0.0'

Kotlin

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

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

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 suo canale predefinito. Il canale predefinito viene visualizzato automaticamente nella schermata Home. Tutti gli altri canali creati devono essere selezionati e accettati dall'utente prima di poter essere visualizzati nella schermata Home.

Creazione di un canale

L'app deve chiedere al sistema di mostrare i canali appena aggiunti solo quando è in esecuzione in primo piano. In questo modo, l'app non visualizzerà una finestra di dialogo che richiede l'approvazione per aggiungere il canale mentre l'utente sta eseguendo un'altra app. Se provi ad aggiungere un canale mentre è in esecuzione in background, il metodo onActivityResult() dell'attività restituisce il codice di stato RESULT_CANCELED.

Per creare un canale:

  1. Crea un generatore di canali e imposta i relativi attributi. Tieni presente che il tipo di canale deve essere TYPE_PREVIEW. Aggiungi altri attributi in base alle esigenze.

    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 i 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 di 80 dp x 80 dp e deve essere opaca. Viene visualizzata sotto una maschera circolare:

    Maschera dell'icona della schermata Home 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. Crea il canale predefinito (facoltativo): quando la tua app crea il suo primo canale, puoi impostarlo come canale predefinito in modo che venga visualizzato immediatamente nella schermata Home senza alcuna azione dell'utente. Gli altri canali creati non sono visibili finché l'utente non li seleziona esplicitamente.

    Kotlin

    TvContractCompat.requestChannelBrowsable(context, channelId)
    

    Java

    TvContractCompat.requestChannelBrowsable(context, channelId);
    
  6. Fai in modo che il canale predefinito venga visualizzato prima dell'apertura dell'app. Puoi ottenere questo comportamento aggiungendo un BroadcastReceiver che ascolta 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 dell'app durante lo sviluppo, puoi testare questo passaggio attivando l'intent tramite adb, dove your.package.name/.YourReceiverName è il BroadcastReceiver della tua app:

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

    In rari casi, l'app potrebbe ricevere la trasmissione contemporaneamente all'avvio dell'app da parte dell'utente. Assicurati che il codice non tenti di aggiungere il canale predefinito più di una volta.

Aggiornamento di un canale

L'aggiornamento dei canali è molto simile alla loro creazione.

Utilizza un altro Channel.Builder per impostare gli attributi da modificare.

Utilizza ContentResolver per aggiornare il canale. Utilizza l'ID canale che hai salvato quando il canale è stato aggiunto originariamente:

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

I programmi sono le singole schede di contenuti visualizzate all'interno di un canale. Puoi pubblicare programmi sia sui canali personalizzati della tua app sia sul canale Cosa guardare gestito dal sistema.

Aggiunta di programmi a un canale 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 visualizzare gli attributi disponibili per ogni tipo di programma, consulta le tabelle 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 Cosa guardare

Per inserire i programmi nel canale Cosa guardare, vedi Aggiungere programmi al canale Cosa guardare.

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 quantità di un programma che l'utente ha guardato.

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

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 i contenuti fornendo un'interfaccia utente per visualizzare e aggiungere canali. La tua app deve anche gestire le interazioni con i tuoi canali dopo che vengono visualizzati nella schermata Home.

Scoperta e aggiunta di canali

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

Dopo che l'utente ha richiesto 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 che chiede 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 e i canali pubblicati dall'app, la schermata Home invia intent all'app:

  • La schermata Home invia l'Uri memorizzato nell'attributo APP_LINK_INTENT_URI di un canale all'app quando l'utente seleziona il logo del canale. L'app deve semplicemente avviare l'interfaccia utente principale o una visualizzazione correlata al canale selezionato.
  • La schermata Home invia l'Uri memorizzato nell'attributo INTENT_URI di un programma all'app quando l'utente seleziona un programma. L'app deve riprodurre i contenuti selezionati.
  • L'utente può indicare di non essere più interessato a un programma e di volerlo rimuovere dall'interfaccia utente della schermata Home. Il sistema rimuove il programma dall'interfaccia utente e invia all'app proprietaria del programma 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 provider e NON deve reinserirlo.

Assicurati di creare filtri per intent per tutti gli Uris che la schermata Home invia per le interazioni dell'utente, 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>

Considerazioni aggiuntive

  • Molte app TV richiedono agli utenti di accedere. In questo caso, il 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 più popolari. Dopo che l'utente ha eseguito l'accesso, può mostrare contenuti personalizzati. Questa è un'ottima opportunità per le app di eseguire l'upselling degli utenti prima che accedano.
  • Quando l'app non è in primo piano e devi aggiornare un canale o un programma, utilizza JobScheduler per pianificare il lavoro (vedi JobScheduler e JobService).
  • Il sistema può revocare le autorizzazioni del provider della tua app se l'app si comporta in modo improprio (ad esempio, inviando continuamente spam al provider con i dati). Assicurati di racchiudere il codice che accede al provider con clausole try-catch per gestire le eccezioni di sicurezza.
  • Prima di aggiornare i programmi e i canali, esegui una query sul provider per i dati da aggiornare e riconcilia i dati. Ad esempio, non è necessario aggiornare un programma che l'utente vuole rimuovere dall'interfaccia utente. Utilizza un job in background che inserisce o aggiorna i dati nel provider dopo aver eseguito una query sui dati esistenti e aver richiesto l'approvazione per i tuoi canali. Puoi eseguire questo job all'avvio dell'app e ogni volta che l'app deve aggiornare i suoi 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 &amp;&amp; cursor.moveToNext()) {
                      Channel channel = Channel.fromCursor(cursor);
                      if (channel.isBrowsable()) {
                          //update channel's programs
                      }
                  }
              }
  • Utilizza Uri univoci per tutte le immagini (loghi, icone, immagini dei contenuti). Assicurati di utilizzare un Uri diverso quando aggiorni un'immagine. Tutte le immagini vengono memorizzate nella cache. Se non modifichi l'Uri quando modifichi l'immagine, continuerà a essere visualizzata l'immagine precedente.

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

Attributi

Questa sezione descrive separatamente gli attributi di canale e programma.

Attributi del canale

Devi specificare questi attributi per ogni canale:

Attributo Note
TIPO Imposta su TYPE_PREVIEW.
DISPLAY_NAME Imposta sul nome del canale.
APP_LINK_INTENT_URI Quando l'utente seleziona il logo del canale, il sistema invia un intent per avviare un'attività che presenta contenuti pertinenti al canale. Imposta questo attributo sull'Uri utilizzato nel filtro per intent per questa attività.

Inoltre, un canale ha anche sei campi riservati all'utilizzo interno dell'app. Questi campi possono essere utilizzati per memorizzare chiavi o altri valori che possono aiutare l'app a mappare il canale alla sua 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 per gli attributi di ogni tipo di programma:

Codice di esempio

Per saperne di più sulla creazione di app che interagiscono con la schermata Home e sull'aggiunta di canali e programmi alla schermata Home di Android TV, consulta il nostro codelab della schermata Home .