একটি Android TV অ্যাপ কাস্ট-সক্ষম করুন

1. ওভারভিউ

Google Cast লোগো

এই কোডল্যাব আপনাকে শেখাবে কিভাবে আপনার বিদ্যমান কাস্ট প্রেরক অ্যাপ থেকে কাস্টিং এবং যোগাযোগ সমর্থন করার জন্য একটি বিদ্যমান Android TV অ্যাপ পরিবর্তন করতে হয়।

Google Cast এবং Cast Connect কি?

Google Cast ব্যবহারকারীদের একটি মোবাইল ডিভাইস থেকে একটি টিভিতে সামগ্রী কাস্ট করার অনুমতি দেয়৷ একটি সাধারণ Google Cast সেশনে দুটি উপাদান থাকে — একটি প্রেরক এবং একটি রিসিভার অ্যাপ্লিকেশন৷ প্রেরক অ্যাপ্লিকেশন, যেমন একটি মোবাইল অ্যাপ বা ওয়েবসাইট যেমন Youtube.com, একটি কাস্ট রিসিভার অ্যাপ্লিকেশনের প্লেব্যাক শুরু এবং নিয়ন্ত্রণ করে৷ কাস্ট রিসিভার অ্যাপ্লিকেশনগুলি হল HTML 5 অ্যাপ্লিকেশন যা Chromecast এবং Android TV ডিভাইসে চলে৷

কাস্ট সেশনের প্রায় সমস্ত রাজ্যই রিসিভার অ্যাপ্লিকেশনে সংরক্ষণ করা হয়। যখন স্টেট আপডেট হয়, উদাহরণস্বরূপ যদি একটি নতুন মিডিয়া আইটেম লোড করা হয়, একটি মিডিয়া স্ট্যাটাস সমস্ত প্রেরকের কাছে সম্প্রচার করা হয়। এই সম্প্রচারগুলিতে কাস্ট সেশনের বর্তমান অবস্থা রয়েছে৷ প্রেরক অ্যাপ্লিকেশনগুলি তাদের UI এ প্লেব্যাক তথ্য প্রদর্শন করতে এই মিডিয়া স্থিতি ব্যবহার করে৷

কাস্ট কানেক্ট এই পরিকাঠামোর উপরে তৈরি করে, আপনার Android TV অ্যাপটি রিসিভার হিসেবে কাজ করে। কাস্ট কানেক্ট লাইব্রেরি আপনার Android TV অ্যাপকে বার্তা গ্রহণ করতে এবং মিডিয়া স্ট্যাটাস সম্প্রচার করতে দেয় যেন এটি একটি কাস্ট রিসিভার অ্যাপ্লিকেশন।

আমরা কি নির্মাণ করা যাচ্ছে?

আপনি যখন এই কোডল্যাবটি সম্পূর্ণ করবেন, তখন আপনি একটি Android TV অ্যাপে ভিডিও কাস্ট করতে কাস্ট প্রেরক অ্যাপ ব্যবহার করতে পারবেন। Android TV অ্যাপটি কাস্ট প্রোটোকলের মাধ্যমে প্রেরক অ্যাপের সাথেও যোগাযোগ করতে পারে।

আপনি কি শিখবেন

  • একটি নমুনা ATV অ্যাপে কাস্ট কানেক্ট লাইব্রেরি কীভাবে যোগ করবেন।
  • কীভাবে একজন কাস্ট প্রেরককে সংযুক্ত করবেন এবং ATV অ্যাপ চালু করবেন।
  • একটি কাস্ট প্রেরক অ্যাপ থেকে ATV অ্যাপে মিডিয়া প্লেব্যাক কীভাবে শুরু করবেন।
  • কিভাবে ATV অ্যাপ থেকে কাস্ট প্রেরক অ্যাপে মিডিয়া স্ট্যাটাস পাঠাবেন।

আপনি কি প্রয়োজন হবে

2। নমুনা কোড পান

আপনি আপনার কম্পিউটারে সমস্ত নমুনা কোড ডাউনলোড করতে পারেন...

এবং ডাউনলোড করা জিপ ফাইলটি আনপ্যাক করুন।

3. নমুনা অ্যাপ চালান

প্রথমে, দেখা যাক সম্পূর্ণ নমুনা অ্যাপটি কেমন দেখাচ্ছে। Android TV অ্যাপটি Leanback UI এবং একটি মৌলিক ভিডিও প্লেয়ার ব্যবহার করে। ব্যবহারকারী একটি তালিকা থেকে একটি ভিডিও নির্বাচন করতে পারেন যা নির্বাচন করা হলে টিভিতে প্লে হয়৷ সহগামী মোবাইল প্রেরক অ্যাপের মাধ্যমে, একজন ব্যবহারকারী Android TV অ্যাপে একটি ভিডিও কাস্ট করতে পারেন।

ভিডিও থাম্বনেইলের একটি সিরিজের ছবি (যার মধ্যে একটি হাইলাইট করা হয়েছে) একটি ভিডিওর একটি পূর্ণ-স্ক্রীন প্রিভিউ ওভারলে করে; 'কাস্ট কানেক্ট' শব্দটি উপরের ডানদিকে প্রদর্শিত হচ্ছে

বিকাশকারী ডিভাইসগুলি নিবন্ধন করুন

In order to enable Cast Connect capabilities for application development you must register the serial number of the Android TV device's built-in Chromecast that you are going to use in the Cast Developer Console . আপনি আপনার Android TV-তে সেটিংস > ডিভাইস পছন্দ > Chromecast বিল্ট-ইন > সিরিয়াল নম্বরে গিয়ে সিরিয়াল নম্বর খুঁজে পেতে পারেন। মনে রাখবেন যে এটি আপনার শারীরিক ডিভাইসের সিরিয়াল নম্বর থেকে আলাদা এবং উপরে বর্ণিত পদ্ধতি থেকে প্রাপ্ত করা আবশ্যক।

Image of an Android TV screen showing the 'Chromecast built-in' screen, the Version number and Serial number

রেজিস্ট্রেশন ছাড়াই, নিরাপত্তার কারণে কাস্ট কানেক্ট শুধুমাত্র Google Play স্টোর থেকে ইনস্টল করা অ্যাপের জন্য কাজ করবে। রেজিস্ট্রেশন প্রক্রিয়া শুরু করার 15 মিনিট পরে, আপনার ডিভাইস পুনরায় চালু করুন।

অ্যান্ড্রয়েড প্রেরক অ্যাপটি ইনস্টল করুন

একটি মোবাইল ডিভাইস থেকে অনুরোধ পাঠানোর পরীক্ষা করার জন্য আমরা সোর্স কোড জিপ ডাউনলোডে কাস্ট ভিডিও হিসাবে mobile-sender-0629.apk .apk ফাইল নামে একটি সাধারণ প্রেরক অ্যাপ্লিকেশন সরবরাহ করেছি। আমরা APK ইন্সটল করতে ADB-এর সাহায্য নেব। আপনি যদি ইতিমধ্যেই কাস্ট ভিডিওগুলির একটি ভিন্ন সংস্করণ ইনস্টল করে থাকেন, তাহলে অনুগ্রহ করে চালিয়ে যাওয়ার আগে ডিভাইসে অবস্থিত সমস্ত প্রোফাইল থেকে সেই সংস্করণটিকে আনইনস্টল করুন৷

  1. আপনার Android ফোনে বিকাশকারী বিকল্প এবং USB ডিবাগিং সক্ষম করুন
  2. আপনার ডেভেলপমেন্ট কম্পিউটারের সাথে আপনার অ্যান্ড্রয়েড ফোন সংযোগ করতে একটি USB ডেটা কেবল প্লাগ ইন করুন৷
  3. আপনার Android ফোনে mobile-sender-0629.apk ইনস্টল করুন।

mobile-sender.apk ইনস্টল করার জন্য adb install কমান্ড চালানোর একটি টার্মিনাল উইন্ডোর চিত্র৷

  1. আপনি আপনার Android ফোনে কাস্ট ভিডিও প্রেরক অ্যাপটি খুঁজে পেতে পারেন৷ কাস্ট ভিডিও প্রেরক অ্যাপ আইকন

একটি Android ফোনের স্ক্রিনে চলমান কাস্ট ভিডিও প্রেরক অ্যাপের চিত্র৷

Android TV অ্যাপটি ইনস্টল করুন

নিম্নলিখিত নির্দেশাবলী বর্ণনা করে কিভাবে অ্যান্ড্রয়েড স্টুডিওতে সম্পূর্ণ নমুনা অ্যাপটি খুলতে এবং চালাতে হয়:

  1. স্বাগতম স্ক্রিনে আমদানি প্রকল্প বা ফাইল > নতুন > আমদানি প্রকল্প... মেনু বিকল্প নির্বাচন করুন।
  2. নির্বাচন করুন ফোল্ডার আইকন নমুনা কোড ফোল্ডার থেকে app-done ডিরেক্টরি এবং ঠিক আছে ক্লিক করুন.
  3. ফাইল > ক্লিক করুন গ্রেডল বোতাম সহ অ্যান্ড্রয়েড অ্যাপ স্টুডিওর সিঙ্ক প্রকল্প গ্রেডল ফাইলের সাথে প্রকল্প সিঙ্ক করুন
  4. আপনার Android TV ডিভাইসে বিকাশকারী বিকল্প এবং USB ডিবাগিং সক্ষম করুন
  5. আপনার অ্যান্ড্রয়েড টিভি ডিভাইসের সাথে ADB কানেক্ট করুন, ডিভাইসটি অ্যান্ড্রয়েড স্টুডিওতে দেখাতে হবে। অ্যান্ড্রয়েড স্টুডিও টুলবারে প্রদর্শিত অ্যান্ড্রয়েড টিভি ডিভাইসটি দেখানো ছবি
  6. ক্লিক করুন অ্যান্ড্রয়েড স্টুডিও রান বোতাম, একটি সবুজ ত্রিভুজ ডানদিকে নির্দেশ করে রান বোতাম, আপনি কাস্ট কানেক্ট কোডল্যাব নামের ATV অ্যাপটি কয়েক সেকেন্ড পরে প্রদর্শিত হবে দেখতে পাবেন।

আসুন ATV অ্যাপের সাথে Cast Connect খেলি

  1. Android TV হোম স্ক্রিনে যান।
  2. আপনার অ্যান্ড্রয়েড ফোন থেকে কাস্ট ভিডিও প্রেরক অ্যাপ খুলুন। কাস্ট বোতামে ক্লিক করুন কাস্ট বোতাম আইকন এবং আপনার ATV ডিভাইস নির্বাচন করুন।
  3. Cast Connect Codelab ATV অ্যাপটি আপনার ATV-তে চালু হবে এবং আপনার প্রেরকের কাস্ট বোতামটি নির্দেশ করবে যে এটি সংযুক্ত আছে উল্টানো রং সহ কাস্ট বোতাম আইকন .
  4. ATV অ্যাপ থেকে একটি ভিডিও নির্বাচন করুন এবং ভিডিওটি আপনার ATV-তে চলতে শুরু করবে।
  5. আপনার মোবাইল ফোনে, একটি মিনি কন্ট্রোলার এখন আপনার প্রেরক অ্যাপের নীচে দৃশ্যমান। আপনি প্লেব্যাক নিয়ন্ত্রণ করতে প্লে/পজ বোতাম ব্যবহার করতে পারেন।
  6. মোবাইল ফোন থেকে একটি ভিডিও নির্বাচন করুন এবং প্লে করুন। ভিডিওটি আপনার ATV-তে বাজানো শুরু হবে এবং প্রসারিত কন্ট্রোলারটি আপনার মোবাইল প্রেরকের উপর প্রদর্শিত হবে।
  7. আপনার ফোন লক করুন এবং আপনি যখন এটি আনলক করেন, তখন মিডিয়া প্লেব্যাক নিয়ন্ত্রণ করতে বা কাস্টিং বন্ধ করতে আপনার লক স্ক্রিনে একটি বিজ্ঞপ্তি দেখতে হবে৷

একটি মিনিপ্লেয়ার সহ একটি ভিডিও চালানোর সাথে Android ফোনের স্ক্রিনের একটি অংশের চিত্র৷

4. শুরু প্রকল্প প্রস্তুত করুন

এখন যেহেতু আমরা সম্পূর্ণ অ্যাপের কাস্ট কানেক্ট ইন্টিগ্রেশন যাচাই করেছি, আমাদের আপনার ডাউনলোড করা স্টার্ট অ্যাপে কাস্ট কানেক্টের জন্য সমর্থন যোগ করতে হবে। এখন আপনি অ্যান্ড্রয়েড স্টুডিও ব্যবহার করে স্টার্টার প্রকল্পের শীর্ষে তৈরি করতে প্রস্তুত:

  1. স্বাগতম স্ক্রিনে আমদানি প্রকল্প বা ফাইল > নতুন > আমদানি প্রকল্প... মেনু বিকল্প নির্বাচন করুন।
  2. নির্বাচন করুন ফোল্ডার আইকন নমুনা কোড ফোল্ডার থেকে app-start ডিরেক্টরি এবং ঠিক আছে ক্লিক করুন.
  3. ফাইল > ক্লিক করুন গ্রেডল বোতাম সহ অ্যান্ড্রয়েড স্টুডিওর সিঙ্ক প্রকল্প গ্রেডল ফাইলের সাথে প্রকল্প সিঙ্ক করুন
  4. ATV ডিভাইস নির্বাচন করুন এবং ক্লিক করুন অ্যান্ড্রয়েড স্টুডিওর রান বোতাম, একটি সবুজ ত্রিভুজ ডানদিকে নির্দেশ করছে অ্যাপটি চালাতে এবং UI অন্বেষণ করতে চালান বোতাম। Android Studio টুলবার নির্বাচিত Android TV ডিভাইস দেখাচ্ছে

ভিডিও থাম্বনেইলের একটি সিরিজের ছবি (যার মধ্যে একটি হাইলাইট করা হয়েছে) একটি ভিডিওর একটি পূর্ণ-স্ক্রীন প্রিভিউ ওভারলে করে; 'কাস্ট কানেক্ট' শব্দটি উপরের ডানদিকে প্রদর্শিত হচ্ছে

অ্যাপ ডিজাইন

অ্যাপটি ব্যবহারকারীকে ব্রাউজ করার জন্য ভিডিওগুলির একটি তালিকা প্রদান করে। ব্যবহারকারীরা অ্যান্ড্রয়েড টিভিতে চালানোর জন্য একটি ভিডিও নির্বাচন করতে পারেন। অ্যাপটিতে দুটি প্রধান ক্রিয়াকলাপ রয়েছে: MainActivity এবং PlaybackActivity

প্রধান কার্যকলাপ

এই ক্রিয়াকলাপে একটি ফ্র্যাগমেন্ট রয়েছে ( MainFragment )। ভিডিওগুলির তালিকা এবং তাদের সম্পর্কিত মেটাডেটা MovieList ক্লাসে কনফিগার করা হয় এবং Movie অবজেক্টের একটি তালিকা তৈরি করতে setupMovies() পদ্ধতি বলা হয়।

একটি Movie অবজেক্ট শিরোনাম, বর্ণনা, ইমেজ থাম্বস এবং ভিডিও ইউআরএল সহ একটি ভিডিও সত্তাকে উপস্থাপন করে। প্রতিটি Movie অবজেক্ট শিরোনাম এবং স্টুডিও সহ ভিডিও থাম্বনেল উপস্থাপন করার জন্য একটি CardPresenter সাথে আবদ্ধ এবং ArrayObjectAdapter এ পাস করা হয়।

যখন একটি আইটেম নির্বাচন করা হয়, সংশ্লিষ্ট Movie অবজেক্টটি PlaybackActivity পাস করা হয়।

প্লেব্যাক কার্যকলাপ

এই ক্রিয়াকলাপে একটি ফ্র্যাগমেন্ট ( PlaybackVideoFragment ) রয়েছে যা ExoPlayer সহ একটি VideoView হোস্ট করে, কিছু মিডিয়া নিয়ন্ত্রণ এবং নির্বাচিত ভিডিওর বিবরণ দেখানোর জন্য একটি পাঠ্য অঞ্চল এবং ব্যবহারকারীকে Android TV-তে ভিডিওটি চালানোর অনুমতি দেয়৷ ব্যবহারকারী রিমোট কন্ট্রোল ব্যবহার করে প্লে/পজ করতে বা ভিডিওর প্লেব্যাক চাইতে পারেন।

কাস্ট কানেক্টের পূর্বশর্ত

কাস্ট কানেক্ট Google Play পরিষেবাগুলির নতুন সংস্করণ ব্যবহার করে যার জন্য AndroidX নামস্থান ব্যবহার করার জন্য আপনার ATV অ্যাপ আপডেট করা প্রয়োজন৷

আপনার Android TV অ্যাপে Cast Connect সমর্থন করার জন্য, আপনাকে অবশ্যই একটি মিডিয়া সেশন থেকে ইভেন্ট তৈরি এবং সমর্থন করতে হবে। কাস্ট কানেক্ট লাইব্রেরি মিডিয়া সেশনের অবস্থার উপর ভিত্তি করে মিডিয়া স্ট্যাটাস তৈরি করে। আপনার মিডিয়া সেশনটি কাস্ট কানেক্ট লাইব্রেরি দ্বারা সংকেত দেওয়ার জন্যও ব্যবহৃত হয় যখন এটি কোনও প্রেরকের কাছ থেকে কিছু বার্তা পেয়েছে, যেমন বিরতি।

5. Configuring Cast Support

নির্ভরতা

প্রয়োজনীয় লাইব্রেরি নির্ভরতা অন্তর্ভুক্ত করতে অ্যাপ build.gradle ফাইলটি আপডেট করুন:

dependencies {
    ....

    // Cast Connect libraries
    implementation 'com.google.android.gms:play-services-cast-tv:20.0.0'
    implementation 'com.google.android.gms:play-services-cast:21.1.0'
}

ত্রুটি ছাড়াই প্রজেক্ট বিল্ড নিশ্চিত করতে প্রকল্পটি সিঙ্ক করুন।

সূচনা

CastReceiverContext হল সমস্ত কাস্ট মিথস্ক্রিয়া সমন্বয় করার জন্য একটি একক বস্তু। CastReceiverContext আরম্ভ হলে CastReceiverOptions প্রদান করতে আপনাকে ReceiverOptionsProvider ইন্টারফেস প্রয়োগ করতে হবে।

CastReceiverOptionsProvider.kt ফাইল তৈরি করুন এবং প্রকল্পে নিম্নলিখিত ক্লাস যোগ করুন:

package com.google.sample.cast.castconnect

import android.content.Context
import com.google.android.gms.cast.tv.ReceiverOptionsProvider
import com.google.android.gms.cast.tv.CastReceiverOptions

class CastReceiverOptionsProvider : ReceiverOptionsProvider {
    override fun getOptions(context: Context): CastReceiverOptions {
        return CastReceiverOptions.Builder(context)
                .setStatusText("Cast Connect Codelab")
                .build()
    }
}

তারপর AndroidManifest.xml ফাইলের <application> ট্যাগের মধ্যে রিসিভার বিকল্প প্রদানকারী নির্দিষ্ট করুন:

<application>
  ...
  <meta-data
    android:name="com.google.android.gms.cast.tv.RECEIVER_OPTIONS_PROVIDER_CLASS_NAME"
    android:value="com.google.sample.cast.castconnect.CastReceiverOptionsProvider" />
</application>

আপনার কাস্ট প্রেরক থেকে আপনার ATV অ্যাপের সাথে সংযোগ করতে, আপনি লঞ্চ করতে চান এমন একটি কার্যকলাপ নির্বাচন করুন৷ এই কোডল্যাবে, একটি কাস্ট সেশন শুরু হলে আমরা অ্যাপটির MainActivity চালু করব। AndroidManifest.xml ফাইলে, MainActivity এ লঞ্চ ইনটেন্ট ফিল্টার যোগ করুন।

<activity android:name=".MainActivity">
  ...
  <intent-filter>
    <action android:name="com.google.android.gms.cast.tv.action.LAUNCH" />
    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

কাস্ট রিসিভার প্রসঙ্গ জীবনচক্র

আপনার অ্যাপ চালু হলে আপনার CastReceiverContext শুরু করা উচিত এবং আপনার অ্যাপটি ব্যাকগ্রাউন্ডে সরানো হলে CastReceiverContext বন্ধ করা উচিত। CastReceiverContext.start() এবং CastReceiverContext.stop() কলিং পরিচালনা করতে আমরা আপনাকে androidx.lifecycle লাইব্রেরি থেকে LifecycleObserver ব্যবহার করার পরামর্শ দিচ্ছি।

MyApplication.kt ফাইল খুলুন, অ্যাপ্লিকেশনের onCreate পদ্ধতিতে initInstance() কল করে কাস্ট প্রসঙ্গ শুরু করুন। AppLifeCycleObserver ক্লাসে অ্যাপ্লিকেশনটি পুনরায় শুরু হলে CastReceiverContext start() এবং অ্যাপ্লিকেশনটি বিরতি দেওয়া হলে এটি stop() :

package com.google.sample.cast.castconnect

import com.google.android.gms.cast.tv.CastReceiverContext
...

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        CastReceiverContext.initInstance(this)
        ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycleObserver())
    }

    class AppLifecycleObserver : DefaultLifecycleObserver {
        override fun onResume(owner: LifecycleOwner) {
            Log.d(LOG_TAG, "onResume")
            CastReceiverContext.getInstance().start()
        }

        override fun onPause(owner: LifecycleOwner) {
            Log.d(LOG_TAG, "onPause")
            CastReceiverContext.getInstance().stop()
        }
    }
}

MediaSession-কে MediaManager-এর সাথে সংযুক্ত করা হচ্ছে

MediaManager হল CastReceiverContext সিঙ্গলটনের একটি সম্পত্তি, এটি মিডিয়া স্ট্যাটাস পরিচালনা করে, লোডের উদ্দেশ্য পরিচালনা করে, প্রেরকদের থেকে মিডিয়া নেমস্পেস বার্তাগুলিকে মিডিয়া কমান্ডে অনুবাদ করে এবং প্রেরকদের কাছে মিডিয়া স্ট্যাটাস ফেরত পাঠায়।

আপনি যখন একটি MediaSession তৈরি করেন, তখন আপনাকে MediaManager কে বর্তমান MediaSession টোকেন প্রদান করতে হবে যাতে এটি কোথায় কমান্ড পাঠাতে হয় এবং মিডিয়া প্লেব্যাক অবস্থা পুনরুদ্ধার করতে পারে তা জানে। PlaybackVideoFragment.kt ফাইলে, MediaManager এ টোকেন সেট করার আগে MediaSession আরম্ভ করা হয়েছে তা নিশ্চিত করুন।

import com.google.android.gms.cast.tv.CastReceiverContext
import com.google.android.gms.cast.tv.media.MediaManager
...

class PlaybackVideoFragment : VideoSupportFragment() {
    private var castReceiverContext: CastReceiverContext? = null
    ...

    private fun initializePlayer() {
        if (mPlayer == null) {
            ...
            mMediaSession = MediaSessionCompat(getContext(), LOG_TAG)
            ...
            castReceiverContext = CastReceiverContext.getInstance()
            if (castReceiverContext != null) {
                val mediaManager: MediaManager = castReceiverContext!!.getMediaManager()
                mediaManager.setSessionCompatToken(mMediaSession!!.getSessionToken())
            }

        }
    }
}

নিষ্ক্রিয় প্লেব্যাকের কারণে আপনি যখন আপনার MediaSession প্রকাশ করেন, তখন আপনার MediaManager এ একটি নাল টোকেন সেট করা উচিত:

private fun releasePlayer() {
    mMediaSession?.release()
    castReceiverContext?.mediaManager?.setSessionCompatToken(null)
    ...
}

এর নমুনা অ্যাপ রান করা যাক

ক্লিক করুন অ্যান্ড্রয়েড স্টুডিওর রান বোতাম, একটি সবুজ ত্রিভুজ ডানদিকে নির্দেশ করে আপনার ATV ডিভাইসে অ্যাপ স্থাপন করতে চালান বোতাম, অ্যাপ বন্ধ করুন এবং ATV হোম স্ক্রিনে ফিরে যান। আপনার প্রেরকের কাছ থেকে, কাস্ট বোতামে ক্লিক করুন কাস্ট বোতাম আইকন এবং আপনার ATV ডিভাইস নির্বাচন করুন। আপনি দেখতে পাবেন ATV অ্যাপটি ATV ডিভাইসে চালু হয়েছে এবং কাস্ট বোতামের অবস্থা সংযুক্ত রয়েছে।

6. মিডিয়া লোড হচ্ছে

লোড কমান্ডটি ডেভেলপার কনসোলে আপনার সংজ্ঞায়িত প্যাকেজ নামের সাথে একটি উদ্দেশ্যের মাধ্যমে পাঠানো হয়। এই অভিপ্রায়টি যে টার্গেট অ্যাক্টিভিটি গ্রহণ করবে তা নির্দিষ্ট করতে আপনাকে আপনার Android TV অ্যাপে নিম্নলিখিত পূর্বনির্ধারিত অভিপ্রায় ফিল্টার যোগ করতে হবে। AndroidManifest.xml ফাইলে, PlayerActivity তে লোড ইনটেন্ট ফিল্টার যোগ করুন:

<activity android:name="com.google.sample.cast.castconnect.PlaybackActivity"
          android:launchMode="singleTask"
          android:exported="true">
  <intent-filter>
     <action android:name="com.google.android.gms.cast.tv.action.LOAD"/>
     <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

অ্যান্ড্রয়েড টিভিতে লোডের অনুরোধগুলি পরিচালনা করা

এখন যেহেতু কার্যকলাপটি একটি লোড অনুরোধ সহ এই অভিপ্রায়টি পাওয়ার জন্য কনফিগার করা হয়েছে আমাদের এটি পরিচালনা করতে হবে৷

অ্যাপ্লিকেশানটি যখন কার্যকলাপ শুরু হয় তখন processIntent নামে একটি ব্যক্তিগত পদ্ধতিকে কল করে। এই পদ্ধতিতে ইনকামিং ইন্টেন্ট প্রক্রিয়াকরণের জন্য যুক্তি রয়েছে। একটি লোড অনুরোধ পরিচালনা করতে আমরা এই পদ্ধতিটি সংশোধন করব এবং MediaManager ইনস্ট্যান্সের onNewIntent পদ্ধতিতে কল করে আরও প্রক্রিয়াকরণের অভিপ্রায় পাঠাব। যদি MediaManager শনাক্ত করে যে উদ্দেশ্যটি একটি লোড অনুরোধ, এটি অভিপ্রায় থেকে MediaLoadRequestData অবজেক্টটি বের করে এবং MediaLoadCommandCallback.onLoad() আহ্বান করে। লোড অনুরোধ ধারণকারী অভিপ্রায় পরিচালনা করতে PlaybackVideoFragment.kt ফাইলে processIntent পদ্ধতি পরিবর্তন করুন:

fun processIntent(intent: Intent?) {
    val mediaManager: MediaManager = CastReceiverContext.getInstance().getMediaManager()
    // Pass intent to Cast SDK
    if (mediaManager.onNewIntent(intent)) {
        return
    }

    // Clears all overrides in the modifier.
    mediaManager.getMediaStatusModifier().clear()

    // If the SDK doesn't recognize the intent, handle the intent with your own logic.
    ...
}

এর পরে আমরা বিমূর্ত ক্লাস MediaLoadCommandCallback প্রসারিত করব যা MediaManager দ্বারা কল করা onLoad() পদ্ধতিটিকে ওভাররাইড করবে। এই পদ্ধতিটি লোড অনুরোধের ডেটা গ্রহণ করে এবং এটিকে একটি Movie অবজেক্টে রূপান্তর করে। একবার রূপান্তরিত হলে, মুভিটি স্থানীয় প্লেয়ার দ্বারা বাজানো হয়। MediaManager তারপর MediaLoadRequest এর সাথে আপডেট করা হয় এবং সংযুক্ত প্রেরকদের কাছে MediaStatus সম্প্রচার করে। PlaybackVideoFragment.kt ফাইলে MyMediaLoadCommandCallback নামে একটি নেস্টেড প্রাইভেট ক্লাস তৈরি করুন:

import com.google.android.gms.cast.MediaLoadRequestData
import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaMetadata
import com.google.android.gms.cast.MediaError
import com.google.android.gms.cast.tv.media.MediaException
import com.google.android.gms.cast.tv.media.MediaCommandCallback
import com.google.android.gms.cast.tv.media.QueueUpdateRequestData
import com.google.android.gms.cast.tv.media.MediaLoadCommandCallback
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
import android.widget.Toast
...

private inner class MyMediaLoadCommandCallback :  MediaLoadCommandCallback() {
    override fun onLoad(
        senderId: String?, mediaLoadRequestData: MediaLoadRequestData): Task<MediaLoadRequestData> {
        Toast.makeText(activity, "onLoad()", Toast.LENGTH_SHORT).show()
        return if (mediaLoadRequestData == null) {
            // Throw MediaException to indicate load failure.
            Tasks.forException(MediaException(
                MediaError.Builder()
                    .setDetailedErrorCode(MediaError.DetailedErrorCode.LOAD_FAILED)
                    .setReason(MediaError.ERROR_REASON_INVALID_REQUEST)
                    .build()))
        } else Tasks.call {
            play(convertLoadRequestToMovie(mediaLoadRequestData)!!)
            // Update media metadata and state
            val mediaManager = castReceiverContext!!.mediaManager
            mediaManager.setDataFromLoad(mediaLoadRequestData)
            mediaLoadRequestData
        }
    }
}

private fun convertLoadRequestToMovie(mediaLoadRequestData: MediaLoadRequestData?): Movie? {
    if (mediaLoadRequestData == null) {
        return null
    }
    val mediaInfo: MediaInfo = mediaLoadRequestData.getMediaInfo() ?: return null
    var videoUrl: String = mediaInfo.getContentId()
    if (mediaInfo.getContentUrl() != null) {
        videoUrl = mediaInfo.getContentUrl()
    }
    val metadata: MediaMetadata = mediaInfo.getMetadata()
    val movie = Movie()
    movie.videoUrl = videoUrl
    movie.title = metadata?.getString(MediaMetadata.KEY_TITLE)
    movie.description = metadata?.getString(MediaMetadata.KEY_SUBTITLE)
    if(metadata?.hasImages() == true) {
        movie.cardImageUrl = metadata.images[0].url.toString()
    }
    return movie
}

এখন যেহেতু কলব্যাক সংজ্ঞায়িত করা হয়েছে, আমাদের এটিকে MediaManager এ নিবন্ধন করতে হবে। MediaManager.onNewIntent() কল করার আগে কলব্যাকটি অবশ্যই নিবন্ধিত হতে হবে৷ প্লেয়ার শুরু হলে setMediaLoadCommandCallback যোগ করুন:

private fun initializePlayer() {
    if (mPlayer == null) {
        ...
        mMediaSession = MediaSessionCompat(getContext(), LOG_TAG)
        ...
        castReceiverContext = CastReceiverContext.getInstance()
        if (castReceiverContext != null) {
            val mediaManager: MediaManager = castReceiverContext.getMediaManager()
            mediaManager.setSessionCompatToken(mMediaSession.getSessionToken())
            mediaManager.setMediaLoadCommandCallback(MyMediaLoadCommandCallback())
        }
    }
}

এর নমুনা অ্যাপ রান করা যাক

ক্লিক করুন অ্যান্ড্রয়েড স্টুডিওর রান বোতাম, একটি সবুজ ত্রিভুজ ডানদিকে নির্দেশ করে আপনার ATV ডিভাইসে অ্যাপটি স্থাপন করতে চালান বোতাম। আপনার প্রেরকের কাছ থেকে, কাস্ট বোতামে ক্লিক করুন কাস্ট বোতাম আইকন and select your ATV device. ATV অ্যাপটি ATV ডিভাইসে চালু হবে। মোবাইলে একটি ভিডিও নির্বাচন করুন, ভিডিওটি এটিভিতে প্লে শুরু হবে। আপনি আপনার ফোনে একটি বিজ্ঞপ্তি পেয়েছেন কিনা তা পরীক্ষা করুন যেখানে আপনার প্লেব্যাক নিয়ন্ত্রণ রয়েছে৷ কন্ট্রোল ব্যবহার করে দেখুন যেমন বিরতি, ATV ডিভাইসে ভিডিও পজ করা উচিত।

7. কাস্ট কন্ট্রোল কমান্ড সমর্থন করে

বর্তমান অ্যাপ্লিকেশনটি এখন মৌলিক কমান্ড সমর্থন করে যা একটি মিডিয়া সেশনের সাথে সামঞ্জস্যপূর্ণ, যেমন খেলা, বিরতি এবং অনুসন্ধান। যাইহোক, কিছু কাস্ট কন্ট্রোল কমান্ড আছে যেগুলো মিডিয়া সেশনে পাওয়া যায় না। সেই কাস্ট কন্ট্রোল কমান্ডগুলিকে সমর্থন করার জন্য আপনাকে একটি MediaCommandCallback নিবন্ধন করতে হবে৷

যখন প্লেয়ারটি আরম্ভ করা হয় তখন setMediaCommandCallback ব্যবহার করে MediaManager ইনস্ট্যান্সে MyMediaCommandCallback যোগ করুন:

private fun initializePlayer() {
    ...
    castReceiverContext = CastReceiverContext.getInstance()
    if (castReceiverContext != null) {
        val mediaManager = castReceiverContext!!.mediaManager
        ...
        mediaManager.setMediaCommandCallback(MyMediaCommandCallback())
    }
}

কাস্ট কন্ট্রোল কমান্ডগুলিকে সমর্থন করার জন্য onQueueUpdate() মতো পদ্ধতিগুলিকে ওভাররাইড করতে MyMediaCommandCallback ক্লাস তৈরি করুন:

private inner class MyMediaCommandCallback : MediaCommandCallback() {
    override fun onQueueUpdate(
        senderId: String?,
        queueUpdateRequestData: QueueUpdateRequestData
    ): Task<Void> {
        Toast.makeText(getActivity(), "onQueueUpdate()", Toast.LENGTH_SHORT).show()
        // Queue Prev / Next
        if (queueUpdateRequestData.getJump() != null) {
            Toast.makeText(
                getActivity(),
                "onQueueUpdate(): Jump = " + queueUpdateRequestData.getJump(),
                Toast.LENGTH_SHORT
            ).show()
        }
        return super.onQueueUpdate(senderId, queueUpdateRequestData)
    }
}

8. মিডিয়া স্ট্যাটাস নিয়ে কাজ করা

মিডিয়া স্থিতি পরিবর্তন করা হচ্ছে

কাস্ট কানেক্ট মিডিয়া সেশন থেকে বেস মিডিয়া স্ট্যাটাস পায়। উন্নত বৈশিষ্ট্যগুলিকে সমর্থন করার জন্য, আপনার Android TV অ্যাপটি MediaStatusModifier মাধ্যমে অতিরিক্ত স্থিতি বৈশিষ্ট্যগুলি নির্দিষ্ট করতে এবং ওভাররাইড করতে পারে৷ MediaStatusModifier সবসময় MediaSession এ কাজ করবে যা আপনি CastReceiverContext এ সেট করেছেন।

উদাহরণস্বরূপ, onLoad কলব্যাক ট্রিগার হলে setMediaCommandSupported নির্দিষ্ট করতে:

import com.google.android.gms.cast.MediaStatus
...
private class MyMediaLoadCommandCallback : MediaLoadCommandCallback() {
    fun onLoad(
        senderId: String?,
        mediaLoadRequestData: MediaLoadRequestData
    ): Task<MediaLoadRequestData> {
        Toast.makeText(getActivity(), "onLoad()", Toast.LENGTH_SHORT).show()
        ...
        return Tasks.call({
            play(convertLoadRequestToMovie(mediaLoadRequestData)!!)
            ...
            // Use MediaStatusModifier to provide additional information for Cast senders.
            mediaManager.getMediaStatusModifier()
                .setMediaCommandSupported(MediaStatus.COMMAND_QUEUE_NEXT, true)
                .setIsPlayingAd(false)
            mediaManager.broadcastMediaStatus()
            // Return the resolved MediaLoadRequestData to indicate load success.
            mediaLoadRequestData
        })
    }
}

পাঠানোর আগে মিডিয়া স্ট্যাটাস আটকানো

Similar to the Web receiver SDK's MessageInterceptor , you can specify a MediaStatusWriter in your MediaManager to perform additional modifications to your MediaStatus before it is broadcast to the connected senders.

উদাহরণস্বরূপ, আপনি মোবাইল প্রেরকদের পাঠানোর আগে MediaStatus এ কাস্টম ডেটা সেট করতে পারেন:

import com.google.android.gms.cast.tv.media.MediaManager.MediaStatusInterceptor
import com.google.android.gms.cast.tv.media.MediaStatusWriter
import org.json.JSONObject
import org.json.JSONException
...

private fun initializePlayer() {
    if (mPlayer == null) {
        ...
        if (castReceiverContext != null) {
            ...
            val mediaManager: MediaManager = castReceiverContext.getMediaManager()
            ...
            // Use MediaStatusInterceptor to process the MediaStatus before sending out.
            mediaManager.setMediaStatusInterceptor(
                MediaStatusInterceptor { mediaStatusWriter: MediaStatusWriter ->
                    try {
                        mediaStatusWriter.setCustomData(JSONObject("{myData: 'CustomData'}"))
                    } catch (e: JSONException) {
                        Log.e(LOG_TAG,e.message,e);
                    }
            })
        }
    }
}        

9. অভিনন্দন

আপনি এখন জানেন কিভাবে কাস্ট কানেক্ট লাইব্রেরি ব্যবহার করে একটি Android TV অ্যাপ কাস্ট-সক্ষম করতে হয়।

আরও বিস্তারিত জানার জন্য ডেভেলপার গাইড দেখুন: /cast/docs/android_tv_receiver