L'ingresso TV deve fornire dati EPG (Electronic Program Guide) per almeno un canale nella sua attività di configurazione. Devi inoltre aggiornare periodicamente di dati, tenendo conto delle dimensioni dell'aggiornamento e del thread di elaborazione che li gestisce. Inoltre, puoi fornire link dell'app per i canali che indirizzano l'utente verso contenuti e attività correlati. Questa lezione illustra la creazione e l'aggiornamento dei dati del canale e del programma sulla di sistema tenendo a mente queste considerazioni.
Prova App di esempio del servizio di input TV.
Autorizza
Affinché l'ingresso TV funzioni con i dati EPG, deve dichiarare il valore l'autorizzazione di scrittura nel relativo file manifest Android, in questo modo:
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
Registra canali nel database
Il database del sistema Android TV conserva i record dei dati dei canali per gli ingressi della TV. Nella configurazione
attività, per ciascuno dei tuoi canali, devi mappare i dati dei canali ai seguenti campi del
TvContract.Channels
corso:
COLUMN_DISPLAY_NAME
: il nome visualizzato dell'account canaleCOLUMN_DISPLAY_NUMBER
: il canale visualizzato numeroCOLUMN_INPUT_ID
: l'ID del servizio di ingresso TVCOLUMN_SERVICE_TYPE
: il tipo di servizio del canaleCOLUMN_TYPE
: lo standard di trasmissione del canale tipoCOLUMN_VIDEO_FORMAT
: il formato video predefinito per il canale
Sebbene il framework di input della TV sia abbastanza generico da gestire sia i sistemi di trasmissione tradizionali contenuti over-the-top (OTT) senza alcuna distinzione, ti consigliamo di definire le seguenti colonne in oltre a quelli elencati sopra per identificare meglio i canali televisivi tradizionali:
COLUMN_ORIGINAL_NETWORK_ID
- la televisione ID reteCOLUMN_SERVICE_ID
: l'ID servizioCOLUMN_TRANSPORT_STREAM_ID
: il flusso di trasporto ID
Se vuoi fornire i dettagli dei link dell'app per i tuoi canali, devi: aggiorna alcuni campi aggiuntivi. Per ulteriori informazioni sui campi dei link dell'app, consulta Aggiungi informazioni sul link dell'app.
Per gli ingressi TV basati su streaming internet, assegna i tuoi valori a quanto sopra in modo che ciascun canale può essere identificato in modo univoco.
Estrai i metadati del canale (in XML, JSON o altro) dal tuo server di backend e nella tua configurazione l'attività mappa i valori al database di sistema come segue:
Kotlin
val values = ContentValues().apply { put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, channel.number) put(TvContract.Channels.COLUMN_DISPLAY_NAME, channel.name) put(TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID, channel.originalNetworkId) put(TvContract.Channels.COLUMN_TRANSPORT_STREAM_ID, channel.transportStreamId) put(TvContract.Channels.COLUMN_SERVICE_ID, channel.serviceId) put(TvContract.Channels.COLUMN_VIDEO_FORMAT, channel.videoFormat) } val uri = context.contentResolver.insert(TvContract.Channels.CONTENT_URI, values)
Java
ContentValues values = new ContentValues(); values.put(Channels.COLUMN_DISPLAY_NUMBER, channel.number); values.put(Channels.COLUMN_DISPLAY_NAME, channel.name); values.put(Channels.COLUMN_ORIGINAL_NETWORK_ID, channel.originalNetworkId); values.put(Channels.COLUMN_TRANSPORT_STREAM_ID, channel.transportStreamId); values.put(Channels.COLUMN_SERVICE_ID, channel.serviceId); values.put(Channels.COLUMN_VIDEO_FORMAT, channel.videoFormat); Uri uri = context.getContentResolver().insert(TvContract.Channels.CONTENT_URI, values);
Nell'esempio precedente, channel
è un oggetto che contiene i metadati del canale
di backend.
Presentare informazioni sul canale e sul programma
L'app TV di sistema mostra informazioni su canali e programmi agli utenti mentre esplorano i canali. come mostrato nella Figura 1. Per assicurarti che le informazioni sul canale e sul programma siano compatibili con il set di dati dell'app di sistema per la TV presentatore delle informazioni sul canale e sul programma segui le linee guida riportate di seguito.
- Numero del canale (
COLUMN_DISPLAY_NUMBER
) - Icona
(
android:icon
nel manifest dell'input TV) - Descrizione del programma (
COLUMN_SHORT_DESCRIPTION
) - Titolo del programma (
COLUMN_TITLE
) - Logo del canale (
TvContract.Channels.Logo
)- Utilizza il colore #EEEEEE per abbinarlo al testo circostante
- Non includere spaziatura interna
- Locandina (
COLUMN_POSTER_ART_URI
)- Proporzioni tra 16:9 e 4:3
L'app TV di sistema fornisce le stesse informazioni nella guida ai programmi, comprese locandina, come mostrato nella Figura 2.
Aggiornare i dati del canale
Quando aggiorni i dati dei canali esistenti, utilizza
update()
anziché eliminare e aggiungere nuovamente i dati. Puoi identificare la versione attuale dei dati
utilizzando Channels.COLUMN_VERSION_NUMBER
e Programs.COLUMN_VERSION_NUMBER
quando si scelgono i record da aggiornare.
Nota: aggiungi i dati del canale a ContentProvider
può richiedere tempo. Aggiungere i programmi attuali (entro due ore dall'ora corrente)
solo quando configuri EpgSyncJobService
per aggiornare il resto
dei dati del canale in background. Consulta
Esempio dell'app Android TV Live TV.
Caricamento in batch dei dati dei canali
Quando aggiorni il database di sistema con una grande quantità di dati di canali, utilizza ContentResolver
applyBatch()
o
bulkInsert()
. Ecco un esempio in cui viene utilizzato applyBatch()
:
Kotlin
val ops = ArrayList<ContentProviderOperation>() val programsCount = channelInfo.mPrograms.size channelInfo.mPrograms.forEachIndexed { index, program -> ops += ContentProviderOperation.newInsert( TvContract.Programs.CONTENT_URI).run { withValues(programs[index]) withValue(TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, programStartSec * 1000) withValue( TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, (programStartSec + program.durationSec) * 1000 ) build() } programStartSec += program.durationSec if (index % 100 == 99 || index == programsCount - 1) { try { contentResolver.applyBatch(TvContract.AUTHORITY, ops) } catch (e: RemoteException) { Log.e(TAG, "Failed to insert programs.", e) return } catch (e: OperationApplicationException) { Log.e(TAG, "Failed to insert programs.", e) return } ops.clear() } }
Java
ArrayList<ContentProviderOperation> ops = new ArrayList<>(); int programsCount = channelInfo.mPrograms.size(); for (int j = 0; j < programsCount; ++j) { ProgramInfo program = channelInfo.mPrograms.get(j); ops.add(ContentProviderOperation.newInsert( TvContract.Programs.CONTENT_URI) .withValues(programs.get(j)) .withValue(Programs.COLUMN_START_TIME_UTC_MILLIS, programStartSec * 1000) .withValue(Programs.COLUMN_END_TIME_UTC_MILLIS, (programStartSec + program.durationSec) * 1000) .build()); programStartSec = programStartSec + program.durationSec; if (j % 100 == 99 || j == programsCount - 1) { try { getContentResolver().applyBatch(TvContract.AUTHORITY, ops); } catch (RemoteException | OperationApplicationException e) { Log.e(TAG, "Failed to insert programs.", e); return; } ops.clear(); } }
Elabora i dati dei canali in modo asincrono
La manipolazione dei dati, come il recupero di un flusso dal server o l'accesso al database,
non bloccano il thread dell'interfaccia utente. Utilizzare AsyncTask
è uno
eseguire aggiornamenti in modo asincrono. Ad esempio, quando carichi informazioni sul canale da un server di backend,
puoi usare AsyncTask
nel seguente modo:
Kotlin
private class LoadTvInputTask(val context: Context) : AsyncTask<Uri, Unit, Unit>() { override fun doInBackground(vararg uris: Uri) { try { fetchUri(uris[0]) } catch (e: IOException) { Log.d("LoadTvInputTask", "fetchUri error") } } @Throws(IOException::class) private fun fetchUri(videoUri: Uri) { context.contentResolver.openInputStream(videoUri).use { inputStream -> Xml.newPullParser().also { parser -> try { parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false) parser.setInput(inputStream, null) sTvInput = ChannelXMLParser.parseTvInput(parser) sSampleChannels = ChannelXMLParser.parseChannelXML(parser) } catch (e: XmlPullParserException) { e.printStackTrace() } } } } }
Java
private static class LoadTvInputTask extends AsyncTask<Uri, Void, Void> { private Context mContext; public LoadTvInputTask(Context context) { mContext = context; } @Override protected Void doInBackground(Uri... uris) { try { fetchUri(uris[0]); } catch (IOException e) { Log.d("LoadTvInputTask", "fetchUri error"); } return null; } private void fetchUri(Uri videoUri) throws IOException { InputStream inputStream = null; try { inputStream = mContext.getContentResolver().openInputStream(videoUri); XmlPullParser parser = Xml.newPullParser(); try { parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); parser.setInput(inputStream, null); sTvInput = ChannelXMLParser.parseTvInput(parser); sSampleChannels = ChannelXMLParser.parseChannelXML(parser); } catch (XmlPullParserException e) { e.printStackTrace(); } } finally { if (inputStream != null) { inputStream.close(); } } } }
Se hai bisogno di aggiornare regolarmente i dati EPG,
WorkManager
eseguire il processo di aggiornamento durante il tempo di inattività, ad esempio ogni giorno alle 3:00
Altre tecniche per separare le attività di aggiornamento dei dati dal thread dell'interfaccia utente includono l'utilizzo
HandlerThread
o puoi implementarne una personalizzata utilizzando Looper
e Handler
corsi. Vedi
Processi e thread per ulteriori informazioni.
Aggiungi informazioni sul link dell'app
I canali possono utilizzare i link alle app per consentire agli utenti di avviare facilmente un all'attività durante la visione dei contenuti del canale. Utilizzo da parte delle app del canale link alle app per aumentare il coinvolgimento degli utenti avviando attività che mostrano informazioni correlate o contenuti aggiuntivi. Ad esempio, puoi usare i link dell'app effettuare le seguenti operazioni:
- Guida l'utente a scoprire e acquistare contenuti correlati.
- Fornisci ulteriori informazioni sui contenuti attualmente in riproduzione.
- Mentre guardi i contenuti a episodi, inizia a guardare la puntata successiva in un Google Cloud.
- Consentire all'utente di interagire con i contenuti, ad esempio valutando o recensisci senza interrompere la riproduzione.
I link dell'app vengono mostrati quando l'utente preme Seleziona per visualizzare Menu della TV mentre guardi i contenuti del canale.
Quando l'utente seleziona il link all'app, il sistema avvia un'attività utilizzando un URI di intent specificato dall'app del canale. La riproduzione dei contenuti del canale continua mentre l'attività di link dell'app è attiva. L'utente può tornare al canale contenuti premendo Indietro.
Fornisci i dati dei canali per il collegamento dell'app
Android TV crea automaticamente un link all'app per ogni canale
utilizzando le informazioni provenienti dai dati del canale. Per fornire informazioni sui link dell'app,
specificare i seguenti dettagli
TvContract.Channels
campi:
COLUMN_APP_LINK_COLOR
- Il colore intenso del link dell'app di questo canale. Per un esempio di colore intenso, vedi la figura 2, callout 3.COLUMN_APP_LINK_ICON_URI
- L'URI dell'icona del badge dell'app del link dell'app di questo canale. Per un esempio di icona del badge dell'app; vedi figura 2, callout 2.COLUMN_APP_LINK_INTENT_URI
- L'URI intent del link dell'app per questo canale. Puoi creare l'URI utilizzatoUri(int)
conURI_INTENT_SCHEME
e converti l'URI all'intent originale conparseUri()
.COLUMN_APP_LINK_POSTER_ART_URI
- L'URI della locandina utilizzata come sfondo del link dell'app per questo canale. Per un esempio di immagine poster, vedi figura 2, callout 1.COLUMN_APP_LINK_TEXT
- Il testo descrittivo del link dell'app per questo canale. Ad esempio, descrizione del link dell'app, vedi il testo nella figura 2, callout 3.
Se i dati del canale non specificano informazioni sui link dell'app, il sistema crea un link all'app predefinito. Il sistema sceglie i dettagli predefiniti nel seguente modo:
- Per l'URI intent
(
COLUMN_APP_LINK_INTENT_URI
), il sistema utilizzaACTION_MAIN
attività per la categoriaCATEGORY_LEANBACK_LAUNCHER
, solitamente definita nel file manifest dell'app. Se questa attività non è definita, viene visualizzato un link di app non funzionante, se l'utente fa clic su di esso, non accade nulla. - Per il testo descrittivo
(
COLUMN_APP_LINK_TEXT
), il sistema utilizza "Apri app-name". Se non è stato definito alcun URI di intent del link dell'app utilizzabile, il sistema utilizza "Nessun link disponibile". - Per il colore di contrasto
(
COLUMN_APP_LINK_COLOR
), il sistema utilizza il colore predefinito dell'app. - Per l'immagine poster
(
COLUMN_APP_LINK_POSTER_ART_URI
), Il sistema utilizza il banner della schermata Home dell'app. Se l'app non fornisce un banner, il sistema utilizza un'immagine predefinita dell'app TV. - Per l'icona del badge
(
COLUMN_APP_LINK_ICON_URI
), usa un badge che mostra il nome dell'app. Se il sistema utilizza anche banner dell'app o immagine dell'app predefinita per l'immagine poster, non viene mostrato alcun badge dell'app.
Devi specificare i dettagli dei link dell'app per i tuoi canali nella sezione
attività di configurazione. Puoi aggiornare questi dettagli dei link all'app in qualsiasi momento, quindi
Se il link di un'app deve corrispondere alle modifiche al canale, aggiorna l'app
dettagli del collegamento e chiamata
ContentResolver.update()
secondo necessità. Per ulteriori dettagli sull'aggiornamento
Consulta i dati dei canali Aggiornare i dati dei canali.