Input TV Anda harus memberikan data Panduan Program Elektronik (EPG) minimal satu saluran dalam aktivitas penyiapannya. Anda juga harus secara berkala memperbarui data, dengan pertimbangan ukuran update dan thread pemrosesan yang menanganinya. Selain itu, Anda dapat memberikan link aplikasi untuk saluran yang memandu pengguna ke konten dan aktivitas terkait. Pelajaran ini membahas cara membuat dan memperbarui data saluran dan program di {i>database<i} sistem dengan mempertimbangkan hal ini.
Cobalah 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-nya seperti 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. Di penyiapan Anda
untuk setiap saluran, Anda harus memetakan data saluran ke bidang
Class TvContract.Channels
:
COLUMN_DISPLAY_NAME
- nama yang ditampilkan saluranCOLUMN_DISPLAY_NUMBER
- saluran yang ditampilkan angkaCOLUMN_INPUT_ID
- ID layanan input TVCOLUMN_SERVICE_TYPE
- jenis layanan saluranCOLUMN_TYPE
- standar siaran channel (jenisCOLUMN_VIDEO_FORMAT
- format video default untuk channel
Meskipun kerangka kerja {i>input<i} TV cukup umum untuk menangani siaran tradisional dan konten over-the-top (OTT) tanpa perbedaan apa pun, Anda dapat menentukan kolom berikut di tambahan yang disebutkan di atas untuk mengidentifikasi saluran siaran tradisional dengan lebih baik:
COLUMN_ORIGINAL_NETWORK_ID
- televisi ID jaringanCOLUMN_SERVICE_ID
- ID layananCOLUMN_TRANSPORT_STREAM_ID
- feed transpor ID
Jika ingin memberikan detail link aplikasi untuk channel Anda, Anda harus memperbarui beberapa kolom tambahan. Untuk informasi selengkapnya tentang kolom link aplikasi, lihat Tambahkan informasi link aplikasi.
Untuk input TV berbasis streaming internet, tetapkan nilai Anda sendiri ke nilai di atas sehingga setiap saluran dapat diidentifikasi secara unik.
Ambil metadata saluran Anda (dalam XML, JSON, atau apa pun) dari server backend, lalu dalam penyiapan Anda memetakan nilai 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 yang ada di sistem menyajikan informasi saluran dan program kepada pengguna saat mereka beralih saluran, seperti yang ditunjukkan pada gambar 1. Untuk memastikan informasi saluran dan program berfungsi dengan aplikasi TV sistem {i>channel<i} dan presenter informasi program, ikuti pedoman di bawah ini.
- Nomor saluran (
COLUMN_DISPLAY_NUMBER
) - Ikon
(
android:icon
di Manifes input TV) - Deskripsi program (
COLUMN_SHORT_DESCRIPTION
) - Judul program (
COLUMN_TITLE
) - Logo channel (
TvContract.Channels.Logo
)- Gunakan warna #EEEEEE untuk mencocokkan teks di sekitarnya
- Jangan sertakan padding
- Seni poster (
COLUMN_POSTER_ART_URI
)- Rasio lebar tinggi antara 16:9 dan 4:3
Aplikasi TV sistem menyediakan informasi yang sama melalui panduan program, termasuk gambar poster, seperti yang ditunjukkan pada gambar 2.
Memperbarui data saluran
Saat memperbarui data saluran yang ada, gunakan
update()
alih-alih menghapus dan menambahkan kembali data. Anda dapat mengidentifikasi versi data saat ini
dengan menggunakan Channels.COLUMN_VERSION_NUMBER
dan Programs.COLUMN_VERSION_NUMBER
ketika memilih catatan yang akan diperbarui.
Catatan: Menambahkan data saluran ke ContentProvider
bisa memakan waktu. Menambahkan program saat ini (program dalam waktu dua jam dari waktu saat ini)
hanya jika Anda mengonfigurasi EpgSyncJobService
untuk memperbarui sisanya
data saluran di latar belakang. Lihat
Aplikasi Contoh Android TV Live TV sebagai contoh.
Mem-batch data saluran pemuatan
Saat memperbarui database sistem dengan data saluran dalam jumlah besar, gunakan 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
dari server atau mengakses {i>database<i}, harus
tidak memblokir UI thread. Menggunakan AsyncTask
adalah salah satu
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 rutin, pertimbangkan untuk menggunakan
WorkManager
untuk menjalankan proses update 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
HandlerThread
, atau Anda dapat menerapkan class Anda sendiri menggunakan Looper
dan Handler
. Lihat
Proses dan thread untuk mengetahui informasi selengkapnya.
Menambahkan informasi link aplikasi
Saluran dapat menggunakan link aplikasi untuk memudahkan pengguna meluncurkan aplikasi terkait aktivitas saat mereka menonton konten saluran. Aplikasi saluran menggunakan link aplikasi untuk memperluas interaksi pengguna dengan meluncurkan aktivitas yang menunjukkan informasi terkait atau konten tambahan. Misalnya, Anda dapat menggunakan link aplikasi untuk melakukan hal berikut:
- Memandu pengguna untuk menemukan dan membeli konten terkait.
- Memberikan informasi tambahan tentang konten yang sedang diputar.
- Saat melihat konten berepisode, mulai lihat episode berikutnya dalam Workspace kami.
- Memungkinkan pengguna berinteraksi dengan konten—misalnya, memberi rating atau ulasan konten tanpa mengganggu pemutaran konten.
Link aplikasi ditampilkan saat pengguna menekan Pilih untuk menampilkan menu TV saat menonton konten channel.
Bila pengguna memilih link aplikasi, sistem akan memulai aktivitas menggunakan URI intent yang ditetapkan oleh aplikasi saluran. Konten channel terus diputar saat aktivitas link aplikasi aktif. Pengguna dapat kembali ke channel konten dengan menekan Kembali.
Memberikan data saluran link aplikasi
Android TV secara otomatis membuat link aplikasi untuk setiap saluran,
menggunakan informasi dari data saluran. Untuk memberikan informasi link aplikasi,
menentukan detail berikut di
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, info 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 channel 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 pada gambar 2, info 3.
Jika data saluran tidak menentukan informasi tautan aplikasi, sistem membuat link aplikasi default. Sistem akan memilih detail default seperti berikut:
- Untuk URI intent
(
COLUMN_APP_LINK_INTENT_URI
), sistem menggunakanACTION_MAIN
untuk kategoriCATEGORY_LEANBACK_LAUNCHER
, biasanya didefinisikan dalam manifes aplikasi. Jika aktivitas ini tidak ditentukan, tautan aplikasi yang tidak berfungsi akan muncul—jika pengguna mengkliknya, tidak terjadi apa-apa. - Untuk teks deskriptif
(
COLUMN_APP_LINK_TEXT
), sistem menggunakan "Buka app-name". Jika tidak ada URI intent link aplikasi yang memadai yang ditentukan, sistem menggunakan "Link tidak tersedia". - Untuk warna aksen
(
COLUMN_APP_LINK_COLOR
), sistem menggunakan warna default aplikasi. - Untuk gambar poster
(
COLUMN_APP_LINK_POSTER_ART_URI
), sistem menggunakan banner layar beranda aplikasi. Jika aplikasi tidak menyediakan banner, sistem menggunakan gambar aplikasi TV default. - Untuk ikon badge
(
COLUMN_APP_LINK_ICON_URI
), 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 di bagian
menyiapkan aktivitas. Anda dapat memperbarui detail link aplikasi ini kapan saja, jadi
jika link aplikasi harus cocok dengan perubahan saluran, update aplikasi
detail tautan dan hubungi
ContentResolver.update()
sesuai kebutuhan. Untuk detail selengkapnya tentang pembaruan
data saluran, lihat Memperbarui data saluran.