टीवी इनपुट सेवा डेवलप करें

एक टीवी इनपुट सेवा एक मीडिया स्ट्रीम स्रोत का प्रतिनिधित्व करती है, और आपको अपनी मीडिया सामग्री को चैनलों और कार्यक्रमों के रूप में एक रैखिक, प्रसारित टीवी शैली में प्रस्तुत करने की अनुमति देती है. टीवी इनपुट सेवा की मदद से, माता-पिता के कंट्रोल, प्रोग्राम गाइड की जानकारी, और कॉन्टेंट रेटिंग दी जा सकती हैं. टीवी इनपुट सेवा, Android सिस्टम टीवी ऐप्लिकेशन के साथ काम करती है. यह ऐप्लिकेशन, टीवी पर चैनल के कॉन्टेंट को कंट्रोल करता है और उसे दिखाता है. सिस्टम टीवी ऐप्लिकेशन को खास तौर पर डिवाइस के लिए बनाया गया है. इसे तीसरे पक्ष के ऐप्लिकेशन नहीं बदल सकते. टीवी इनपुट फ़्रेमवर्क (टीआईएफ़) के आर्किटेक्चर और इसके कॉम्पोनेंट के बारे में ज़्यादा जानने के लिए, टीवी इनपुट फ़्रेमवर्क देखें.

TIF Companion Library का इस्तेमाल करके, टीवी इनपुट सेवा बनाना

TIF Companion Library एक ऐसा फ़्रेमवर्क है जो टीवी इनपुट सेवा की सामान्य सुविधाओं को लागू करने के लिए, एक्सटेंड किए जा सकने वाले तरीके उपलब्ध कराता है. इसका इस्तेमाल सिर्फ़ ओईएम, Android 5.0 (एपीआई लेवल 21) से लेकर Android 7.1 (एपीआई लेवल 25) तक के वर्शन के लिए चैनल बनाने के लिए कर सकते हैं.

प्रोजेक्ट अपडेट करना

TIF कंपेनियन लाइब्रेरी OEM द्वारा विरासत उपयोग के लिए androidtv-sample-inputs रिपॉजिटरी में उपलब्ध है. किसी ऐप्लिकेशन में लाइब्रेरी को शामिल करने का तरीका जानने के लिए, उस रिपॉज़िटरी को देखें.

मेनिफ़ेस्ट फ़ाइल में, टीवी इनपुट सेवा के बारे में जानकारी देना

आपके ऐप्लिकेशन को TvInputService के साथ काम करने वाली सेवा देनी होगी. सिस्टम इस सेवा का इस्तेमाल करके, आपके ऐप्लिकेशन को ऐक्सेस करता है. TIF कंपैनियन लाइब्रेरी, BaseTvInputService क्लास उपलब्ध कराती है. यह TvInputService का डिफ़ॉल्ट तौर पर लागू किया गया वर्शन उपलब्ध कराती है. इसे अपनी ज़रूरत के हिसाब से बदला जा सकता है. BaseTvInputService की एक सबक्लास बनाएं. इसके बाद, अपनी मेनिफ़ेस्ट फ़ाइल में सबक्लास को सेवा के तौर पर घोषित करें.

मेनिफ़ेस्ट के एलान में, BIND_TV_INPUT अनुमति के बारे में बताएं, ताकि सेवा को टीवी इनपुट को सिस्टम से कनेक्ट करने की अनुमति मिल सके. एक सिस्टम सेवा बाइंडिंग करती है और उसके पास BIND_TV_INPUT अनुमति है. सिस्टम टीवी ऐप्लिकेशन TvInputManager इंटरफ़ेस के माध्यम से टीवी इनपुट सेवाओं को अनुरोध भेजता है.

अपनी सेवा घोषणा में, एक इंटेंट फ़िल्टर शामिल करें जो TvInputService को इंटेंट के साथ निष्पादित करने के लिए क्रिया के रूप में निर्दिष्ट करता है. इसके अलावा, सेवा के मेटाडेटा को एक अलग एक्सएमएल संसाधन के तौर पर भी घोषित करें. नीचे दिए गए उदाहरण में, सेवा के बारे में जानकारी, इंटेंट फ़िल्टर, और सेवा के मेटाडेटा के बारे में जानकारी दी गई है:

<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 रिसॉर्स डायरेक्ट्री में मौजूद होती है. इसका नाम, मेनिफ़ेस्ट में एलान किए गए रिसॉर्स के नाम से मेल खाना चाहिए. पिछले उदाहरण से मैनिफ़ेस्ट प्रविष्टियों का उपयोग करके, आप 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" />

चैनल परिभाषित करें और अपनी सेटअप गतिविधि बनाएं

आपकी टीवी इनपुट सेवा को कम से कम एक ऐसा चैनल तय करना होगा जिसे उपयोगकर्ता, सिस्टम टीवी ऐप्लिकेशन के ज़रिए ऐक्सेस कर सकें. आपको अपने चैनलों को सिस्टम डेटाबेस में रजिस्टर करना होगा. साथ ही, एक सेटअप गतिविधि उपलब्ध करानी होगी. जब सिस्टम को आपके ऐप्लिकेशन के लिए कोई चैनल नहीं मिलता है, तब वह इस गतिविधि को शुरू करता है.

सबसे पहले, अपने ऐप्लिकेशन को सिस्टम के इलेक्ट्रॉनिक प्रोग्रामिंग गाइड (ईपीजी) से डेटा पढ़ने और उसमें डेटा लिखने की अनुमति दें. ईपीजी के डेटा में, उपयोगकर्ता के लिए उपलब्ध चैनल और प्रोग्राम शामिल होते हैं. अपने ऐप्लिकेशन को ये कार्रवाइयां करने की अनुमति देने के लिए, अपने ऐप्लिकेशन मेनिफ़ेस्ट में ये एलिमेंट जोड़ें. साथ ही, डिवाइस को रीस्टार्ट करने के बाद, ईपीजी के साथ सिंक करें:

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

यह सुनिश्चित करने के लिए कि आपका ऐप Google Play Store में Android TV में कंटेंट चैनल प्रदान करने वाले ऐप के रूप में दिखाई दे, निम्नलिखित एलिमेंट जोड़ें:

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

इसके बाद, एक ऐसी क्लास बनाएं जो EpgSyncJobService क्लास को बढ़ाती हो. इस ऐब्स्ट्रैक्ट क्लास की मदद से, ऐसी जॉब सर्विस बनाई जा सकती है जो सिस्टम डेटाबेस में चैनल बनाती है और उन्हें अपडेट करती है.

अपने सब-क्लास में, getChannels में चैनलों की पूरी सूची बनाएं और उसे वापस भेजें. यदि आपके चैनल XMLTV फ़ाइल से आते हैं, तो XmlTvParser क्लास का उपयोग करें. इसके अलावा, Channel.Builder क्लास का इस्तेमाल करके, प्रोग्राम के हिसाब से चैनल जनरेट करें.

प्रत्येक चैनल के लिए, सिस्टम getProgramsForChannel को कॉल करता है जब उसे चैनल पर दिए गए समय विंडो के भीतर देखे जा सकने वाले कार्यक्रमों की सूची की आवश्यकता होती है. चैनल के लिए Program ऑब्जेक्ट की सूची लौटाएँ. XMLTV फ़ाइल से प्रोग्राम पाने के लिए, XmlTvParser क्लास का इस्तेमाल करें. इसके अलावा, 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 Companion Library, requestImmediateSync का एक और ओवरलोड किया गया तरीका उपलब्ध कराती है. इसकी मदद से, चैनल के डेटा को मिलीसेकंड में सिंक करने की अवधि तय की जा सकती है. डिफ़ॉल्ट तरीके से, एक घंटे का चैनल डेटा सिंक किया जाता है.

TIF Companion Library, setUpPeriodicSync का एक और ओवरलोड किया गया तरीका भी उपलब्ध कराती है. इसकी मदद से, सिंक किए जाने वाले चैनल डेटा की अवधि और समय-समय पर होने वाले सिंक की फ़्रीक्वेंसी तय की जा सकती है. डिफ़ॉल्ट तरीके से, हर 12 घंटे में चैनल के 48 घंटे के डेटा को सिंक किया जाता है.

चैनल के डेटा और ईपीजी के बारे में ज़्यादा जानने के लिए, चैनल के डेटा के साथ काम करना लेख पढ़ें.

ट्यूनिंग के अनुरोधों और मीडिया प्लेबैक को मैनेज करना

जब कोई उपयोगकर्ता किसी विशिष्ट चैनल का चयन करता है, तो सिस्टम टीवी ऐप्लिकेशन आपके ऐप द्वारा बनाए गए 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 Companion Library का इस्तेमाल नहीं कर सकती, तो आपको इन कॉम्पोनेंट को लागू करना होगा:

  • TvInputService टीवी इनपुट को लंबे समय तक और बैकग्राउंड में उपलब्ध कराता है
  • TvInputService.Session टीवी इनपुट की स्थिति को बनाए रखता है और होस्टिंग ऐप्लिकेशन से कम्यूनिकेट करता है
  • TvContract से पता चलता है कि टीवी इनपुट के लिए कौनसे चैनल और प्रोग्राम उपलब्ध हैं
  • TvContract.Channels किसी टीवी चैनल के बारे में जानकारी दिखाता है
  • TvContract.Programs एक टीवी कार्यक्रम का वर्णन करता है जिसमें कार्यक्रम का शीर्षक और प्रारंभ समय जैसी जानकारी शामिल होती है.
  • TvTrackInfo ऑडियो, वीडियो या सबटाइटल ट्रैक को दर्शाता है
  • TvContentRating कॉन्टेंट रेटिंग के बारे में बताता है. इससे कॉन्टेंट रेटिंग के कस्टम स्कीम की अनुमति मिलती है
  • TvInputManager सिस्टम टीवी ऐप्लिकेशन के लिए एक API प्रदान करता है और टीवी इनपुट और ऐप्स के साथ इंटरैक्शन को प्रबंधित करता है.

आपको निम्नलिखित कार्य भी करने होंगे:

  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. टीवी इनपुट सेवा जीवनचक्र.

अवरुद्ध सामग्री के साथ काम करने और माता-पिता का नियंत्रण प्रदान करने के बारे में अधिक जानकारी के लिए सामग्री को नियंत्रित करें देखें. अपने टीवी इनपुट सेवा में आप जिन सिस्टम-चालित कार्यों को संभालना चाहते हैं, उनके बारे में अधिक जानने के लिए TvInputManager देखें.

TvInputService, एक TvInputService.Session बनाता है. यह Handler.Callback को लागू करता है, ताकि प्लेयर के स्टेटस में होने वाले बदलावों को मैनेज किया जा सके. onSetSurface के साथ, TvInputService.Session वीडियो सामग्री के साथ Surface सेट करता है. वीडियो रेंडर करने के लिए, Surface का इस्तेमाल करने के बारे में ज़्यादा जानने के लिए, प्लेयर को प्लैटफ़ॉर्म के साथ इंटिग्रेट करना लेख पढ़ें.

जब उपयोगकर्ता कोई चैनल चुनता है, तो TvInputService.Session onTune इवेंट को हैंडल करता है. साथ ही, कॉन्टेंट और कॉन्टेंट के मेटाडेटा में हुए बदलावों के बारे में, सिस्टम टीवी ऐप्लिकेशन को सूचना देता है. इन notify तरीकों के बारे में, इस ट्रेनिंग में आगे कॉन्टेंट कंट्रोल करना और ट्रैक चुनने की सुविधा मैनेज करना लेख में बताया गया है.

अपनी सेटअप गतिविधि को परिभाषित करें

सिस्टम टीवी ऐप्लिकेशन आपके टीवी इनपुट के लिए आपके द्वारा परिभाषित सेटअप ऐक्टिविटी के साथ काम करता है. सेटअप करना ज़रूरी है. साथ ही, सिस्टम डेटाबेस के लिए कम से कम एक चैनल रिकॉर्ड देना ज़रूरी है. जब सिस्टम टीवी ऐप्लिकेशन को टीवी इनपुट के लिए कोई चैनल नहीं मिलता है, तो यह सेटअप ऐक्टिविटी को शुरू कर देता है.

सेटअप गतिविधि सिस्टम टीवी ऐप्लिकेशन को टीवी इनपुट के माध्यम से उपलब्ध कराए गए चैनलों का वर्णन करती है, जैसा कि अगले पाठ में प्रदर्शित किया गया है, चैनल डेटा बनाएं और अपडेट करें.

अन्य रेफ़रंस