Input TV Anda harus memberikan data Panduan Program Elektronik (EPG) untuk minimal satu saluran dalam aktivitas penyiapannya. Anda juga harus memperbarui data tersebut secara berkala, dengan pertimbangan untuk ukuran pembaruan dan thread pemrosesan yang menanganinya. Selain itu, Anda dapat memberikan link aplikasi untuk saluran yang memandu pengguna ke konten dan aktivitas terkait. Tutorial ini membahas cara membuat dan memperbarui data saluran dan program pada database sistem dengan mempertimbangkan pertimbangan ini.
Coba aplikasi contoh Layanan Input TV.
Mendapatkan izin
Agar input TV Anda berfungsi dengan data EPG, input TV harus mendeklarasikan izin tulis dalam file manifes Android sebagai berikut:
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
Mendaftarkan saluran dalam database
Database sistem Android TV menyimpan catatan data saluran untuk input TV. Dalam aktivitas penyiapan, untuk setiap saluran, Anda harus memetakan data saluran ke kolom class TvContract.Channels
.
COLUMN_DISPLAY_NAME
- nama saluran yang ditampilkanCOLUMN_DISPLAY_NUMBER
- nomor saluran yang ditampilkanCOLUMN_INPUT_ID
- ID layanan input TVCOLUMN_SERVICE_TYPE
- jenis layanan saluranCOLUMN_TYPE
- jenis standar siaran saluranCOLUMN_VIDEO_FORMAT
- format video default untuk saluran
Meskipun framework input TV cukup umum untuk menangani konten siaran tradisional dan over-the-top (OTT) tanpa perbedaan apa pun, ada baiknya kalau Anda menentukan kolom berikut selain yang di atas untuk mengidentifikasi saluran siaran tradisional dengan lebih optimal:
COLUMN_ORIGINAL_NETWORK_ID
- ID jaringan televisiCOLUMN_SERVICE_ID
- ID layananCOLUMN_TRANSPORT_STREAM_ID
- ID streaming transpor
Jika ingin memberikan detail link aplikasi untuk saluran Anda, Anda perlu memperbarui beberapa kolom tambahan. Untuk informasi selengkapnya mengenai kolom link, lihat Menambahkan informasi link aplikasi.
Untuk input TV berbasis streaming internet, tetapkan nilai Anda sendiri dengan yang sesuai di atas sehingga setiap saluran dapat diidentifikasi secara unik.
Tarik metadata saluran Anda (dalam XML, JSON, atau apa pun) dari server backend, dan dalam aktivitas penyiapan petakan nilainya ke database sistem sebagai berikut:
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);
Pada contoh di atas, channel
adalah objek yang menyimpan metadata saluran dari server backend.
Menyajikan informasi saluran dan program
Aplikasi TV sistem menyajikan informasi saluran dan program kepada pengguna saat mereka beralih melalui saluran, seperti yang ditunjukkan pada gambar 1. Untuk memastikan informasi saluran dan program berfungsi dengan presenter informasi saluran dan program aplikasi TV sistem, ikuti panduan di bawah ini.
- Nomor saluran (
COLUMN_DISPLAY_NUMBER
) - Ikon (
android:icon
dalam manifes input TV) - Deskripsi program (
COLUMN_SHORT_DESCRIPTION
) - Judul program (
COLUMN_TITLE
) - Logo saluran (
TvContract.Channels.Logo
)- Gunakan warna #EEEEEE untuk mencocokkan teks di sekitarnya
- Jangan sertakan padding
- Seni poster (
COLUMN_POSTER_ART_URI
)- Rasio tinggi lebar antara 16:9 dan 4:3

Gambar 1. Saluran aplikasi TV sistem dan presenter informasi program.
Aplikasi TV sistem menyediakan informasi yang sama melalui panduan program, termasuk seni poster, seperti yang ditunjukkan pada gambar 2.

Gambar 2. Panduan program aplikasi TV sistem.
Memperbarui data saluran
Saat memperbarui data saluran yang ada, gunakan metode update()
sebagai ganti dari menghapus dan menambahkan kembali data. Anda dapat mengidentifikasi versi data saat ini dengan menggunakan Channels.COLUMN_VERSION_NUMBER
dan Programs.COLUMN_VERSION_NUMBER
saat memilih catatan untuk diperbarui.
Catatan: Menambahkan data saluran ke ContentProvider
dapat memerlukan waktu. Tambahkan program saat ini (dalam waktu dua jam dari waktu saat ini) hanya saat Anda mengonfigurasi EpgSyncJobService
untuk memperbarui sisa data saluran di latar belakang. Lihat Aplikasi contoh TV Live Android TV untuk contohnya.
Mem-batch data saluran pemuatan
Saat memperbarui database sistem dengan sejumlah besar data saluran, gunakan metode ContentResolver
, applyBatch()
, atau bulkInsert()
. Berikut ini contoh yang menggunakan 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(); } }
Memproses data saluran secara asinkron
Manipulasi data, seperti mengambil aliran data dari server atau mengakses database, tidak boleh memblokir UI thread. Menggunakan AsyncTask
adalah satu cara untuk melakukan pembaruan secara asinkron. Misalnya, saat memuat info saluran dari server backend, Anda dapat menggunakan AsyncTask
sebagai berikut:
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(); } } } }
Jika Anda perlu memperbarui data EPG secara teratur, pertimbangkan menggunakan WorkManager
untuk menjalankan proses pembaruan selama waktu tidak ada aktivitas, seperti setiap hari pada pukul 03.00 pagi.
Teknik lain untuk memisahkan tugas pembaruan data dari UI thread termasuk menggunakan class HandlerThread
, atau Anda dapat mengimplementasikan class Anda sendiri menggunakan class Looper
dan Handler
. Lihat Proses dan thread untuk informasi selengkapnya.
Menambahkan informasi link aplikasi
Saluran dapat menggunakan link aplikasi untuk memungkinkan pengguna meluncurkan dengan mudah aktivitas terkait saat mereka menonton konten saluran. Aplikasi saluran menggunakan link aplikasi untuk memperluas interaksi pengguna dengan meluncurkan aktivitas yang menampilkan informasi terkait atau konten tambahan. Misalnya, Anda dapat menggunakan link aplikasi untuk melakukan hal ini:
- Memandu pengguna untuk menemukan dan membeli konten terkait.
- Memberikan informasi tambahan tentang konten yang sedang diputar.
- Saat melihat konten episodik, mulailah melihat episode berikutnya dalam sebuah serial.
- Membiarkan pengguna berinteraksi dengan konten—misalnya, memberi rating atau meninjau konten—tanpa mengganggu pemutaran konten.
Link aplikasi ditampilkan saat pengguna menekan Pilih untuk menampilkan menu TV saat menonton konten saluran.

Gambar 1. Contoh link aplikasi ditampilkan pada baris Saluran saat konten saluran ditampilkan.
Saat pengguna memilih link aplikasi, sistem akan memulai aktivitas menggunakan URI intent yang ditentukan oleh aplikasi saluran. Konten saluran akan terus diputar saat aktivitas link aplikasi aktif. Pengguna dapat menampilkan ke konten saluran dengan menekan Kembali.
Memberikan data saluran link aplikasi
Android TV otomatis membuat link aplikasi untuk setiap saluran menggunakan informasi dari data saluran. Untuk memberikan informasi link aplikasi, tentukan detail berikut dalam kolom TvContract.Channels
.
COLUMN_APP_LINK_COLOR
- Warna aksen link aplikasi untuk saluran ini. Untuk contoh warna aksen, lihat gambar 2, keterangan 3.COLUMN_APP_LINK_ICON_URI
- URI untuk ikon badge aplikasi dari link aplikasi untuk saluran ini. Untuk contoh ikon badge aplikasi, lihat gambar 2, keterangan 2.COLUMN_APP_LINK_INTENT_URI
- URI intent link aplikasi untuk saluran ini. Anda dapat membuat URI menggunakantoUri(int)
denganURI_INTENT_SCHEME
dan mengonversi URI kembali ke intent asli denganparseUri()
.COLUMN_APP_LINK_POSTER_ART_URI
- URI untuk seni poster digunakan sebagai latar belakang link aplikasi untuk saluran ini. Untuk contoh gambar poster, lihat gambar 2, keterangan 1.COLUMN_APP_LINK_TEXT
- Teks link deskriptif dari link aplikasi untuk saluran ini. Untuk contoh deskripsi link aplikasi, lihat teks dalam gambar 2, keterangan 3.

Gambar 2. Detail link aplikasi.
Jika data saluran tidak menentukan informasi link aplikasi, sistem akan membuat link aplikasi default. Sistem akan memilih detail default seperti berikut:
- Untuk URI intent (
COLUMN_APP_LINK_INTENT_URI
), sistem menggunakan aktivitasACTION_MAIN
untuk kategoriCATEGORY_LEANBACK_LAUNCHER
, biasanya ditentukan dalam manifes aplikasi. Jika aktivitas ini tidak ditentukan, link aplikasi yang tidak berfungsi akan muncul—jika pengguna mengkliknya, tidak ada pengaruhnya. - Untuk teks deskriptif (
COLUMN_APP_LINK_TEXT
), sistem menggunakan "Buka app-name". Jika tidak ada URI intent link aplikasi yang memadai yang ditentukan, sistem akan menggunakan "Tidak ada link yang tersedia". - Untuk warna aksen (
COLUMN_APP_LINK_COLOR
), sistem menggunakan warna aplikasi default. - Untuk gambar poster (
COLUMN_APP_LINK_POSTER_ART_URI
), sistem menggunakan banner layar utama aplikasi. Jika aplikasi tidak menyediakan banner, sistem menggunakan gambar aplikasi TV default. - Untuk ikon badge (
COLUMN_APP_LINK_ICON_URI
), sistem menggunakan badge yang menampilkan nama aplikasi. Jika sistem juga menggunakan banner aplikasi atau gambar aplikasi default untuk gambar poster, tidak ada badge aplikasi yang ditampilkan.
Anda menentukan detail link aplikasi untuk saluran pada aktivitas penyiapan aplikasi Anda. Anda dapat memperbarui detail link aplikasi ini kapan saja, jadi jika link aplikasi perlu mencocokkan perubahan saluran, perbarui detail link aplikasi dan panggil ContentResolver.update()
yang diperlukan. Untuk mengetahui detail selengkapnya mengenai memperbarui data saluran, lihat Memperbarui data saluran.