تطوير خدمة إدخال تلفزيون

تمثل خدمة إدخال التلفزيون مصدر بث وسائط، وتسمح لك بتقديم محتوى الوسائط في البرامج التلفزيونية المُجدوَلة، مثل القنوات والبرامج من خلال خدمة إدخال التلفزيون، يمكنك توفير أدوات رقابة الأهل ومعلومات في دليل البرامج وتقييمات المحتوى. خدمة إدخال التلفزيون تعمل من خلال تطبيق Android TV يتحكّم هذا التطبيق في النهاية في محتوى القناة ويعرضه. على التلفزيون. إنّ تطبيق YouTube TV مصمَّم خصيصًا للأجهزة غير قابل للتغيير. تطبيقات تابعة لجهات خارجية مزيد من المعلومات حول إطار عمل إدخال التلفزيون (TIF) الهندسة ومكوناتها، انظر إطار عمل إدخال التلفزيون

إنشاء خدمة إدخال تلفزيون باستخدام مكتبة TIF المصاحبة

مكتبة TIF المصاحبة هي إطار عمل يوفر مستندات قابلة للتوسُّع استخدامات لميزات خدمة إدخال التلفزيون الشائعة. فمن المفترض أن يستخدمه المصنّعون الأصليون للأجهزة لبناء قنوات الإصدارات من Android 5.0 (المستوى 21 لواجهة برمجة التطبيقات) إلى Android 7.1 (المستوى 25 من واجهة برمجة التطبيقات) فقط.

تحديث مشروعك

تتوفر مكتبة 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" />

وأخيرًا، أنشئ نشاط إعداد. ينبغي أن يوفر نشاط الإعداد وسيلة لمزامنة بيانات القناة والبرنامج تتمثل إحدى طرق القيام بذلك في أن يقوم المستخدم بذلك عبر واجهة المستخدم في النشاط. قد يكون لديك أيضًا التطبيق الذي ينفّذ ذلك تلقائيًا عند بدء النشاط. عندما يحتاج نشاط الإعداد إلى مزامنة القناة معلومات البرنامج، يجب أن يبدأ التطبيق خدمة الوظيفة:

Kotlin

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

Java

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

استخدام طريقة requestImmediateSync() للمزامنة خدمة العمل. وعلى المستخدم الانتظار حتى تنتهي المزامنة، لذا عليك اجعل فترة الطلب قصيرة نسبيًا.

استخدِم الطريقة setUpPeriodicSync() للحصول على خدمة المهام مزامنة بيانات القناة والبرنامج بشكل دوري في الخلفية:

Kotlin

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

Java

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

وتوفر المكتبة المصاحبة لـ TIF طريقة إضافية محمّلة بشكل زائد requestImmediateSync() التي تتيح لك تحديد مدة بيانات القناة لتتم مزامنتها بالمللي ثانية. تُزامن الطريقة الافتراضية ساعة واحدة من بيانات القناة.

كما توفر مكتبة TIF المصاحبة أيضًا طريقة إضافية setUpPeriodicSync() التي تتيح لك تحديد مدة بيانات القناة المطلوب مزامنتها وعدد مرات حدوث المزامنة الدورية. تشير رسالة الأشكال البيانية إلى مزامنة بيانات القناة لمدة 48 ساعة كل 12 ساعة.

لمزيد من التفاصيل حول بيانات القناة ودليل EPG، يمكنك الاطّلاع على استخدام بيانات القناة:

معالجة طلبات التوليف وتشغيل الوسائط

عندما يختار مستخدم قناة معيّنة، يستخدم تطبيق تلفزيون النظام قناة "Session" التي أنشأها تطبيقك للعثور على القناة المطلوبة وتشغيل المحتوى. توفر المكتبة المصاحبة لـ TIF العديد من يمكنك توسيعها للتعامل مع مكالمات القناة والجلسات من النظام.

تنشئ الفئة الفرعية BaseTvInputService جلسات تتعامل مع طلبات التوليف. إلغاء onCreateSession()، يمكنك إنشاء جلسة تم تمديدها من فئة BaseTvInputService.Session، واستدعاء super.sessionCreated() مع جلستك الجديدة. في ما يلي على سبيل المثال، تُرجع الدالة onCreateSession() كائن RichTvInputSessionImpl يمتد BaseTvInputService.Session:

Kotlin

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

Java

@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 واجهة برمجة تطبيقات للنظام ويديرها تطبيق TV. التفاعل مع إدخالات التلفزيون والتطبيقات

عليك أيضًا إجراء ما يلي:

  1. يُرجى تعريف خدمة إدخال التلفزيون في البيان باسم كما هو موضح في توضيح خدمة إدخال التلفزيون في البيان.
  2. أنشئ ملف البيانات الوصفية للخدمة.
  3. إنشاء وتسجيل معلومات القناة والبرنامج
  4. إنشاء نشاط الإعداد.

تحديد خدمة إدخال التلفزيون

ولتوفير الخدمة لك، يمكنك تمديد فئة TvInputService. حاسمة تنفيذ TvInputService هو الخدمة المرتبطة حيث تعمل خدمة النظام هو العميل الذي يرتبط بها. طرق دورة حياة الخدمة التي تحتاج إلى تنفيذها كما هو موضح في الشكل 1.

تعمل الطريقة onCreate() على تهيئة وبدء علامة HandlerThread الذي يوفر سلسلة عملية منفصلة عن سلسلة واجهة المستخدم التعامل مع الإجراءات المستندة إلى النظام. في المثال التالي، تشير السمة onCreate() تعمل على إعداد CaptioningManager وتستعد للتعامل مع ACTION_BLOCKED_RATINGS_CHANGED وACTION_PARENTAL_CONTROLS_ENABLED_CHANGED إجراء. هذه تصف نوايا النظام التي يتم تنشيطها عندما يغيّر المستخدم إعدادات أدوات رقابة الأهل، وعندما أن يكون هناك تغيير في قائمة التقييمات المحظورة.

Kotlin

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)
}

Java

@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);
}

الشكل 1.دورة حياة TVInputService.

عرض يمكنك التحكّم في المحتوى للحصول على مزيد من المعلومات حول التعامل مع المحتوى المحظور وتقديمه رقابة الأهل. يمكنك الاطّلاع على TvInputManager لمزيد من الإجراءات المستندة إلى النظام التي التي قد ترغب في معالجتها في خدمة إدخال التلفزيون.

تُنشئ TvInputService TvInputService.Session التي تنفّذ Handler.Callback للتعامل مع التغييرات في حالة اللاعب. مع onSetSurface(), يحدد TvInputService.Session Surface مع محتوى الفيديو. راجِع القسم دمج المشغّل مع مساحة العرض لمزيد من المعلومات حول استخدام Surface لعرض الفيديو.

تعالج السمة TvInputService.Session onTune() حدث عندما يختار المستخدم قناة، ويُرسِل إشعارًا إلى تطبيق التلفزيون بشأن أي تغييرات في المحتوى بيانات التعريف للمحتوى. يتم وصف طُرق notify() هذه في التحكّم في المحتوى والتعامل مع اختيار المقطع الصوتي بشكل أكبر في هذا التدريب.

تحديد نشاط الإعداد

يعمل تطبيق النظام على التلفزيون مع نشاط الإعداد الذي تحدّده لإدخال التلفزيون. تشير رسالة الأشكال البيانية نشاط الإعداد مطلوب ويجب أن يقدم سجل قناة واحدًا على الأقل لقاعدة بيانات النظام. تشير رسالة الأشكال البيانية يستدعي تطبيق تلفزيون النظام نشاط الإعداد عندما لا يتمكن من العثور على قناة لإدخال التلفزيون.

يصف نشاط الإعداد لنظام التلفزيون القنوات المتاحة من خلال التلفزيون كما هو موضح في الدرس التالي، إنشاء وتعديل بيانات القناة

مراجع إضافية