ورودی تلویزیون شما باید داده های راهنمای برنامه الکترونیکی (EPG) را برای حداقل یک کانال در فعالیت راه اندازی خود ارائه دهد. همچنین باید بهطور دورهای آن دادهها را با در نظر گرفتن اندازه بهروزرسانی و رشته پردازشی که آن را مدیریت میکند، بهروزرسانی کنید. علاوه بر این، میتوانید پیوندهای برنامه را برای کانالهایی ارائه دهید که کاربر را به محتوا و فعالیتهای مرتبط راهنمایی میکند. این درس ایجاد و به روز رسانی داده های کانال و برنامه در پایگاه داده سیستم را با در نظر گرفتن این ملاحظات مورد بحث قرار می دهد.
برنامه نمونه سرویس ورودی تلویزیون را امتحان کنید.
اجازه بگیرید
برای اینکه ورودی تلویزیون شما با داده های EPG کار کند، باید مجوز نوشتن را در فایل مانیفست اندروید خود به صورت زیر اعلام کند:
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
کانال ها را در پایگاه داده ثبت کنید
پایگاه داده سیستم Android TV سوابق داده های کانال را برای ورودی های تلویزیون نگهداری می کند. در فعالیت راه اندازی خود، برای هر یک از کانال های خود، باید داده های کانال خود را به فیلدهای زیر از کلاس TvContract.Channels
نگاشت کنید:
-
COLUMN_DISPLAY_NAME
- نام نمایش داده شده کانال -
COLUMN_DISPLAY_NUMBER
- شماره کانال نمایش داده شده -
COLUMN_INPUT_ID
- شناسه سرویس ورودی تلویزیون -
COLUMN_SERVICE_TYPE
- نوع سرویس کانال -
COLUMN_TYPE
- نوع استاندارد پخش کانال -
COLUMN_VIDEO_FORMAT
- قالب ویدیوی پیشفرض برای کانال
اگرچه چارچوب ورودی تلویزیون به اندازه کافی عمومی است که بتواند هم پخش سنتی و هم محتوای بیش از حد (OTT) را بدون هیچ تمایزی انجام دهد، ممکن است بخواهید ستونهای زیر را علاوه بر ستونهای بالا برای شناسایی بهتر کانالهای پخش سنتی تعریف کنید:
-
COLUMN_ORIGINAL_NETWORK_ID
- شناسه شبکه تلویزیونی -
COLUMN_SERVICE_ID
- شناسه سرویس -
COLUMN_TRANSPORT_STREAM_ID
- شناسه جریان حمل و نقل
اگر میخواهید جزئیات پیوند برنامه را برای کانالهای خود ارائه دهید، باید چند فیلد اضافی را بهروزرسانی کنید. برای اطلاعات بیشتر در مورد فیلدهای پیوند برنامه، به افزودن اطلاعات پیوند برنامه مراجعه کنید.
برای ورودیهای تلویزیون مبتنی بر پخش آنلاین، مقادیر خود را بر اساس آن به موارد بالا اختصاص دهید تا هر کانال به طور منحصر به فرد شناسایی شود.
ابرداده کانال خود (در XML، JSON یا هر چیز دیگری) را از سرور پشتیبان خود بیرون بکشید و در فعالیت راه اندازی، مقادیر را به صورت زیر به پایگاه داده سیستم ترسیم کنید:
کاتلین
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)
جاوا
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);
در مثال بالا، channel
یک شی است که ابرداده کانال را از سرور باطن نگه میدارد.
ارائه اطلاعات کانال و برنامه
برنامه تلویزیون سیستم، همانطور که در شکل 1 نشان داده شده است، هنگام ورق زدن کانال ها، اطلاعات کانال و برنامه را به کاربران ارائه می دهد. برای اطمینان از کارکرد اطلاعات کانال و برنامه با کانال و ارائه کننده اطلاعات برنامه تلویزیون سیستم، دستورالعمل های زیر را دنبال کنید.
- شماره کانال (
COLUMN_DISPLAY_NUMBER
) - نماد (
android:icon
در مانیفست ورودی تلویزیون) - توضیحات برنامه (
COLUMN_SHORT_DESCRIPTION
) - عنوان برنامه (
COLUMN_TITLE
) - لوگوی کانال (
TvContract.Channels.Logo
)- از رنگ #EEEEEE برای مطابقت با متن اطراف استفاده کنید
- بالشتک را شامل نشود
- هنر پوستر (
COLUMN_POSTER_ART_URI
)- نسبت تصویر بین 16:9 و 4:3
برنامه تلویزیون سیستم همان اطلاعات را از طریق راهنمای برنامه، از جمله هنر پوستر، همانطور که در شکل 2 نشان داده شده است، ارائه می دهد.
به روز رسانی داده های کانال
هنگام به روز رسانی داده های کانال موجود، به جای حذف و اضافه کردن مجدد داده ها، از متد update()
استفاده کنید. هنگام انتخاب سوابق برای بهروزرسانی، میتوانید نسخه فعلی دادهها را با استفاده از Channels.COLUMN_VERSION_NUMBER
و Programs.COLUMN_VERSION_NUMBER
شناسایی کنید.
توجه: افزودن داده های کانال به ContentProvider
ممکن است زمان بر باشد. برنامههای فعلی (آنهایی که در عرض دو ساعت از زمان فعلی هستند) را فقط زمانی اضافه کنید که EpgSyncJobService
خود را برای بهروزرسانی بقیه دادههای کانال در پسزمینه پیکربندی کنید. برای مثال به برنامه نمونه تلویزیون زنده Android TV مراجعه کنید.
داده های کانال بارگیری دسته ای
هنگام به روز رسانی پایگاه داده سیستم با حجم زیادی از داده های کانال، از روش ContentResolver
applyBatch()
یا bulkInsert()
استفاده کنید. در اینجا یک مثال با استفاده از applyBatch()
آورده شده است:
کاتلین
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() } }
جاوا
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(); } }
داده های کانال را به صورت ناهمزمان پردازش کنید
دستکاری داده ها، مانند دریافت جریان از سرور یا دسترسی به پایگاه داده، نباید رشته رابط کاربری را مسدود کند. استفاده از AsyncTask
یکی از راه های انجام به روز رسانی به صورت ناهمزمان است. به عنوان مثال، هنگام بارگیری اطلاعات کانال از یک سرور باطن، می توانید از AsyncTask
به صورت زیر استفاده کنید:
کاتلین
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() } } } } }
جاوا
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(); } } } }
اگر نیاز دارید که دادههای EPG را بهطور منظم بهروزرسانی کنید، از WorkManager
برای اجرای فرآیند بهروزرسانی در زمان بیکاری، مانند هر روز در ساعت 3:00 صبح استفاده کنید.
تکنیکهای دیگر برای جدا کردن وظایف بهروزرسانی داده از رشته UI شامل استفاده از کلاس HandlerThread
است، یا میتوانید خودتان را با استفاده از کلاسهای Looper
و Handler
پیادهسازی کنید. برای اطلاعات بیشتر به فرآیندها و موضوعات مراجعه کنید.
اطلاعات پیوند برنامه را اضافه کنید
کانالها میتوانند از پیوندهای برنامه استفاده کنند تا به کاربران اجازه دهند به راحتی یک فعالیت مرتبط را در حین تماشای محتوای کانال اجرا کنند. برنامههای کانال از پیوندهای برنامه برای گسترش تعامل کاربر با راهاندازی فعالیتهایی که اطلاعات مرتبط یا محتوای اضافی را نشان میدهند، استفاده میکنند. به عنوان مثال، می توانید از پیوندهای برنامه برای انجام کارهای زیر استفاده کنید:
- کاربر را برای کشف و خرید محتوای مرتبط راهنمایی کنید.
- اطلاعات بیشتری درباره محتوای در حال پخش ارائه دهید.
- در حین مشاهده محتوای اپیزودیک، شروع به مشاهده قسمت بعدی در یک سریال کنید.
- به کاربر اجازه دهید با محتوا تعامل داشته باشد - به عنوان مثال، محتوا را رتبه بندی یا بررسی کند - بدون وقفه در پخش محتوا.
پیوندهای برنامه زمانی نمایش داده می شوند که کاربر انتخاب را فشار می دهد تا منوی تلویزیون در حین تماشای محتوای کانال نشان داده شود.
هنگامی که کاربر پیوند برنامه را انتخاب می کند، سیستم با استفاده از یک URI هدف مشخص شده توسط برنامه کانال، فعالیتی را شروع می کند. تا زمانی که فعالیت پیوند برنامه فعال است، محتوای کانال به پخش ادامه میدهد. کاربر می تواند با فشار دادن Back به محتوای کانال برگردد.
داده های کانال پیوند برنامه را ارائه دهید
Android TV بهطور خودکار با استفاده از اطلاعات دادههای کانال، یک پیوند برنامه برای هر کانال ایجاد میکند. برای ارائه اطلاعات پیوند برنامه، جزئیات زیر را در فیلدهای TvContract.Channels
خود مشخص کنید:
-
COLUMN_APP_LINK_COLOR
- رنگ تاکیدی پیوند برنامه برای این کانال. برای مثال رنگ تاکیدی، شکل 2، فراخوان 3 را ببینید. -
COLUMN_APP_LINK_ICON_URI
- URI نماد نشان برنامه پیوند برنامه برای این کانال. برای مثال نماد نشان برنامه، شکل 2، فراخوان 2 را ببینید. -
COLUMN_APP_LINK_INTENT_URI
- URI هدف پیوند برنامه برای این کانال. می توانید URI را با استفاده ازtoUri(int)
باURI_INTENT_SCHEME
ایجاد کنید و باparseUri()
URI را به قصد اصلی تبدیل کنید. -
COLUMN_APP_LINK_POSTER_ART_URI
- URI برای هنر پوستر که به عنوان پسزمینه پیوند برنامه برای این کانال استفاده میشود. برای مثال تصویر پوستر، شکل 2، فراخوان 1 را ببینید. -
COLUMN_APP_LINK_TEXT
- متن پیوند توصیفی پیوند برنامه برای این کانال. برای مثال توضیح پیوند برنامه، به متن شکل 2، فراخوان 3 مراجعه کنید.
اگر دادههای کانال اطلاعات پیوند برنامه را مشخص نکند، سیستم یک پیوند برنامه پیشفرض ایجاد میکند. سیستم جزئیات پیش فرض را به صورت زیر انتخاب می کند:
- برای URI قصد (
COLUMN_APP_LINK_INTENT_URI
)، سیستم از فعالیتACTION_MAIN
برای دستهCATEGORY_LEANBACK_LAUNCHER
استفاده میکند که معمولاً در مانیفست برنامه تعریف میشود. اگر این فعالیت تعریف نشده باشد، یک پیوند برنامه غیرفعال ظاهر می شود - اگر کاربر روی آن کلیک کند، هیچ اتفاقی نمی افتد. - برای متن توصیفی (
COLUMN_APP_LINK_TEXT
)، سیستم از " app-name باز" استفاده می کند. اگر URI هدف پیوند برنامه قابل اجرا تعریف نشده باشد، سیستم از «هیچ پیوند موجود نیست» استفاده میکند. - برای رنگ تاکیدی (
COLUMN_APP_LINK_COLOR
)، سیستم از رنگ برنامه پیشفرض استفاده میکند. - برای تصویر پوستر (
COLUMN_APP_LINK_POSTER_ART_URI
)، سیستم از بنر صفحه اصلی برنامه استفاده می کند. اگر برنامه بنری ارائه ندهد، سیستم از تصویر برنامه تلویزیونی پیشفرض استفاده میکند. - برای نماد نشان (
COLUMN_APP_LINK_ICON_URI
)، سیستم از نشانی استفاده می کند که نام برنامه را نشان می دهد. اگر سیستم از بنر برنامه یا تصویر پیشفرض برنامه برای تصویر پوستر نیز استفاده میکند، هیچ نشان برنامه نشان داده نمیشود.
شما جزئیات پیوند برنامه را برای کانال های خود در فعالیت راه اندازی برنامه خود مشخص می کنید. میتوانید جزئیات پیوند برنامه را در هر زمانی بهروزرسانی کنید، بنابراین اگر پیوند برنامه باید با تغییرات کانال مطابقت داشته باشد، جزئیات پیوند برنامه را بهروزرسانی کنید و در صورت نیاز با ContentResolver.update()
تماس بگیرید. برای جزئیات بیشتر در مورد بهروزرسانی دادههای کانال، بهروزرسانی دادههای کانال را ببینید.