توسعه سرویس ورودی تلویزیون

سرویس ورودی تلویزیون نشان‌دهنده منبع جاری‌سازی رسانه است و به شما امکان می‌دهد محتوای رسانه‌ای خود را به‌صورت خطی و به‌شکل تلویزیون آنتنی به‌عنوان کانال و برنامه ارائه دهید. با سرویس ورودی تلویزیون، می‌توانید کنترل‌های والدین، اطلاعات راهنمای برنامه، و رده‌بندی‌های محتوا را ارائه دهید. سرویس ورودی تلویزیون با برنامه تلویزیون سیستم Android کار می‌کند. این برنامه درنهایت محتوای کانال را در تلویزیون کنترل و ارائه می‌کند. برنامه تلویزیون سیستم به‌طور خاص برای دستگاه توسعه یافته است و توسط برنامه‌های طرف سوم تغییرناپذیر است. برای اطلاعات بیشتر درباره معماری «چارچوب ورودی تلویزیون» (TIF) و مؤلفه‌های آن، چارچوب ورودی تلویزیون را ببینید.

ایجاد سرویس ورودی تلویزیون بااستفاده از «کتابخانه همراه TIF»

«کتابخانه همراه TIF» چارچوبی است که پیاده‌سازی‌های قابل‌توسعه‌ای از ویژگی‌های رایج سرویس ورودی تلویزیون ارائه می‌دهد. این ویژگی برای استفاده سازندگان تجهیزات اصلی (OEM) جهت ساختن کانال‌ها فقط برای Android نسخه ۵.۰ (سطح میانای برنامه‌سازی کاربردی ۲۱) تا Android نسخه ۷.۱ (سطح میانای برنامه‌سازی کاربردی ۲۵) درنظر گرفته شده است.

به‌روزرسانی پروژه

«کتابخانه همپا TIF» برای استفاده قدیمی توسط سازندگان اصلی در مخزن androidtv-sample-inputs دردسترس است. برای دیدن نمونه‌ای از نحوه گنجاندن کتابخانه در برنامه، به آن مخزن مراجعه کنید.

سرویس ورودی تلویزیون را در مانیفست اعلام کنید

برنامه شما باید سرویس سازگار با TvInputService ارائه دهد که سیستم از آن برای دسترسی به برنامه شما استفاده می‌کند. «کتابخانه همراه TIF» کلاس BaseTvInputService را ارائه می‌دهد که پیاده‌سازی پیش‌فرض TvInputService را ارائه می‌دهد که می‌توانید آن را سفارشی‌سازی کنید. زیرکلاسی از BaseTvInputService ایجاد کنید، و زیرکلاس را در مانیفست خود به‌عنوان سرویس اعلام کنید.

در اظهارنامه مانیفست، اجازه BIND_TV_INPUT را مشخص کنید تا به سرویس اجازه داده شود ورودی تلویزیون را به سیستم متصل کند. سرویس سیستم اتصال را انجام می‌دهد و اجازه BIND_TV_INPUT را دارد. برنامه تلویزیون سیستم درخواست‌ها را ازطریق میانای TvInputManager به سرویس‌های ورودی تلویزیون ارسال می‌کند.

در اعلامیه سرویس خود، فیلتر هدفی را اضافه کنید که TvInputService را به‌عنوان کنشی که باید با هدف انجام شود مشخص می‌کند. همچنین فراداده سرویس را به‌عنوان منبع XML جداگانه اعلام کنید. اظهارنامه سرویس، فیلتر قصد، و اظهارنامه فراداده سرویس در مثال زیر نشان داده شده است:

<service android:name=".rich.RichTvInputService"
    android:label="@string/rich_input_label"
    android:permission="android.permission.BIND_TV_INPUT">
    <!-- Required filter used by the system to launch our account service. -->
    <intent-filter>
        <action android:name="android.media.tv.TvInputService" />
    </intent-filter>
    <!-- An XML file which describes this input. This provides pointers to
    the RichTvInputSetupActivity to the system/TV app. -->
    <meta-data
        android:name="android.media.tv.input"
        android:resource="@xml/richtvinputservice" />
</service>

فراداده سرویس را در فایل XML جداگانه‌ای تعریف کنید. فایل XML فراداده سرویس باید شامل میانای راه‌اندازی باشد که پیکربندی اولیه و اسکن کانال ورودی تلویزیون را شرح دهد. فایل فراداده باید همچنین حاوی یک پرچم باشد که نشان دهد آیا کاربران می‌توانند محتوا را ضبط کنند یا نه. برای اطلاعات بیشتر درباره نحوه پشتیبانی از ضبط محتوا در برنامه‌تان، به پشتیبانی از ضبط محتوا مراجعه کنید.

فایل فراداده سرویس در فهرست راهنمای منابع XML برای برنامه‌تان قرار دارد و باید با نام منبعی که در مانیفست اعلام کرده‌اید مطابقت داشته باشد. بااستفاده از ورودی‌های مانیفست از مثال قبلی، فایل XML را در res/xml/richtvinputservice.xml با محتوای زیر ایجاد می‌کنید:

<?xml version="1.0" encoding="utf-8"?>
<tv-input xmlns:android="http://schemas.android.com/apk/res/android"
  android:canRecord="true"
  android:setupActivity="com.example.android.sampletvinput.rich.RichTvInputSetupActivity" />

کانال‌ها را تعریف کنید و فعالیت راه‌اندازی‌تان را ایجاد کنید

سرویس ورودی تلویزیون شما باید حداقل یک کانال تعریف کند که کاربران ازطریق برنامه تلویزیون سیستم به آن دسترسی داشته باشند. باید کانال‌هایتان را در پایگاه داده سیستم ثبت کنید و فعالیت راه‌اندازی‌ای ارائه دهید که سیستم وقتی نمی‌تواند کانالی برای برنامه‌تان پیدا کند آن را فراخوانی کند.

ابتدا، به برنامه‌تان اجازه دهید از «راهنمای برنامه‌نویسی الکترونیکی» (EPG) سیستم بخواند و در آن بنویسد. داده‌های این راهنما شامل کانال‌ها و برنامه‌های دردسترس کاربر است. برای اینکه برنامه‌تان بتواند این کنش‌ها را انجام دهد و پس‌از بازراه‌اندازی دستگاه با EPG همگام‌سازی شود، عناصر زیر را به مانیفست برنامه‌تان اضافه کنید:

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

عنصر زیر را اضافه کنید تا مطمئن شوید برنامه‌تان در «فروشگاه Google Play» به‌عنوان برنامه‌ای که کانال‌های محتوا در Android TV ارائه می‌دهد نشان داده می‌شود:

<uses-feature
    android:name="android.software.live_tv"
    android:required="true" />

سپس، کلاسی ایجاد کنید که کلاس EpgSyncJobService را گسترش دهد. این کلاس انتزاعی به شما امکان می‌دهد سرویس کاری ایجاد کنید که کانال‌ها را در پایگاه داده سیستم ایجاد و به‌روزرسانی می‌کند.

در زیرکلاس خود، فهرست کامل کانال‌هایتان را در getChannels ایجاد کنید و برگردانید. اگر کانال‌هایتان از فایل XMLTV می‌آید، از کلاس XmlTvParser استفاده کنید. درغیراین‌صورت، کانال‌ها را به‌صورت برنامه‌نویسی‌شده بااستفاده از کلاس Channel.Builder تولید کنید.

برای هر کانال، وقتی سیستم به فهرستی از برنامه‌هایی نیاز دارد که می‌توانند در پنجره زمانی مشخصی در کانال مشاهده شوند، getProgramsForChannel را فراخوانی می‌کند. فهرستی از اشیاء Program را برای کانال برگردانید. از کلاس XmlTvParser برای دریافت برنامه‌ها از فایل XMLTV استفاده کنید، یا آن‌ها را به‌صورت برنامه‌نویسی‌شده بااستفاده از کلاس Program.Builder تولید کنید.

برای هر شیء Program، از شیء InternalProviderData برای تنظیم اطلاعات برنامه مانند نوع ویدیو برنامه استفاده کنید. اگر فقط تعداد محدودی برنامه دارید که می‌خواهید کانال آن‌ها را به‌صورت حلقه‌ای تکرار کند، هنگام تنظیم اطلاعات مربوط به برنامه‌تان، از روش InternalProviderData.setRepeatable با مقدار true استفاده کنید.

پس‌از پیاده‌سازی سرویس کار، آن را به مانیفست برنامه‌تان اضافه کنید:

<service
    android:name=".sync.SampleJobService"
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:exported="true" />

درنهایت، فعالیت راه‌اندازی ایجاد کنید. فعالیت راه‌اندازی شما باید راهی برای همگام‌سازی داده‌های کانال و برنامه ارائه دهد. یک راه برای انجام این کار این است که کاربر آن را بااستفاده از میانای کاربر در فعالیت انجام دهد. همچنین می‌توانید تنظیم کنید برنامه این کار را به‌طور خودکار هنگام شروع فعالیت انجام دهد. وقتی فعالیت راه‌اندازی نیاز به همگام‌سازی اطلاعات کانال و برنامه دارد، برنامه باید سرویس کار را شروع کند:

کاتلین

val inputId = getActivity().intent.getStringExtra(TvInputInfo.EXTRA_INPUT_ID)
EpgSyncJobService.cancelAllSyncRequests(getActivity())
EpgSyncJobService.requestImmediateSync(
        getActivity(),
        inputId,
        ComponentName(getActivity(), SampleJobService::class.java)
)

جاوا

String inputId = getActivity().getIntent().getStringExtra(TvInputInfo.EXTRA_INPUT_ID);
EpgSyncJobService.cancelAllSyncRequests(getActivity());
EpgSyncJobService.requestImmediateSync(getActivity(), inputId,
        new ComponentName(getActivity(), SampleJobService.class));

از روش requestImmediateSync برای همگام‌سازی سرویس کار استفاده کنید. کاربر باید منتظر بماند تا همگام‌سازی تمام شود، بنابراین باید دوره درخواستتان را نسبتاً کوتاه نگه دارید.

از روش setUpPeriodicSync استفاده کنید تا سرویس کار به‌طور دوره‌ای داده‌های کانال و برنامه را در پس‌زمینه همگام‌سازی کند:

کاتلین

EpgSyncJobService.setUpPeriodicSync(
        context,
        inputId,
        ComponentName(context, SampleJobService::class.java)
)

جاوا

EpgSyncJobService.setUpPeriodicSync(context, inputId,
        new ComponentName(context, SampleJobService.class));

«کتابخانه همراه TIF» روش سربارگذاری‌شده دیگری برای requestImmediateSync ارائه می‌دهد که به شما امکان می‌دهد مدت زمان داده‌های کانال را برای همگام‌سازی برحسب میلی‌ثانیه مشخص کنید. روش پیش‌فرض داده‌های کانال را برای یک ساعت همگام‌سازی می‌کند.

«کتابخانه همراه TIF» همچنین روش سربارگذاری‌شده دیگری برای setUpPeriodicSync ارائه می‌دهد که به شما امکان می‌دهد مدت زمان داده‌های کانال را برای همگام‌سازی و تعداد دفعات همگام‌سازی دوره‌ای را مشخص کنید. روش پیش‌فرض، داده‌های کانال را هر ۱۲ ساعت یک‌بار برای ۴۸ ساعت همگام‌سازی می‌کند.

برای جزئیات بیشتر درباره داده‌های کانال و راهنمای الکترونیکی برنامه، کار با داده‌های کانال را ببینید.

رسیدگی به درخواست‌های تنظیم و بازپخش رسانه

وقتی کاربر کانال خاصی را انتخاب می‌کند، برنامه تلویزیون سیستم از Session، که توسط برنامه شما ایجاد شده است، برای تنظیم کانال درخواستی و پخش محتوا استفاده می‌کند. «کتابخانه همپای TIF» چندین کلاس ارائه می‌دهد که می‌توانید برای رسیدگی به تماس‌های کانال و جلسه از سیستم، آن‌ها را گسترش دهید.

زیرکلاس BaseTvInputService شما جلسه‌هایی ایجاد می‌کند که درخواست‌های بهینه‌سازی را مدیریت می‌کنند. روش onCreateSession را لغو کنید، جلسه‌ای ایجاد کنید که از کلاس BaseTvInputService.Session گسترش یافته باشد، و super.sessionCreated را با جلسه جدیدتان فراخوانی کنید. در مثال زیر، onCreateSession یک شیء RichTvInputSessionImpl را برمی‌گرداند که BaseTvInputService.Session را گسترش می‌دهد:

کاتلین

override fun onCreateSession(inputId: String): Session =
        RichTvInputSessionImpl(this, inputId).apply {
            setOverlayViewEnabled(true)
        }

جاوا

@Override
public final Session onCreateSession(String inputId) {
    RichTvInputSessionImpl session = new RichTvInputSessionImpl(this, inputId);
    session.setOverlayViewEnabled(true);
    return session;
}

وقتی کاربر از برنامه تلویزیون سیستم برای شروع مشاهده یکی از کانال‌های شما استفاده می‌کند، سیستم روش onPlayChannel جلسه شما را فراخوانی می‌کند. اگر لازم است قبل‌از شروع پخش برنامه، مقداردهی اولیه خاصی برای کانال انجام دهید، این روش را لغو کنید.

سپس سیستم برنامه زمان‌بندی‌شده فعلی را دریافت می‌کند و روش onPlayProgram جلسه شما را فراخوانی می‌کند و اطلاعات برنامه و زمان شروع را به میلی‌ثانیه مشخص می‌کند. از میانای TvPlayer برای شروع پخش برنامه استفاده کنید.

کد پخش‌کننده رسانه شما باید TvPlayer را برای رسیدگی به رویدادهای بازپخش خاص پیاده‌سازی کند. کلاس TvPlayer ویژگی‌هایی مثل کنترل‌های تغییر زمان را بدون افزودن پیچیدگی به پیاده‌سازی BaseTvInputService شما مدیریت می‌کند.

در روش getTvPlayer جلسه، پخش‌کننده رسانه‌تان را که TvPlayer را پیاده‌سازی می‌کند برگردانید. برنامه نمونه سرویس ورودی تلویزیون پخش‌کننده رسانه‌ای را پیاده‌سازی می‌کند که از ExoPlayer استفاده می‌کند.

ایجاد سرویس ورودی تلویزیون بااستفاده از چارچوب ورودی تلویزیون

اگر سرویس ورودی تلویزیون شما نمی‌تواند از «کتابخانه همراه TIF» استفاده کند، باید مؤلفه‌های زیر را پیاده‌سازی کنید:

  • TvInputService دردسترس بودن طولانی‌مدت و پس‌زمینه‌ای را برای ورودی تلویزیون فراهم می‌کند
  • TvInputService.Session وضعیت ورودی تلویزیون را حفظ می‌کند و با برنامه میزبان ارتباط برقرار می‌کند
  • TvContract کانال‌ها و برنامه‌های دردسترس برای ورودی تلویزیون را شرح می‌دهد
  • TvContract.Channels نشان‌دهنده اطلاعات مربوط به کانال تلویزیونی است
  • TvContract.Programs برنامه تلویزیونی را با داده‌هایی مثل عنوان برنامه و زمان شروع توصیف می‌کند
  • TvTrackInfo نشان‌دهنده قطعه صوتی، تصویری، یا زیرنویس است
  • TvContentRating رده‌بندی محتوا را شرح می‌دهد، امکان استفاده از طرح‌های رده‌بندی محتوای سفارشی را فراهم می‌کند
  • TvInputManager میانای برنامه‌سازی کاربردی را برای برنامه تلویزیون سیستم فراهم می‌کند و تعامل با ورودی‌ها و برنامه‌های تلویزیون را مدیریت می‌کند

همچنین باید کارهای زیر را انجام دهید:

  1. سرویس ورودی تلویزیون را در مانیفست اعلام کنید، همان‌طور که در اعلام سرویس ورودی تلویزیون در مانیفست شرح داده شده است.
  2. فایل فراداده سرویس را ایجاد کنید.
  3. اطلاعات کانال و برنامه خود را ایجاد و ثبت کنید.
  4. فعالیت راه‌اندازی‌تان را ایجاد کنید.

تعریف سرویس ورودی تلویزیون

برای سرویس خود، کلاس TvInputService را گسترش می‌دهید. پیاده‌سازی TvInputService یک خدمات محدودکننده است که در آن خدمات سیستم سرویس‌گیرنده‌ای است که به آن محدود می‌شود. روش‌های چرخه حیات سرویس که باید پیاده‌سازی کنید در شکل ۱ نشان داده شده است.

روش onCreate، HandlerThread را مقداردهی اولیه و راه‌اندازی می‌کند که رشته فرایندی جدا از رشته میانای کاربر برای رسیدگی به کنش‌های سیستم‌محور ارائه می‌دهد. در مثال زیر، روش onCreate CaptioningManager را مقداردهی اولیه می‌کند و برای مدیریت کنش‌های ACTION_BLOCKED_RATINGS_CHANGED و ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED آماده می‌شود. این کنش‌ها هدف‌های سیستم را که هنگام تغییر تنظیمات کنترل والدین توسط کاربر و هنگام تغییر در فهرست رده‌بندی‌های مسدودشده فعال می‌شوند شرح می‌دهند.

کاتلین

override fun onCreate() {
    super.onCreate()
    handlerThread = HandlerThread(javaClass.simpleName).apply {
        start()
    }
    dbHandler = Handler(handlerThread.looper)
    handler = Handler()
    captioningManager = getSystemService(Context.CAPTIONING_SERVICE) as CaptioningManager

    setTheme(android.R.style.Theme_Holo_Light_NoActionBar)

    sessions = mutableListOf<BaseTvInputSessionImpl>()
    val intentFilter = IntentFilter().apply {
        addAction(TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED)
        addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED)
    }
    registerReceiver(broadcastReceiver, intentFilter)
}

جاوا

@Override
public void onCreate() {
    super.onCreate();
    handlerThread = new HandlerThread(getClass()
      .getSimpleName());
    handlerThread.start();
    dbHandler = new Handler(handlerThread.getLooper());
    handler = new Handler();
    captioningManager = (CaptioningManager)
      getSystemService(Context.CAPTIONING_SERVICE);

    setTheme(android.R.style.Theme_Holo_Light_NoActionBar);

    sessions = new ArrayList<BaseTvInputSessionImpl>();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(TvInputManager
      .ACTION_BLOCKED_RATINGS_CHANGED);
    intentFilter.addAction(TvInputManager
      .ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED);
    registerReceiver(broadcastReceiver, intentFilter);
}

شکل ۱.چرخه حیات TvInputService.

برای اطلاعات بیشتر درباره کار با محتوای مسدودشده و ارائه کنترل والدین، به کنترل محتوا مراجعه کنید. برای کنش‌های سیستم‌محور بیشتری که ممکن است بخواهید در سرویس ورودی تلویزیون خود مدیریت کنید، به TvInputManager مراجعه کنید.

TvInputService یک TvInputService.Session ایجاد می‌کند که Handler.Callback را پیاده‌سازی می‌کند تا تغییرات وضعیت پخش‌کننده را مدیریت کند. با onSetSurface، TvInputService.Session Surface را با محتوای ویدیو تنظیم می‌کند. برای اطلاعات بیشتر درباره کار با Surface برای رندر کردن ویدیو، ادغام کردن پخش‌کننده با سطح را ببینید.

TvInputService.Session onTune رویداد را وقتی کاربر کانالی را انتخاب می‌کند مدیریت می‌کند و به برنامه تلویزیون سیستم برای تغییرات در محتوا و فراداده محتوا اطلاع می‌دهد. این notify روش در «کنترل محتوا» و مدیریت انتخاب قطعه در ادامه این آموزش شرح داده شده‌اند.

تعریف کردن فعالیت راه‌اندازی

برنامه تلویزیون سیستم با فعالیت راه‌اندازی‌ای که برای ورودی تلویزیون تعریف می‌کنید کار می‌کند. فعالیت راه‌اندازی الزامی است و باید حداقل یک سابقه کانال برای پایگاه داده سیستم ارائه دهد. برنامه تلویزیون سیستم، وقتی نمی‌تواند کانالی برای ورودی تلویزیون پیدا کند، فعالیت راه‌اندازی را فراخوانی می‌کند.

فعالیت راه‌اندازی، کانال‌های دردسترس ازطریق ورودی تلویزیون را برای برنامه تلویزیون سیستم شرح می‌دهد، همان‌طور که در درس بعدی، ایجاد و به‌روزرسانی داده‌های کانال، نشان داده شده است.

مرجع‌های اضافی