चैनल के डेटा का इस्तेमाल करना

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

टीवी इनपुट सर्विस के सैंपल ऐप्लिकेशन को आज़माएं.

अनुमति पाना

ईपीजी डेटा के साथ काम करने के लिए, आपके टीवी इनपुट को अपनी Android मेनिफ़ेस्ट फ़ाइल में, फ़ाइल या एंट्री में बदलाव करने की अनुमति इस तरह से देनी होगी:

<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 - चैनल का डिफ़ॉल्ट वीडियो फ़ॉर्मैट

टीवी इनपुट फ़्रेमवर्क, पारंपरिक ब्रॉडकास्ट और ओवर-द-टॉप (ओटीटी) कॉन्टेंट, दोनों को बिना किसी अंतर के हैंडल करने के लिए काफ़ी सामान्य है. हालांकि, पारंपरिक ब्रॉडकास्ट चैनलों की बेहतर पहचान करने के लिए, इन कॉलम को भी तय किया जा सकता है:

अगर आपको अपने चैनलों के लिए, ऐप्लिकेशन के लिंक की जानकारी देनी है, तो आपको कुछ और फ़ील्ड अपडेट करने होंगे. ऐप्लिकेशन के लिंक वाले फ़ील्ड के बारे में ज़्यादा जानने के लिए, ऐप्लिकेशन के लिंक की जानकारी जोड़ना लेख पढ़ें.

इंटरनेट स्ट्रीमिंग पर आधारित टीवी इनपुट के लिए, अपनी वैल्यू असाइन करें, ताकि हर चैनल की अलग से पहचान की जा सके.

अपने बैकएंड सर्वर से, चैनल का मेटाडेटा (एक्सएमएल, JSON या किसी अन्य फ़ॉर्मैट में) पुल करें. इसके बाद, सेटअप की गतिविधि के दौरान, वैल्यू को सिस्टम डेटाबेस में इस तरह से मैप करें:

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

इस उदाहरण में, channel एक ऑब्जेक्ट है, जिसमें बैकएंड सर्वर से मिला चैनल का मेटाडेटा होता है.

चैनल और प्रोग्राम की जानकारी दिखाना

सिस्टम टीवी ऐप्लिकेशन, उपयोगकर्ताओं को चैनल और प्रोग्राम की जानकारी दिखाता है. यह जानकारी तब दिखती है, जब उपयोगकर्ता चैनलों को बदलता है. पहली इमेज में इसका उदाहरण दिया गया है. यह पक्का करने के लिए कि चैनल और प्रोग्राम की जानकारी, सिस्टम टीवी ऐप्लिकेशन के चैनल और प्रोग्राम की जानकारी दिखाने वाले टूल के साथ काम करे, इन दिशा-निर्देशों का पालन करें:

  1. चैनल नंबर (COLUMN_DISPLAY_NUMBER)
  2. आइकॉन (टीवी इनपुट के मेनिफ़ेस्ट मेंandroid:icon)
  3. प्रोग्राम की जानकारी (COLUMN_SHORT_DESCRIPTION)
  4. प्रोग्राम का टाइटल (COLUMN_TITLE)
  5. चैनल का लोगो (TvContract.Channels.Logo)
    • आसपास के टेक्स्ट से मैच करने के लिए, #EEEEEE रंग का इस्तेमाल करें
    • पैडिंग शामिल न करें
  6. पोस्टर आर्ट (COLUMN_POSTER_ART_URI)
    • आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) 16:9 और 4:3 के बीच होना चाहिए
पहली इमेज. सिस्टम टीवी ऐप्लिकेशन का चैनल और प्रोग्राम की जानकारी दिखाने वाला टूल.

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

दूसरी इमेज. सिस्टम टीवी ऐप्लिकेशन की प्रोग्राम गाइड.

चैनल का डेटा अपडेट करना

मौजूदा चैनल का डेटा अपडेट करते समय, डेटा को मिटाने और फिर से जोड़ने के बजाय, update तरीके का इस्तेमाल करें. अपडेट करने के लिए रिकॉर्ड चुनते समय, Channels.COLUMN_VERSION_NUMBER और Programs.COLUMN_VERSION_NUMBER का इस्तेमाल करके, डेटा का मौजूदा वर्शन पहचाना जा सकता है.

ध्यान दें: ContentProvider में चैनल का डेटा जोड़ने में समय लग सकता है. मौजूदा प्रोग्राम (जो मौजूदा समय से दो घंटे के अंदर दिखाए जाने वाले हैं) सिर्फ़ तब जोड़ें, जब आपने EpgSyncJobService को बैकग्राउंड में चैनल का बाकी डेटा अपडेट करने के लिए कॉन्फ़िगर किया हो. उदाहरण के लिए, Android TV के लाइव टीवी सैंपल ऐप्लिकेशन को देखें.

चैनल का डेटा बैच में लोड करना

सिस्टम डेटाबेस को चैनल के ज़्यादा डेटा के साथ अपडेट करते समय, ContentResolver applyBatch या bulkInsert तरीके का इस्तेमाल करें. 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();
    }
}

चैनल का डेटा एसिंक्रोनस तरीके से प्रोसेस करना

डेटा में बदलाव करने से, यूज़र इंटरफ़ेस (यूआई) थ्रेड ब्लॉक नहीं होना चाहिए. जैसे, सर्वर से स्ट्रीम फ़ेच करना या डेटाबेस ऐक्सेस करना. AsyncTask का इस्तेमाल करके, अपडेट को एसिंक्रोनस तरीके से किया जा सकता है. उदाहरण के लिए, बैकएंड सर्वर से चैनल की जानकारी लोड करते समय, AsyncTask का इस्तेमाल इस तरह किया जा सकता है:

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

अगर आपको ईपीजी डेटा को नियमित तौर पर अपडेट करना है, तो WorkManager का इस्तेमाल करें. इससे अपडेट की प्रोसेस, फ़्री टाइम में चलती है. जैसे, हर दिन सुबह 3:00 बजे.

डेटा अपडेट करने के टास्क को यूज़र इंटरफ़ेस (यूआई) थ्रेड से अलग करने के अन्य तरीकों में, HandlerThread क्लास का इस्तेमाल करना शामिल है. इसके अलावा, Looper और Handler क्लास का इस्तेमाल करके, अपना तरीका भी लागू किया जा सकता है. ज़्यादा जानकारी के लिए, प्रोसेस और थ्रेड लेख पढ़ें.

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

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

चैनल का कॉन्टेंट देखते समय, चुनें बटन दबाने पर, टीवी मेन्यू दिखता है. इस मेन्यू में, ऐप्लिकेशन के लिंक दिखते हैं.

पहली इमेज. चैनल का कॉन्टेंट दिखाते समय, चैनल वाली लाइन पर दिखने वाले ऐप्लिकेशन के लिंक का उदाहरण.

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

ऐप्लिकेशन के लिंक के चैनल का डेटा उपलब्ध कराना

Android TV, हर चैनल के लिए अपने-आप ऐप्लिकेशन का लिंक बनाता है. इसके लिए, वह चैनल के डेटा से मिली जानकारी का इस्तेमाल करता है. ऐप्लिकेशन के लिंक की जानकारी देने के लिए, TvContract.Channels के इन फ़ील्ड में जानकारी दें:

  • COLUMN_APP_LINK_COLOR - इस चैनल के लिए, ऐप्लिकेशन के लिंक का ऐक्सेंट कलर. ऐक्सेंट कलर के उदाहरण के लिए, दूसरी इमेज का कॉलआउट 3 देखें.
  • COLUMN_APP_LINK_ICON_URI - इस चैनल के लिए, ऐप्लिकेशन के लिंक के ऐप्लिकेशन बैज आइकॉन का यूआरआई. ऐप्लिकेशन बैज आइकॉन के उदाहरण के लिए, दूसरी इमेज का कॉलआउट 2 देखें.
  • COLUMN_APP_LINK_INTENT_URI - इस चैनल के लिए, ऐप्लिकेशन के लिंक का इंटेंट यूआरआई. URI_INTENT_SCHEME के साथ toUri(int) का इस्तेमाल करके, यूआरआई बनाया जा सकता है. साथ ही, parseUri की मदद से, यूआरआई को वापस ओरिजनल इंटेंट में बदला जा सकता है.
  • COLUMN_APP_LINK_POSTER_ART_URI - इस चैनल के लिए, ऐप्लिकेशन के लिंक के बैकग्राउंड के तौर पर इस्तेमाल किए गए पोस्टर आर्ट का यूआरआई. पोस्टर इमेज के उदाहरण के लिए, दूसरी इमेज का कॉलआउट 1 देखें.
  • COLUMN_APP_LINK_TEXT - इस चैनल के लिए, ऐप्लिकेशन के लिंक का जानकारी देने वाला लिंक टेक्स्ट. ऐप्लिकेशन के लिंक की जानकारी के उदाहरण के लिए, दूसरी इमेज का कॉलआउट 3 देखें.
दूसरी इमेज. ऐप्लिकेशन के लिंक की जानकारी.

अगर चैनल के डेटा में, ऐप्लिकेशन के लिंक की जानकारी नहीं दी गई है, तो सिस्टम, डिफ़ॉल्ट ऐप्लिकेशन का लिंक बनाता है. सिस्टम, डिफ़ॉल्ट जानकारी इस तरह चुनता है:

  • इंटेंट यूआरआई (COLUMN_APP_LINK_INTENT_URI) के लिए, सिस्टम, CATEGORY_LEANBACK_LAUNCHER कैटगरी के लिए ACTION_MAIN गतिविधि का इस्तेमाल करता है. आम तौर पर, यह गतिविधि ऐप्लिकेशन के मेनिफ़ेस्ट में तय की जाती है. अगर यह गतिविधि तय नहीं की जाती है, तो ऐप्लिकेशन का ऐसा लिंक दिखता है जो काम नहीं करता. इस पर क्लिक करने से कुछ नहीं होता.
  • जानकारी देने वाले टेक्स्ट (COLUMN_APP_LINK_TEXT) के लिए, सिस्टम "app-name खोलें" का इस्तेमाल करता है. अगर ऐप्लिकेशन के लिंक के लिए कोई मान्य इंटेंट यूआरआई तय नहीं किया गया है, तो सिस्टम "कोई लिंक उपलब्ध नहीं है" का इस्तेमाल करता है.
  • ऐक्सेंट कलर (COLUMN_APP_LINK_COLOR) के लिए, सिस्टम, ऐप्लिकेशन के डिफ़ॉल्ट कलर का इस्तेमाल करता है.
  • पोस्टर इमेज (COLUMN_APP_LINK_POSTER_ART_URI) के लिए, सिस्टम, ऐप्लिकेशन के होम स्क्रीन बैनर का इस्तेमाल करता है. अगर ऐप्लिकेशन, बैनर उपलब्ध नहीं कराता है, तो सिस्टम, टीवी ऐप्लिकेशन की डिफ़ॉल्ट इमेज का इस्तेमाल करता है.
  • बैज आइकॉन (COLUMN_APP_LINK_ICON_URI) के लिए, सिस्टम, ऐसा बैज इस्तेमाल करता है जिसमें ऐप्लिकेशन का नाम दिखता है. अगर सिस्टम, पोस्टर इमेज के लिए ऐप्लिकेशन बैनर या ऐप्लिकेशन की डिफ़ॉल्ट इमेज का भी इस्तेमाल कर रहा है, तो ऐप्लिकेशन का बैज नहीं दिखता.

अपने चैनलों के लिए, ऐप्लिकेशन के लिंक की जानकारी, ऐप्लिकेशन की सेटअप गतिविधि में तय करें. ऐप्लिकेशन के लिंक की इस जानकारी को किसी भी समय अपडेट किया जा सकता है. इसलिए, अगर ऐप्लिकेशन के लिंक को चैनल में किए गए बदलावों के हिसाब से अपडेट करना है, तो ऐप्लिकेशन के लिंक की जानकारी अपडेट करें और ज़रूरत के हिसाब से ContentResolver.update को कॉल करें. चैनल का डेटा अपडेट करने के बारे में ज़्यादा जानने के लिए, चैनल का डेटा अपडेट करना लेख पढ़ें.