আপনার Android TV রিসিভারে মূল বৈশিষ্ট্য যোগ করুন

এই পৃষ্ঠায় কোড স্নিপেট এবং অ্যান্ড্রয়েড টিভি রিসিভার অ্যাপ কাস্টমাইজ করার জন্য উপলব্ধ বৈশিষ্ট্যগুলির বিবরণ রয়েছে।

লাইব্রেরি কনফিগার করা

আপনার Android TV অ্যাপে Cast Connect API গুলি উপলব্ধ করতে:

অ্যান্ড্রয়েড
  1. আপনার অ্যাপ্লিকেশন মডিউল ডিরেক্টরির ভিতরে build.gradle ফাইলটি খুলুন।
  2. তালিকাভুক্ত repositories google() অন্তর্ভুক্ত আছে কিনা তা যাচাই করুন।
      repositories {
        google()
      }
  3. আপনার অ্যাপের জন্য আপনার টার্গেট ডিভাইসের ধরণের উপর নির্ভর করে, আপনার নির্ভরতাগুলিতে লাইব্রেরির সর্বশেষ সংস্করণগুলি যুক্ত করুন:
    • অ্যান্ড্রয়েড রিসিভার অ্যাপের জন্য:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast-tv:21.1.1'
          implementation 'com.google.android.gms:play-services-cast:22.2.0'
        }
    • অ্যান্ড্রয়েড সেন্ডার অ্যাপের জন্য:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast:21.1.1'
          implementation 'com.google.android.gms:play-services-cast-framework:22.2.0'
        }
    প্রতিবার পরিষেবাগুলি আপডেট করার সময় এই সংস্করণ নম্বরটি আপডেট করতে ভুলবেন না।
  4. পরিবর্তনগুলি সংরক্ষণ করুন এবং টুলবারে Sync Project with Gradle Files এ ক্লিক করুন।
আইওএস
  1. নিশ্চিত করুন যে আপনার Podfile google-cast-sdk 4.8.4 বা তার বেশি ভার্সনকে টার্গেট করছে
  2. iOS 15 বা তার পরবর্তী ভার্সনগুলিকে টার্গেট করুন। আরও বিস্তারিত জানার জন্য রিলিজ নোট দেখুন।
      platform: ios, '15'
    
      def target_pods
         pod 'google-cast-sdk', '~>4.8.4'
      end
ওয়েব
  1. Chromium ব্রাউজার সংস্করণ M87 বা উচ্চতর প্রয়োজন।
  2. আপনার প্রকল্পে ওয়েব সেন্ডার API লাইব্রেরি যোগ করুন
      <script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

অ্যান্ড্রয়েডএক্সের প্রয়োজনীয়তা

গুগল প্লে সার্ভিসেসের নতুন সংস্করণগুলিতে androidx নেমস্পেস ব্যবহার করার জন্য একটি অ্যাপ আপডেট করা প্রয়োজন। AndroidX এ মাইগ্রেট করার জন্য নির্দেশাবলী অনুসরণ করুন।

অ্যান্ড্রয়েড টিভি অ্যাপ—পূর্বশর্ত

আপনার অ্যান্ড্রয়েড টিভি অ্যাপে কাস্ট কানেক্ট সাপোর্ট করার জন্য, আপনাকে অবশ্যই একটি মিডিয়া সেশন থেকে ইভেন্ট তৈরি এবং সাপোর্ট করতে হবে। আপনার মিডিয়া সেশন দ্বারা প্রদত্ত ডেটা আপনার মিডিয়া স্ট্যাটাসের জন্য মৌলিক তথ্য প্রদান করে—যেমন, অবস্থান, প্লেব্যাক স্ট্যাটাস ইত্যাদি। আপনার মিডিয়া সেশনটি কাস্ট কানেক্ট লাইব্রেরি দ্বারা প্রেরকের কাছ থেকে নির্দিষ্ট বার্তা, যেমন বিরতি, গ্রহণ করার সময় সংকেত দেওয়ার জন্যও ব্যবহার করা হয়।

মিডিয়া সেশন এবং কীভাবে একটি মিডিয়া সেশন শুরু করবেন সে সম্পর্কে আরও তথ্যের জন্য, মিডিয়া সেশনের সাথে কাজ করার নির্দেশিকাটি দেখুন।

মিডিয়া সেশনের জীবনচক্র

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

সেশনের অবস্থা আপডেট করা হচ্ছে

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

মিডিয়ামেটাডেটাকম্প্যাট

মেটাডেটা ক্ষেত্র বিবরণ
METADATA_KEY_TITLE (প্রয়োজনীয়) মিডিয়া শিরোনাম।
মেটাডাটা_কী_ডিসপ্লে_সাবটাইটেল সাবটাইটেল।
মেটাডেটা_কী_ডিসপ্লে_আইকন_ইউআরআই আইকন URL।
METADATA_KEY_DURATION (প্রয়োজনীয়) মিডিয়ার সময়কাল।
মেটাডাটা_কী_মিডিয়া_ইউআরআই কন্টেন্ট আইডি।
মেটাডাটা_কী_শিল্পী শিল্পী।
মেটাডেটা_কী_অ্যালবাম অ্যালবামটি।

প্লেব্যাকস্টেটকম্প্যাট

প্রয়োজনীয় পদ্ধতি বিবরণ
সেটঅ্যাকশন() সমর্থিত মিডিয়া কমান্ড সেট করে।
সেটস্টেট() বাজানোর অবস্থা এবং বর্তমান অবস্থান সেট করুন।

মিডিয়াসেশনকম্প্যাট

প্রয়োজনীয় পদ্ধতি বিবরণ
সেট রিপিটমোড() পুনরাবৃত্তি মোড সেট করে।
সেটশাফলমোড() শাফেল মোড সেট করে।
সেটমেটাডেটা() মিডিয়া মেটাডেটা সেট করে।
সেটপ্লেব্যাকস্টেট() প্লেব্যাক অবস্থা সেট করে।
কোটলিন
private fun updateMediaSession() {
    val metadata = MediaMetadataCompat.Builder()
         .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "title")
         .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "subtitle")
         .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, mMovie.getCardImageUrl())
         .build()

    val playbackState = PlaybackStateCompat.Builder()
         .setState(
             PlaybackStateCompat.STATE_PLAYING,
             player.getPosition(),
             player.getPlaybackSpeed(),
             System.currentTimeMillis()
        )
         .build()

    mediaSession.setMetadata(metadata)
    mediaSession.setPlaybackState(playbackState)
}
জাভা
private void updateMediaSession() {
  MediaMetadataCompat metadata =
      new MediaMetadataCompat.Builder()
          .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "title")
          .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "subtitle")
          .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI,mMovie.getCardImageUrl())
          .build();

  PlaybackStateCompat playbackState =
      new PlaybackStateCompat.Builder()
          .setState(
               PlaybackStateCompat.STATE_PLAYING,
               player.getPosition(),
               player.getPlaybackSpeed(),
               System.currentTimeMillis())
          .build();

  mediaSession.setMetadata(metadata);
  mediaSession.setPlaybackState(playbackState);
}

পরিবহন নিয়ন্ত্রণ পরিচালনা

আপনার অ্যাপটি মিডিয়া সেশন ট্রান্সপোর্ট কন্ট্রোল কলব্যাক বাস্তবায়ন করবে। নিম্নলিখিত টেবিলটি দেখায় যে তাদের কোন পরিবহন নিয়ন্ত্রণ পদক্ষেপগুলি পরিচালনা করতে হবে:

মিডিয়াসেশনকম্প্যাট.কলব্যাক

কর্ম বিবরণ
অনপ্লে() জীবনবৃত্তান্ত
অনপজ() বিরতি
অনসিকটু() একটি অবস্থান খুঁজুন
অনস্টপ() বর্তমান মিডিয়া বন্ধ করুন
কোটলিন
class MyMediaSessionCallback : MediaSessionCompat.Callback() {
  override fun onPause() {
    // Pause the player and update the play state.
    ...
  }

  override fun onPlay() {
    // Resume the player and update the play state.
    ...
  }

  override fun onSeekTo (long pos) {
    // Seek and update the play state.
    ...
  }
  ...
}

mediaSession.setCallback( MyMediaSessionCallback() );
জাভা
public MyMediaSessionCallback extends MediaSessionCompat.Callback {
  public void onPause() {
    // Pause the player and update the play state.
    ...
  }

  public void onPlay() {
    // Resume the player and update the play state.
    ...
  }

  public void onSeekTo (long pos) {
    // Seek and update the play state.
    ...
  }
  ...
}

mediaSession.setCallback(new MyMediaSessionCallback());

কাস্ট সাপোর্ট কনফিগার করা হচ্ছে

যখন কোনও প্রেরক অ্যাপ্লিকেশন দ্বারা একটি লঞ্চ অনুরোধ পাঠানো হয়, তখন একটি অ্যাপ্লিকেশন নেমস্পেস ব্যবহার করে একটি ইনটেন্ট তৈরি করা হয়। আপনার অ্যাপ্লিকেশনটি এটি পরিচালনা করার এবং টিভি অ্যাপ চালু হওয়ার সময় CastReceiverContext অবজেক্টের একটি উদাহরণ তৈরি করার জন্য দায়ী। টিভি অ্যাপটি চলাকালীন Cast এর সাথে ইন্টারঅ্যাক্ট করার জন্য CastReceiverContext অবজেক্টের প্রয়োজন। এই অবজেক্টটি আপনার টিভি অ্যাপ্লিকেশনকে যেকোনো সংযুক্ত প্রেরক থেকে আসা Cast মিডিয়া বার্তা গ্রহণ করতে সক্ষম করে।

অ্যান্ড্রয়েড টিভি সেটআপ

একটি লঞ্চ ইন্টেন্ট ফিল্টার যোগ করা হচ্ছে

আপনার প্রেরক অ্যাপ থেকে লঞ্চ ইন্টেন্ট পরিচালনা করতে চান এমন কার্যকলাপে একটি নতুন ইন্টেন্ট ফিল্টার যোগ করুন:

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

রিসিভার বিকল্প প্রদানকারী নির্দিষ্ট করুন

CastReceiverOptions প্রদানের জন্য আপনাকে একটি ReceiverOptionsProvider বাস্তবায়ন করতে হবে:

কোটলিন
class MyReceiverOptionsProvider : ReceiverOptionsProvider {
  override fun getOptions(context: Context?): CastReceiverOptions {
    return CastReceiverOptions.Builder(context)
          .setStatusText("My App")
          .build()
    }
}
জাভা
public class MyReceiverOptionsProvider implements ReceiverOptionsProvider {
  @Override
  public CastReceiverOptions getOptions(Context context) {
    return new CastReceiverOptions.Builder(context)
        .setStatusText("My App")
        .build();
  }
}

তারপর আপনার AndroidManifest এ বিকল্প সরবরাহকারী নির্দিষ্ট করুন:

 <meta-data
    android:name="com.google.android.gms.cast.tv.RECEIVER_OPTIONS_PROVIDER_CLASS_NAME"
    android:value="com.example.mysimpleatvapplication.MyReceiverOptionsProvider" />

CastReceiverContext শুরু করার সময় CastReceiverOptions প্রদান করতে ReceiverOptionsProvider ব্যবহার করা হয়।

কাস্ট রিসিভারের প্রসঙ্গ

আপনার অ্যাপ তৈরি হওয়ার সময় CastReceiverContext আরম্ভ করুন:

কোটলিন
override fun onCreate() {
  CastReceiverContext.initInstance(this)

  ...
}
জাভা
@Override
public void onCreate() {
  CastReceiverContext.initInstance(this);

  ...
}

আপনার অ্যাপটি যখন ফোরগ্রাউন্ডে চলে যাবে তখন CastReceiverContext শুরু করুন:

কোটলিন
CastReceiverContext.getInstance().start()
জাভা
CastReceiverContext.getInstance().start();

ভিডিও অ্যাপ অথবা ব্যাকগ্রাউন্ড প্লেব্যাক সাপোর্ট করে না এমন অ্যাপের জন্য অ্যাপটি ব্যাকগ্রাউন্ডে চলে যাওয়ার পরে CastReceiverContext এ কল stop() :

কোটলিন
// Player has stopped.
CastReceiverContext.getInstance().stop()
জাভা
// Player has stopped.
CastReceiverContext.getInstance().stop();

এছাড়াও, যদি আপনার অ্যাপটি ব্যাকগ্রাউন্ডে প্লে করা সমর্থন করে, তাহলে CastReceiverContext ব্যাকগ্রাউন্ডে প্লে করা বন্ধ হয়ে গেলে stop() কল করুন।

আমরা দৃঢ়ভাবে সুপারিশ করছি যে আপনি androidx.lifecycle লাইব্রেরি থেকে LifecycleObserver ব্যবহার করে CastReceiverContext.start() এবং CastReceiverContext.stop() কলিং পরিচালনা করুন, বিশেষ করে যদি আপনার নেটিভ অ্যাপে একাধিক অ্যাক্টিভিটি থাকে। এটি বিভিন্ন অ্যাক্টিভিটি থেকে start() এবং stop() কল করার সময় রেস কন্ডিশন এড়ায়।

কোটলিন
// Create a LifecycleObserver class.
class MyLifecycleObserver : DefaultLifecycleObserver {
  override fun onStart(owner: LifecycleOwner) {
    // App prepares to enter foreground.
    CastReceiverContext.getInstance().start()
  }

  override fun onStop(owner: LifecycleOwner) {
    // App has moved to the background or has terminated.
    CastReceiverContext.getInstance().stop()
  }
}

// Add the observer when your application is being created.
class MyApplication : Application() {
  fun onCreate() {
    super.onCreate()

    // Initialize CastReceiverContext.
    CastReceiverContext.initInstance(this /* android.content.Context */)

    // Register LifecycleObserver
    ProcessLifecycleOwner.get().lifecycle.addObserver(
        MyLifecycleObserver())
  }
}
জাভা
// Create a LifecycleObserver class.
public class MyLifecycleObserver implements DefaultLifecycleObserver {
  @Override
  public void onStart(LifecycleOwner owner) {
    // App prepares to enter foreground.
    CastReceiverContext.getInstance().start();
  }

  @Override
  public void onStop(LifecycleOwner owner) {
    // App has moved to the background or has terminated.
    CastReceiverContext.getInstance().stop();
  }
}

// Add the observer when your application is being created.
public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();

    // Initialize CastReceiverContext.
    CastReceiverContext.initInstance(this /* android.content.Context */);

    // Register LifecycleObserver
    ProcessLifecycleOwner.get().getLifecycle().addObserver(
        new MyLifecycleObserver());
  }
}
// In AndroidManifest.xml set MyApplication as the application class
<application
    ...
    android:name=".MyApplication">

মিডিয়া ম্যানেজারের সাথে মিডিয়াসেশন সংযোগ করা হচ্ছে

যখন আপনি একটি MediaSession তৈরি করেন, তখন আপনাকে CastReceiverContext এ বর্তমান MediaSession টোকেনটিও প্রদান করতে হবে যাতে এটি জানতে পারে কোথায় কমান্ড পাঠাতে হবে এবং মিডিয়া প্লেব্যাক অবস্থা পুনরুদ্ধার করতে হবে:

কোটলিন
val mediaManager: MediaManager = receiverContext.getMediaManager()
mediaManager.setSessionCompatToken(currentMediaSession.getSessionToken())
জাভা
MediaManager mediaManager = receiverContext.getMediaManager();
mediaManager.setSessionCompatToken(currentMediaSession.getSessionToken());

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

কোটলিন
myPlayer.stop()
mediaSession.release()
mediaManager.setSessionCompatToken(null)
জাভা
myPlayer.stop();
mediaSession.release();
mediaManager.setSessionCompatToken(null);

যদি আপনার অ্যাপটি ব্যাকগ্রাউন্ডে থাকাকালীন মিডিয়া প্লে করা সমর্থন করে, তাহলে আপনার অ্যাপটি ব্যাকগ্রাউন্ডে পাঠানো হলে CastReceiverContext.stop() কল করার পরিবর্তে, আপনার অ্যাপটি ব্যাকগ্রাউন্ডে থাকা অবস্থায় এবং মিডিয়া প্লে না করলেই কেবল এটি কল করা উচিত। উদাহরণস্বরূপ:

কোটলিন
class MyLifecycleObserver : DefaultLifecycleObserver {
  ...
  // App has moved to the background.
  override fun onPause(owner: LifecycleOwner) {
    mIsBackground = true
    myStopCastReceiverContextIfNeeded()
  }
}

// Stop playback on the player.
private fun myStopPlayback() {
  myPlayer.stop()

  myStopCastReceiverContextIfNeeded()
}

// Stop the CastReceiverContext when both the player has
// stopped and the app has moved to the background.
private fun myStopCastReceiverContextIfNeeded() {
  if (mIsBackground && myPlayer.isStopped()) {
    CastReceiverContext.getInstance().stop()
  }
}
জাভা
public class MyLifecycleObserver implements DefaultLifecycleObserver {
  ...
  // App has moved to the background.
  @Override
  public void onPause(LifecycleOwner owner) {
    mIsBackground = true;

    myStopCastReceiverContextIfNeeded();
  }
}

// Stop playback on the player.
private void myStopPlayback() {
  myPlayer.stop();

  myStopCastReceiverContextIfNeeded();
}

// Stop the CastReceiverContext when both the player has
// stopped and the app has moved to the background.
private void myStopCastReceiverContextIfNeeded() {
  if (mIsBackground && myPlayer.isStopped()) {
    CastReceiverContext.getInstance().stop();
  }
}

কাস্ট কানেক্টের সাথে এক্সোপ্লেয়ার ব্যবহার করা

আপনি যদি Exoplayer ব্যবহার করেন, তাহলে আপনি MediaSessionConnector ব্যবহার করে সেশন এবং প্লেব্যাক অবস্থা সহ সমস্ত সম্পর্কিত তথ্য স্বয়ংক্রিয়ভাবে বজায় রাখতে পারেন, পরিবর্তনগুলি ম্যানুয়ালি ট্র্যাক করার পরিবর্তে।

MediaSessionConnector.MediaButtonEventHandler ব্যবহার করে setMediaButtonEventHandler(MediaButtonEventHandler) কল করে MediaButton ইভেন্টগুলি পরিচালনা করা যেতে পারে, যা অন্যথায় ডিফল্টরূপে MediaSessionCompat.Callback দ্বারা পরিচালিত হয়।

আপনার অ্যাপে MediaSessionConnector ইন্টিগ্রেট করতে, আপনার প্লেয়ার অ্যাক্টিভিটি ক্লাসে অথবা আপনার মিডিয়া সেশন পরিচালনা করার যেকোনো জায়গায় নিম্নলিখিতগুলি যোগ করুন:

কোটলিন
class PlayerActivity : Activity() {
  private var mMediaSession: MediaSessionCompat? = null
  private var mMediaSessionConnector: MediaSessionConnector? = null
  private var mMediaManager: MediaManager? = null

  override fun onCreate(savedInstanceState: Bundle?) {
    ...
    mMediaSession = MediaSessionCompat(this, LOG_TAG)
    mMediaSessionConnector = MediaSessionConnector(mMediaSession!!)
    ...
  }

  override fun onStart() {
    ...
    mMediaManager = receiverContext.getMediaManager()
    mMediaManager!!.setSessionCompatToken(currentMediaSession.getSessionToken())
    mMediaSessionConnector!!.setPlayer(mExoPlayer)
    mMediaSessionConnector!!.setMediaMetadataProvider(mMediaMetadataProvider)
    mMediaSession!!.isActive = true
    ...
  }

  override fun onStop() {
    ...
    mMediaSessionConnector!!.setPlayer(null)
    mMediaSession!!.release()
    mMediaManager!!.setSessionCompatToken(null)
    ...
  }
}
জাভা
public class PlayerActivity extends Activity {
  private MediaSessionCompat mMediaSession;
  private MediaSessionConnector mMediaSessionConnector;
  private MediaManager mMediaManager;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    ...
    mMediaSession = new MediaSessionCompat(this, LOG_TAG);
    mMediaSessionConnector = new MediaSessionConnector(mMediaSession);
    ...
  }

  @Override
  protected void onStart() {
    ...
    mMediaManager = receiverContext.getMediaManager();
    mMediaManager.setSessionCompatToken(currentMediaSession.getSessionToken());

    mMediaSessionConnector.setPlayer(mExoPlayer);
    mMediaSessionConnector.setMediaMetadataProvider(mMediaMetadataProvider);
    mMediaSession.setActive(true);
    ...
  }

  @Override
  protected void onStop() {
    ...
    mMediaSessionConnector.setPlayer(null);
    mMediaSession.release();
    mMediaManager.setSessionCompatToken(null);
    ...
  }
}

প্রেরক অ্যাপ সেটআপ

কাস্ট কানেক্ট সমর্থন সক্ষম করুন

একবার আপনি আপনার প্রেরক অ্যাপটিকে Cast Connect সাপোর্ট সহ আপডেট করার পরে, LaunchOptionsandroidReceiverCompatible ফ্ল্যাগটিকে true-তে সেট করে এর প্রস্তুতি ঘোষণা করতে পারেন।

অ্যান্ড্রয়েড

play-services-cast-framework সংস্করণ 19.0.0 বা তার বেশি প্রয়োজন।

androidReceiverCompatible পতাকাটি LaunchOptions (যা CastOptions এর অংশ) তে সেট করা আছে:

কোটলিন
class CastOptionsProvider : OptionsProvider {
  override fun getCastOptions(context: Context?): CastOptions {
    val launchOptions: LaunchOptions = Builder()
          .setAndroidReceiverCompatible(true)
          .build()
    return CastOptions.Builder()
          .setLaunchOptions(launchOptions)
          ...
          .build()
    }
}
জাভা
public class CastOptionsProvider implements OptionsProvider {
  @Override
  public CastOptions getCastOptions(Context context) {
    LaunchOptions launchOptions = new LaunchOptions.Builder()
              .setAndroidReceiverCompatible(true)
              .build();
    return new CastOptions.Builder()
        .setLaunchOptions(launchOptions)
        ...
        .build();
  }
}
আইওএস

google-cast-sdk সংস্করণ v4.4.8 বা তার বেশি প্রয়োজন।

androidReceiverCompatible ফ্ল্যাগটি GCKLaunchOptions (যা GCKCastOptions এর অংশ) তে সেট করা আছে:

let options = GCKCastOptions(discoveryCriteria: GCKDiscoveryCriteria(applicationID: kReceiverAppID))
...
let launchOptions = GCKLaunchOptions()
launchOptions.androidReceiverCompatible = true
options.launchOptions = launchOptions
GCKCastContext.setSharedInstanceWith(options)
ওয়েব

Chromium ব্রাউজার সংস্করণ M87 বা উচ্চতর প্রয়োজন।

const context = cast.framework.CastContext.getInstance();
const castOptions = new cast.framework.CastOptions();
castOptions.receiverApplicationId = kReceiverAppID;
castOptions.androidReceiverCompatible = true;
context.setOptions(castOptions);

কাস্ট ডেভেলপার কনসোল সেটআপ

Android TV অ্যাপটি কনফিগার করুন

আপনার Android TV অ্যাপের প্যাকেজ নামটি Cast Developer Console- এ যোগ করুন যাতে এটি আপনার Cast অ্যাপ আইডির সাথে যুক্ত হয়।

ডেভেলপার ডিভাইসগুলি নিবন্ধন করুন

আপনি যে অ্যান্ড্রয়েড টিভি ডিভাইসটি ডেভেলপমেন্টের জন্য ব্যবহার করতে যাচ্ছেন তার সিরিয়াল নম্বরটি কাস্ট ডেভেলপার কনসোলে নিবন্ধন করুন।

রেজিস্ট্রেশন ছাড়া, নিরাপত্তার কারণে Cast Connect শুধুমাত্র Google Play Store থেকে ইনস্টল করা অ্যাপগুলির জন্য কাজ করবে।

কাস্ট ডেভেলপমেন্টের জন্য কাস্ট বা অ্যান্ড্রয়েড টিভি ডিভাইস নিবন্ধন সম্পর্কে আরও তথ্যের জন্য, নিবন্ধন পৃষ্ঠাটি দেখুন।

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

যদি আপনি ইতিমধ্যেই আপনার অ্যান্ড্রয়েড টিভি অ্যাপে ডিপ লিঙ্ক সাপোর্ট প্রয়োগ করে থাকেন, তাহলে আপনার অ্যান্ড্রয়েড টিভি ম্যানিফেস্টেও একই রকম সংজ্ঞা কনফিগার করা উচিত:

<activity android:name="com.example.activity">
  <intent-filter>
     <action android:name="android.intent.action.VIEW" />
     <category android:name="android.intent.category.DEFAULT" />
     <data android:scheme="https"/>
     <data android:host="www.example.com"/>
     <data android:pathPattern=".*"/>
  </intent-filter>
</activity>

প্রেরকের উপর সত্তা অনুসারে লোড করুন

প্রেরকদের ক্ষেত্রে, লোড অনুরোধের জন্য মিডিয়া তথ্যে entity সেট করে আপনি ডিপ লিঙ্কটি পাস করতে পারেন:

কোটলিন
val mediaToLoad = MediaInfo.Builder("some-id")
    .setEntity("https://example.com/watch/some-id")
    ...
    .build()
val loadRequest = MediaLoadRequestData.Builder()
    .setMediaInfo(mediaToLoad)
    .setCredentials("user-credentials")
    ...
    .build()
remoteMediaClient.load(loadRequest)
অ্যান্ড্রয়েড
জাভা
MediaInfo mediaToLoad =
    new MediaInfo.Builder("some-id")
        .setEntity("https://example.com/watch/some-id")
        ...
        .build();
MediaLoadRequestData loadRequest =
    new MediaLoadRequestData.Builder()
        .setMediaInfo(mediaToLoad)
        .setCredentials("user-credentials")
        ...
        .build();
remoteMediaClient.load(loadRequest);
আইওএস
let mediaInfoBuilder = GCKMediaInformationBuilder(entity: "https://example.com/watch/some-id")
...
mediaInformation = mediaInfoBuilder.build()

let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
mediaLoadRequestDataBuilder.mediaInformation = mediaInformation
mediaLoadRequestDataBuilder.credentials = "user-credentials"
...
let mediaLoadRequestData = mediaLoadRequestDataBuilder.build()

remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
ওয়েব

Chromium ব্রাউজার সংস্করণ M87 বা উচ্চতর প্রয়োজন।

let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4');
mediaInfo.entity = 'https://example.com/watch/some-id';
...

let request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
...

cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);

লোড কমান্ডটি আপনার ডিপ লিঙ্ক এবং ডেভেলপার কনসোলে আপনার দ্বারা সংজ্ঞায়িত প্যাকেজের নাম সহ একটি ইনটেন্টের মাধ্যমে পাঠানো হয়।

প্রেরকের উপর ATV শংসাপত্র সেট করা

এটা সম্ভব যে আপনার ওয়েব রিসিভার অ্যাপ এবং অ্যান্ড্রয়েড টিভি অ্যাপ ভিন্ন ভিন্ন ডিপ লিঙ্ক এবং credentials সমর্থন করে (উদাহরণস্বরূপ, যদি আপনি দুটি প্ল্যাটফর্মে আলাদাভাবে প্রমাণীকরণ পরিচালনা করেন)। এটি সমাধানের জন্য, আপনি অ্যান্ড্রয়েড টিভির জন্য বিকল্প entity এবং credentials সরবরাহ করতে পারেন:

অ্যান্ড্রয়েড
কোটলিন
val mediaToLoad = MediaInfo.Builder("some-id")
        .setEntity("https://example.com/watch/some-id")
        .setAtvEntity("myscheme://example.com/atv/some-id")
        ...
        .build()
val loadRequest = MediaLoadRequestData.Builder()
        .setMediaInfo(mediaToLoad)
        .setCredentials("user-credentials")
        .setAtvCredentials("atv-user-credentials")
        ...
        .build()
remoteMediaClient.load(loadRequest)
জাভা
MediaInfo mediaToLoad =
    new MediaInfo.Builder("some-id")
        .setEntity("https://example.com/watch/some-id")
        .setAtvEntity("myscheme://example.com/atv/some-id")
        ...
        .build();
MediaLoadRequestData loadRequest =
    new MediaLoadRequestData.Builder()
        .setMediaInfo(mediaToLoad)
        .setCredentials("user-credentials")
        .setAtvCredentials("atv-user-credentials")
        ...
        .build();
remoteMediaClient.load(loadRequest);
আইওএস
let mediaInfoBuilder = GCKMediaInformationBuilder(entity: "https://example.com/watch/some-id")
mediaInfoBuilder.atvEntity = "myscheme://example.com/atv/some-id"
...
mediaInformation = mediaInfoBuilder.build()

let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
mediaLoadRequestDataBuilder.mediaInformation = mediaInformation
mediaLoadRequestDataBuilder.credentials = "user-credentials"
mediaLoadRequestDataBuilder.atvCredentials = "atv-user-credentials"
...
let mediaLoadRequestData = mediaLoadRequestDataBuilder.build()

remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
ওয়েব

Chromium ব্রাউজার সংস্করণ M87 বা উচ্চতর প্রয়োজন।

let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4');
mediaInfo.entity = 'https://example.com/watch/some-id';
mediaInfo.atvEntity = 'myscheme://example.com/atv/some-id';
...

let request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
request.atvCredentials = 'atv-user-credentials';
...

cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);

যদি ওয়েব রিসিভার অ্যাপটি চালু করা হয়, তাহলে এটি লোড রিকোয়েস্টে entity এবং credentials ব্যবহার করে। তবে যদি আপনার অ্যান্ড্রয়েড টিভি অ্যাপটি চালু করা হয়, তাহলে SDK আপনার atvEntity এবং atvCredentials (যদি নির্দিষ্ট করা থাকে) দিয়ে entity এবং credentials ওভাররাইড করে।

Content ID অথবা MediaQueueData অনুসারে লোড হচ্ছে

আপনি যদি entity বা atvEntity ব্যবহার না করেন এবং আপনার মিডিয়া তথ্যে Content ID বা Content URL ব্যবহার করেন অথবা আরও বিস্তারিত Media Load Request Data ব্যবহার করেন, তাহলে আপনার Android TV অ্যাপে নিম্নলিখিত পূর্বনির্ধারিত ইন্টেন্ট ফিল্টার যোগ করতে হবে:

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

প্রেরকের দিকে, load by entity এর মতো, আপনি আপনার কন্টেন্ট তথ্য দিয়ে একটি লোড অনুরোধ তৈরি করতে পারেন এবং load() কল করতে পারেন।

অ্যান্ড্রয়েড
কোটলিন
val mediaToLoad = MediaInfo.Builder("some-id").build()
val loadRequest = MediaLoadRequestData.Builder()
    .setMediaInfo(mediaToLoad)
    .setCredentials("user-credentials")
    ...
    .build()
remoteMediaClient.load(loadRequest)
জাভা
MediaInfo mediaToLoad =
    new MediaInfo.Builder("some-id").build();
MediaLoadRequestData loadRequest =
    new MediaLoadRequestData.Builder()
        .setMediaInfo(mediaToLoad)
        .setCredentials("user-credentials")
        ...
        .build();
remoteMediaClient.load(loadRequest);
আইওএস
let mediaInfoBuilder = GCKMediaInformationBuilder(contentId: "some-id")
...
mediaInformation = mediaInfoBuilder.build()

let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
mediaLoadRequestDataBuilder.mediaInformation = mediaInformation
mediaLoadRequestDataBuilder.credentials = "user-credentials"
...
let mediaLoadRequestData = mediaLoadRequestDataBuilder.build()

remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
ওয়েব

Chromium ব্রাউজার সংস্করণ M87 বা উচ্চতর প্রয়োজন।

let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4');
...

let request = new chrome.cast.media.LoadRequest(mediaInfo);
...

cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);

লোড অনুরোধ পরিচালনা করা

আপনার কার্যকলাপে, এই লোড অনুরোধগুলি পরিচালনা করার জন্য, আপনার কার্যকলাপের জীবনচক্র কলব্যাকের উদ্দেশ্যগুলি পরিচালনা করতে হবে:

কোটলিন
class MyActivity : Activity() {
  override fun onStart() {
    super.onStart()
    val mediaManager = CastReceiverContext.getInstance().getMediaManager()
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(intent)) {
        // If the SDK recognizes the intent, you should early return.
        return
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }

  // For some cases, a new load intent triggers onNewIntent() instead of
  // onStart().
  override fun onNewIntent(intent: Intent) {
    val mediaManager = CastReceiverContext.getInstance().getMediaManager()
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(intent)) {
        // If the SDK recognizes the intent, you should early return.
        return
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }
}
জাভা
public class MyActivity extends Activity {
  @Override
  protected void onStart() {
    super.onStart();
    MediaManager mediaManager =
        CastReceiverContext.getInstance().getMediaManager();
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(getIntent())) {
      // If the SDK recognizes the intent, you should early return.
      return;
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }

  // For some cases, a new load intent triggers onNewIntent() instead of
  // onStart().
  @Override
  protected void onNewIntent(Intent intent) {
    MediaManager mediaManager =
        CastReceiverContext.getInstance().getMediaManager();
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(intent)) {
      // If the SDK recognizes the intent, you should early return.
      return;
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }
}

যদি MediaManager সনাক্ত করে যে ইন্টেন্টটি একটি লোড ইন্টেন্ট, তাহলে এটি ইন্টেন্ট থেকে একটি MediaLoadRequestData অবজেক্ট বের করে এবং MediaLoadCommandCallback.onLoad() ইনকাম করে। লোড রিকোয়েস্ট পরিচালনা করার জন্য আপনাকে এই পদ্ধতিটি ওভাররাইড করতে হবে। MediaManager.onNewIntent() কল করার আগে কলব্যাকটি নিবন্ধিত হতে হবে (এটি একটি Activity বা Application onCreate() পদ্ধতিতে থাকা বাঞ্ছনীয়)।

কোটলিন
class MyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val mediaManager = CastReceiverContext.getInstance().getMediaManager()
        mediaManager.setMediaLoadCommandCallback(MyMediaLoadCommandCallback())
    }
}

class MyMediaLoadCommandCallback : MediaLoadCommandCallback() {
  override fun onLoad(
        senderId: String?,
        loadRequestData: MediaLoadRequestData
  ): Task {
      return Tasks.call {
        // Resolve the entity into your data structure and load media.
        val mediaInfo = loadRequestData.getMediaInfo()
        if (!checkMediaInfoSupported(mediaInfo)) {
            // Throw MediaException to indicate load failure.
            throw MediaException(
                MediaError.Builder()
                    .setDetailedErrorCode(DetailedErrorCode.LOAD_FAILED)
                    .setReason(MediaError.ERROR_REASON_INVALID_REQUEST)
                    .build()
            )
        }
        myFillMediaInfo(MediaInfoWriter(mediaInfo))
        myPlayerLoad(mediaInfo.getContentUrl())

        // Update media metadata and state (this clears all previous status
        // overrides).
        castReceiverContext.getMediaManager()
            .setDataFromLoad(loadRequestData)
        ...
        castReceiverContext.getMediaManager().broadcastMediaStatus()

        // Return the resolved MediaLoadRequestData to indicate load success.
        return loadRequestData
     }
  }

  private fun myPlayerLoad(contentURL: String) {
    myPlayer.load(contentURL)

    // Update the MediaSession state.
    val playbackState: PlaybackStateCompat = Builder()
        .setState(
            player.getState(), player.getPosition(), System.currentTimeMillis()
        )
        ...
        .build()
    mediaSession.setPlaybackState(playbackState)
  }
জাভা
public class MyActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    MediaManager mediaManager =
        CastReceiverContext.getInstance().getMediaManager();
    mediaManager.setMediaLoadCommandCallback(new MyMediaLoadCommandCallback());
  }
}

public class MyMediaLoadCommandCallback extends MediaLoadCommandCallback {
  @Override
  public Task onLoad(String senderId, MediaLoadRequestData loadRequestData) {
    return Tasks.call(() -> {
        // Resolve the entity into your data structure and load media.
        MediaInfo mediaInfo = loadRequestData.getMediaInfo();
        if (!checkMediaInfoSupported(mediaInfo)) {
          // Throw MediaException to indicate load failure.
          throw new MediaException(
              new MediaError.Builder()
                  .setDetailedErrorCode(DetailedErrorCode.LOAD_FAILED)
                  .setReason(MediaError.ERROR_REASON_INVALID_REQUEST)
                  .build());
        }
        myFillMediaInfo(new MediaInfoWriter(mediaInfo));
        myPlayerLoad(mediaInfo.getContentUrl());

        // Update media metadata and state (this clears all previous status
        // overrides).
        castReceiverContext.getMediaManager()
            .setDataFromLoad(loadRequestData);
        ...
        castReceiverContext.getMediaManager().broadcastMediaStatus();

        // Return the resolved MediaLoadRequestData to indicate load success.
        return loadRequestData;
    });
}

private void myPlayerLoad(String contentURL) {
  myPlayer.load(contentURL);

  // Update the MediaSession state.
  PlaybackStateCompat playbackState =
      new PlaybackStateCompat.Builder()
          .setState(
              player.getState(), player.getPosition(), System.currentTimeMillis())
          ...
          .build();
  mediaSession.setPlaybackState(playbackState);
}

লোড ইন্টেন্ট প্রক্রিয়া করার জন্য, আপনি আমাদের সংজ্ঞায়িত ডেটা স্ট্রাকচারে ইন্টেন্টটি পার্স করতে পারেন (লোড অনুরোধের জন্য MediaLoadRequestData )।

মিডিয়া কমান্ড সমর্থন করে

বেসিক প্লেব্যাক নিয়ন্ত্রণ সমর্থন

বেসিক ইন্টিগ্রেশন কমান্ডের মধ্যে মিডিয়া সেশনের সাথে সামঞ্জস্যপূর্ণ কমান্ডগুলি অন্তর্ভুক্ত থাকে। এই কমান্ডগুলি মিডিয়া সেশন কলব্যাকের মাধ্যমে জানানো হয়। এটি সমর্থন করার জন্য আপনাকে মিডিয়া সেশনে একটি কলব্যাক নিবন্ধন করতে হবে (আপনি হয়তো ইতিমধ্যেই এটি করছেন)।

কোটলিন
private class MyMediaSessionCallback : MediaSessionCompat.Callback() {
  override fun onPause() {
    // Pause the player and update the play state.
    myPlayer.pause()
  }

  override fun onPlay() {
    // Resume the player and update the play state.
    myPlayer.play()
  }

  override fun onSeekTo(pos: Long) {
    // Seek and update the play state.
    myPlayer.seekTo(pos)
  }
    ...
 }

mediaSession.setCallback(MyMediaSessionCallback())
জাভা
private class MyMediaSessionCallback extends MediaSessionCompat.Callback {
  @Override
  public void onPause() {
    // Pause the player and update the play state.
    myPlayer.pause();
  }
  @Override
  public void onPlay() {
    // Resume the player and update the play state.
    myPlayer.play();
  }
  @Override
  public void onSeekTo(long pos) {
    // Seek and update the play state.
    myPlayer.seekTo(pos);
  }

  ...
}

mediaSession.setCallback(new MyMediaSessionCallback());

কাস্ট নিয়ন্ত্রণ কমান্ড সমর্থন করে

কিছু Cast কমান্ড আছে যা MediaSession তে পাওয়া যায় না, যেমন skipAd() অথবা setActiveMediaTracks() । এছাড়াও, কিছু কিউ কমান্ড এখানে বাস্তবায়ন করা প্রয়োজন কারণ Cast কিউ MediaSession কিউয়ের সাথে সম্পূর্ণরূপে সামঞ্জস্যপূর্ণ নয়।

কোটলিন
class MyMediaCommandCallback : MediaCommandCallback() {
    override fun onSkipAd(requestData: RequestData?): Task<Void?> {
        // Skip your ad
        ...
        return Tasks.forResult(null)
    }
}

val mediaManager = CastReceiverContext.getInstance().getMediaManager()
mediaManager.setMediaCommandCallback(MyMediaCommandCallback())
জাভা
public class MyMediaCommandCallback extends MediaCommandCallback {
  @Override
  public Task onSkipAd(RequestData requestData) {
    // Skip your ad
    ...
    return Tasks.forResult(null);
  }
}

MediaManager mediaManager =
    CastReceiverContext.getInstance().getMediaManager();
mediaManager.setMediaCommandCallback(new MyMediaCommandCallback());

সমর্থিত মিডিয়া কমান্ডগুলি নির্দিষ্ট করুন

আপনার কাস্ট রিসিভারের মতো, আপনার Android TV অ্যাপে কোন কমান্ডগুলি সমর্থিত তা নির্দিষ্ট করা উচিত, যাতে প্রেরকরা নির্দিষ্ট UI নিয়ন্ত্রণগুলি সক্ষম বা অক্ষম করতে পারেন। MediaSession এর অংশ এমন কমান্ডগুলির জন্য, PlaybackStateCompat এ কমান্ডগুলি নির্দিষ্ট করুন। MediaStatusModifier এ অতিরিক্ত কমান্ডগুলি নির্দিষ্ট করা উচিত।

কোটলিন
// Set media session supported commands
val playbackState: PlaybackStateCompat = PlaybackStateCompat.Builder()
    .setActions(PlaybackStateCompat.ACTION_PLAY or PlaybackStateCompat.ACTION_PAUSE)
    .setState(PlaybackStateCompat.STATE_PLAYING)
    .build()

mediaSession.setPlaybackState(playbackState)

// Set additional commands in MediaStatusModifier
val mediaManager = CastReceiverContext.getInstance().getMediaManager()
mediaManager.getMediaStatusModifier()
    .setMediaCommandSupported(MediaStatus.COMMAND_QUEUE_NEXT)
জাভা
// Set media session supported commands
PlaybackStateCompat playbackState =
    new PlaybackStateCompat.Builder()
        .setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE)
        .setState(PlaybackStateCompat.STATE_PLAYING)
        .build();

mediaSession.setPlaybackState(playbackState);

// Set additional commands in MediaStatusModifier
MediaManager mediaManager = CastReceiverContext.getInstance().getMediaManager();
mediaManager.getMediaStatusModifier()
            .setMediaCommandSupported(MediaStatus.COMMAND_QUEUE_NEXT);

অসমর্থিত বোতামগুলি লুকান

যদি আপনার Android TV অ্যাপটি শুধুমাত্র বেসিক মিডিয়া নিয়ন্ত্রণ সমর্থন করে কিন্তু আপনার ওয়েব রিসিভার অ্যাপটি আরও উন্নত নিয়ন্ত্রণ সমর্থন করে, তাহলে আপনার প্রেরক অ্যাপটি Android TV অ্যাপে কাস্ট করার সময় সঠিকভাবে আচরণ করে কিনা তা নিশ্চিত করা উচিত। উদাহরণস্বরূপ, যদি আপনার Android TV অ্যাপটি প্লেব্যাক রেট পরিবর্তন সমর্থন না করে এবং আপনার ওয়েব রিসিভার অ্যাপটি সমর্থন করে, তাহলে আপনার প্রতিটি প্ল্যাটফর্মে সমর্থিত ক্রিয়াগুলি সঠিকভাবে সেট করা উচিত এবং নিশ্চিত করা উচিত যে আপনার প্রেরক অ্যাপটি সঠিকভাবে UI রেন্ডার করছে।

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

ট্র্যাক, বিজ্ঞাপন, লাইভ এবং কিউইংয়ের মতো উন্নত বৈশিষ্ট্যগুলিকে সমর্থন করার জন্য, আপনার Android TV অ্যাপটিকে অতিরিক্ত তথ্য প্রদান করতে হবে যা MediaSession মাধ্যমে নিশ্চিত করা যাবে না।

এটি অর্জনের জন্য আমরা আপনার জন্য MediaStatusModifier ক্লাস প্রদান করি। MediaStatusModifier সর্বদা আপনার CastReceiverContext এ সেট করা MediaSession এ কাজ করবে।

MediaStatus তৈরি এবং সম্প্রচার করতে:

কোটলিন
val mediaManager: MediaManager = castReceiverContext.getMediaManager()
val statusModifier: MediaStatusModifier = mediaManager.getMediaStatusModifier()

statusModifier
    .setLiveSeekableRange(seekableRange)
    .setAdBreakStatus(adBreakStatus)
    .setCustomData(customData)

mediaManager.broadcastMediaStatus()
জাভা
MediaManager mediaManager = castReceiverContext.getMediaManager();
MediaStatusModifier statusModifier = mediaManager.getMediaStatusModifier();

statusModifier
    .setLiveSeekableRange(seekableRange)
    .setAdBreakStatus(adBreakStatus)
    .setCustomData(customData);

mediaManager.broadcastMediaStatus();

আমাদের ক্লায়েন্ট লাইব্রেরি MediaSession থেকে বেস MediaStatus পাবে, আপনার Android TV অ্যাপটি MediaStatus মডিফায়ারের মাধ্যমে অতিরিক্ত স্ট্যাটাস এবং ওভাররাইড স্ট্যাটাস নির্দিষ্ট করতে পারে।

কিছু স্টেট এবং মেটাডেটা MediaSession এবং MediaStatusModifier উভয় ক্ষেত্রেই সেট করা যেতে পারে। আমরা দৃঢ়ভাবে সুপারিশ করছি যে আপনি এগুলি শুধুমাত্র MediaSession এ সেট করুন। আপনি এখনও MediaSession এ স্টেটগুলিকে ওভাররাইড করার জন্য মডিফায়ার ব্যবহার করতে পারেন — এটি নিরুৎসাহিত কারণ মডিফায়ারের স্ট্যাটাস সর্বদা MediaSession দ্বারা প্রদত্ত মানের চেয়ে বেশি অগ্রাধিকার পায়।

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

ওয়েব রিসিভার SDK এর মতোই, যদি আপনি পাঠানোর আগে কিছু শেষ কাজ করতে চান, তাহলে পাঠানোর জন্য MediaStatus প্রক্রিয়া করার জন্য আপনি একটি MediaStatusInterceptor নির্দিষ্ট করতে পারেন। আমরা MediaStatus পাঠানোর আগে এটি পরিচালনা করার জন্য একটি MediaStatusWriter পাস করি।

কোটলিন
mediaManager.setMediaStatusInterceptor(object : MediaStatusInterceptor {
    override fun intercept(mediaStatusWriter: MediaStatusWriter) {
      // Perform customization.
        mediaStatusWriter.setCustomData(JSONObject("{data: \"my Hello\"}"))
    }
})
জাভা
mediaManager.setMediaStatusInterceptor(new MediaStatusInterceptor() {
    @Override
    public void intercept(MediaStatusWriter mediaStatusWriter) {
        // Perform customization.
        mediaStatusWriter.setCustomData(new JSONObject("{data: \"my Hello\"}"));
    }
});

ব্যবহারকারীর শংসাপত্র পরিচালনা করা

আপনার Android TV অ্যাপটি শুধুমাত্র নির্দিষ্ট কিছু ব্যবহারকারীকে অ্যাপ সেশন চালু করতে বা যোগদান করতে অনুমতি দিতে পারে। উদাহরণস্বরূপ, শুধুমাত্র একজন প্রেরককে লঞ্চ করতে বা যোগদান করতে অনুমতি দিন যদি:

  • প্রেরক অ্যাপটি ATV অ্যাপের মতো একই অ্যাকাউন্ট এবং প্রোফাইলে লগ ইন করা আছে।
  • প্রেরক অ্যাপটি একই অ্যাকাউন্টে লগ ইন করা আছে, কিন্তু ATV অ্যাপের মতো প্রোফাইল আলাদা।

যদি আপনার অ্যাপ একাধিক বা বেনামী ব্যবহারকারীদের পরিচালনা করতে পারে, তাহলে আপনি অতিরিক্ত যেকোনো ব্যবহারকারীকে ATV সেশনে যোগদানের অনুমতি দিতে পারেন। যদি ব্যবহারকারী শংসাপত্র প্রদান করে, তাহলে আপনার ATV অ্যাপটিকে তাদের শংসাপত্রগুলি পরিচালনা করতে হবে যাতে তাদের অগ্রগতি এবং অন্যান্য ব্যবহারকারীর ডেটা সঠিকভাবে ট্র্যাক করা যায়।

যখন আপনার সেন্ডার অ্যাপটি আপনার Android TV অ্যাপে লঞ্চ করে বা যোগদান করে, তখন আপনার সেন্ডার অ্যাপটি সেই শংসাপত্রগুলি সরবরাহ করবে যা সেশনে কে যোগদান করছে তা প্রতিনিধিত্ব করে।

একজন প্রেরক আপনার Android TV অ্যাপ চালু এবং যোগদান করার আগে, আপনি একটি লঞ্চ চেকার নির্দিষ্ট করতে পারেন যাতে প্রেরকের শংসাপত্র অনুমোদিত কিনা তা দেখা যায়। যদি তা না হয়, তাহলে Cast Connect SDK আপনার ওয়েব রিসিভার চালু করার জন্য ফিরে আসে।

প্রেরকের অ্যাপ লঞ্চ শংসাপত্রের ডেটা

প্রেরকের দিকে, আপনি সেশনে কে যোগ দিচ্ছেন তা উপস্থাপন করার জন্য CredentialsData নির্দিষ্ট করতে পারেন।

credentials হল একটি স্ট্রিং যা ব্যবহারকারী-সংজ্ঞায়িত করা যেতে পারে, যতক্ষণ না আপনার ATV অ্যাপ এটি বুঝতে পারে। credentialsType নির্ধারণ করে যে কোন প্ল্যাটফর্ম থেকে CredentialsData আসছে অথবা এটি একটি কাস্টম মান হতে পারে। ডিফল্টরূপে এটি সেই প্ল্যাটফর্মে সেট করা থাকে যেখান থেকে এটি পাঠানো হচ্ছে।

CredentialsData শুধুমাত্র লঞ্চ বা যোগদানের সময় আপনার Android TV অ্যাপে পাঠানো হয়। আপনি যদি সংযুক্ত থাকাকালীন এটি আবার সেট করেন, তাহলে এটি আপনার Android TV অ্যাপে পাঠানো হবে না। যদি আপনার প্রেরক সংযুক্ত থাকাকালীন প্রোফাইল পরিবর্তন করেন, তাহলে আপনি হয় সেশনে থাকতে পারেন, অথবা যদি আপনার মনে হয় যে নতুন প্রোফাইলটি সেশনের সাথে সামঞ্জস্যপূর্ণ নয় তাহলে SessionManager.endCurrentCastSession(boolean stopCasting) এ কল করতে পারেন।

প্রতিটি প্রেরকের জন্য CredentialsData CastReceiverContextgetSenders ব্যবহার করে SenderInfo পেতে, getCastLaunchRequest() CastLaunchRequest পেতে এবং তারপর getCredentialsData() ব্যবহার করে পুনরুদ্ধার করা যেতে পারে।

অ্যান্ড্রয়েড

play-services-cast-framework সংস্করণ 19.0.0 বা তার বেশি প্রয়োজন।

কোটলিন
CastContext.getSharedInstance().setLaunchCredentialsData(
    CredentialsData.Builder()
        .setCredentials("{\"userId\": \"abc\"}")
        .build()
)
জাভা
CastContext.getSharedInstance().setLaunchCredentialsData(
    new CredentialsData.Builder()
        .setCredentials("{\"userId\": \"abc\"}")
        .build());
আইওএস

google-cast-sdk সংস্করণ v4.8.4 বা উচ্চতর প্রয়োজন।

অপশনগুলো সেট করার পর যেকোনো সময় কল করা যেতে পারে: GCKCastContext.setSharedInstanceWith(options)

GCKCastContext.sharedInstance().setLaunch(
    GCKCredentialsData(credentials: "{\"userId\": \"abc\"}")
ওয়েব

Chromium ব্রাউজার সংস্করণ M87 বা উচ্চতর প্রয়োজন।

অপশনগুলো সেট করার পর যেকোনো সময় কল করা যেতে পারে: cast.framework.CastContext.getInstance().setOptions(options); .

let credentialsData =
    new chrome.cast.CredentialsData("{\"userId\": \"abc\"}");
cast.framework.CastContext.getInstance().setLaunchCredentialsData(credentialsData);

এটিভি লঞ্চ অনুরোধ পরীক্ষক বাস্তবায়ন করা হচ্ছে

যখন কোনও প্রেরক লঞ্চ বা যোগদানের চেষ্টা করেন তখন CredentialsData আপনার Android TV অ্যাপে পাঠানো হয়। এই অনুরোধটি অনুমোদন বা প্রত্যাখ্যান করার জন্য আপনি LaunchRequestChecker প্রয়োগ করতে পারেন।

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

যদি কোনও অনুরোধ অনুমোদিত হয়, তাহলে ATV অ্যাপটি চালু হয়। ব্যবহারকারী ATV অ্যাপে লগ ইন না থাকা অবস্থায় আপনার অ্যাপ লোড অনুরোধ পাঠানো সমর্থন করে কিনা বা ব্যবহারকারীর অমিল আছে কিনা তার উপর নির্ভর করে আপনি এই আচরণটি কাস্টমাইজ করতে পারেন। LaunchRequestChecker এ এই আচরণটি সম্পূর্ণরূপে কাস্টমাইজযোগ্য।

CastReceiverOptions.LaunchRequestChecker ইন্টারফেস বাস্তবায়ন করে একটি ক্লাস তৈরি করুন:

কোটলিন
class MyLaunchRequestChecker : LaunchRequestChecker {
  override fun checkLaunchRequestSupported(launchRequest: CastLaunchRequest): Task {
    return Tasks.call {
      myCheckLaunchRequest(
           launchRequest
      )
    }
  }
}

private fun myCheckLaunchRequest(launchRequest: CastLaunchRequest): Boolean {
  val credentialsData = launchRequest.getCredentialsData()
     ?: return false // or true if you allow anonymous users to join.

  // The request comes from a mobile device, e.g. checking user match.
  return if (credentialsData.credentialsType == CredentialsData.CREDENTIALS_TYPE_ANDROID) {
     myCheckMobileCredentialsAllowed(credentialsData.getCredentials())
  } else false // Unrecognized credentials type.
}
জাভা
public class MyLaunchRequestChecker
    implements CastReceiverOptions.LaunchRequestChecker {
  @Override
  public Task checkLaunchRequestSupported(CastLaunchRequest launchRequest) {
    return Tasks.call(() -> myCheckLaunchRequest(launchRequest));
  }
}

private boolean myCheckLaunchRequest(CastLaunchRequest launchRequest) {
  CredentialsData credentialsData = launchRequest.getCredentialsData();
  if (credentialsData == null) {
    return false;  // or true if you allow anonymous users to join.
  }

  // The request comes from a mobile device, e.g. checking user match.
  if (credentialsData.getCredentialsType().equals(CredentialsData.CREDENTIALS_TYPE_ANDROID)) {
    return myCheckMobileCredentialsAllowed(credentialsData.getCredentials());
  }

  // Unrecognized credentials type.
  return false;
}

তারপর এটি আপনার ReceiverOptionsProvider এ সেট করুন:

কোটলিন
class MyReceiverOptionsProvider : ReceiverOptionsProvider {
  override fun getOptions(context: Context?): CastReceiverOptions {
    return CastReceiverOptions.Builder(context)
        ...
        .setLaunchRequestChecker(MyLaunchRequestChecker())
        .build()
  }
}
জাভা
public class MyReceiverOptionsProvider implements ReceiverOptionsProvider {
  @Override
  public CastReceiverOptions getOptions(Context context) {
    return new CastReceiverOptions.Builder(context)
        ...
        .setLaunchRequestChecker(new MyLaunchRequestChecker())
        .build();
  }
}

LaunchRequestCheckertrue সমাধান করলে ATV অ্যাপ চালু হয় এবং false আপনার ওয়েব রিসিভার অ্যাপ চালু করে।

কাস্টম বার্তা পাঠানো এবং গ্রহণ করা

Cast প্রোটোকল আপনাকে প্রেরক এবং আপনার রিসিভার অ্যাপ্লিকেশনের মধ্যে কাস্টম স্ট্রিং বার্তা পাঠাতে দেয়। আপনার CastReceiverContext শুরু করার আগে আপনাকে বার্তা পাঠানোর জন্য একটি নেমস্পেস (চ্যানেল) নিবন্ধন করতে হবে।

অ্যান্ড্রয়েড টিভি—কাস্টম নেমস্পেস নির্দিষ্ট করুন

সেটআপের সময় আপনার CastReceiverOptions এ আপনার সমর্থিত নেমস্পেসগুলি নির্দিষ্ট করতে হবে:

কোটলিন
class MyReceiverOptionsProvider : ReceiverOptionsProvider {
  override fun getOptions(context: Context?): CastReceiverOptions {
    return CastReceiverOptions.Builder(context)
        .setCustomNamespaces(
            Arrays.asList("urn:x-cast:com.example.cast.mynamespace")
        )
        .build()
  }
}
জাভা
public class MyReceiverOptionsProvider implements ReceiverOptionsProvider {
  @Override
  public CastReceiverOptions getOptions(Context context) {
    return new CastReceiverOptions.Builder(context)
        .setCustomNamespaces(
              Arrays.asList("urn:x-cast:com.example.cast.mynamespace"))
        .build();
  }
}

অ্যান্ড্রয়েড টিভি—বার্তা পাঠানো

কোটলিন
// If senderId is null, then the message is broadcasted to all senders.
CastReceiverContext.getInstance().sendMessage(
    "urn:x-cast:com.example.cast.mynamespace", senderId, customString)
জাভা
// If senderId is null, then the message is broadcasted to all senders.
CastReceiverContext.getInstance().sendMessage(
    "urn:x-cast:com.example.cast.mynamespace", senderId, customString);

অ্যান্ড্রয়েড টিভি—কাস্টম নেমস্পেস বার্তা গ্রহণ করুন

কোটলিন
class MyCustomMessageListener : MessageReceivedListener {
    override fun onMessageReceived(
        namespace: String, senderId: String?, message: String ) {
        ...
    }
}

CastReceiverContext.getInstance().setMessageReceivedListener(
    "urn:x-cast:com.example.cast.mynamespace", new MyCustomMessageListener());
জাভা
class MyCustomMessageListener implements CastReceiverContext.MessageReceivedListener {
  @Override
  public void onMessageReceived(
      String namespace, String senderId, String message) {
    ...
  }
}

CastReceiverContext.getInstance().setMessageReceivedListener(
    "urn:x-cast:com.example.cast.mynamespace", new MyCustomMessageListener());