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

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

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

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

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

AndroidX প্রয়োজনীয়তা

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

Android TV অ্যাপ—পূর্বশর্ত

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

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

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

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

সেশন স্ট্যাটাস আপডেট করা হচ্ছে

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

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

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

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

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

MediaSessionCompat

প্রয়োজনীয় পদ্ধতি বর্ণনা
setRepeatMode() পুনরাবৃত্তি মোড সেট করে।
সেট শাফেলমোড() শাফেল মোড সেট করে।
সেট মেটাডেটা() মিডিয়া মেটাডেটা সেট করে।
সেটপ্লেব্যাকস্টেট() প্লেব্যাক অবস্থা সেট করে।
কোটলিন
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);
}

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

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

MediaSessionCompat.Callback

কর্ম বর্ণনা
অনপ্লে() জীবনবৃত্তান্ত
অনপজ() বিরতি
onSeekTo() একটি অবস্থান সন্ধান করুন
অনস্টপ() বর্তমান মিডিয়া বন্ধ করুন
কোটলিন
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());

কাস্ট সমর্থন কনফিগার করা হচ্ছে

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

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

একটি লঞ্চ অভিপ্রায় ফিল্টার যোগ করা হচ্ছে

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

<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 আরম্ভ হলে ReceiverOptionsProvider CastReceiverOptions প্রদান করতে ব্যবহৃত হয়।

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

আপনার অ্যাপ তৈরি হলে 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();

অতিরিক্তভাবে, যদি আপনার অ্যাপটি ব্যাকগ্রাউন্ডে বাজানো সমর্থন করে, তাহলে পটভূমিতে থাকাকালীন বাজানো বন্ধ হয়ে গেলে CastReceiverContextstop() কল করুন।

CastReceiverContext.start() এবং CastReceiverContext.stop() কল পরিচালনা করতে আমরা আপনাকে androidx.lifecycle লাইব্রেরি থেকে LifecycleObserver ব্যবহার করার দৃঢ়ভাবে সুপারিশ করছি, বিশেষ করে যদি আপনার নেটিভ অ্যাপের একাধিক কার্যকলাপ থাকে। আপনি যখন বিভিন্ন ক্রিয়াকলাপ থেকে 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-কে MediaManager-এর সাথে সংযুক্ত করা হচ্ছে

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

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

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

কোটলিন
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();
  }
}

Cast Connect-এর সাথে Exoplayer ব্যবহার করা

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

MediaSessionConnector.MediaButtonEventHandler setMediaButtonEventHandler(MediaButtonEventHandler) কল করে মিডিয়াবাটন ইভেন্টগুলি পরিচালনা করতে ব্যবহার করা যেতে পারে যা অন্যথায় 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);
    ...
  }
}

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

কাস্ট সংযোগ সমর্থন সক্ষম করুন৷

একবার আপনি কাস্ট কানেক্ট সমর্থন সহ আপনার প্রেরক অ্যাপ আপডেট করলে, আপনি LaunchOptionsandroidReceiverCompatible পতাকাকে সত্যে সেট করে এর প্রস্তুতি ঘোষণা করতে পারেন।

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

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

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 অ্যাপ আইডির সাথে যুক্ত করতে যোগ করুন।

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

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

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

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

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

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

<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);
iOS
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 সমর্থন করে (উদাহরণস্বরূপ যদি আপনি দুটি প্ল্যাটফর্মে ভিন্নভাবে প্রমাণীকরণ পরিচালনা করেন)। এটি মোকাবেলা করার জন্য, আপনি Android TV-এর জন্য বিকল্প 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);
iOS
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 ব্যবহার করে। তবে আপনার Android TV অ্যাপ চালু হলে, SDK আপনার atvEntity এবং atvCredentials (যদি নির্দিষ্ট করা থাকে) দিয়ে entity এবং credentials ওভাররাইড করে।

Content ID বা MediaQueueData দ্বারা লোড হচ্ছে

আপনি যদি entity বা atvEntity ব্যবহার না করেন এবং আপনার মিডিয়া তথ্যে Content ID বা Content URL ব্যবহার করেন বা আরও বিস্তারিত মিডিয়া লোড অনুরোধের ডেটা ব্যবহার করেন, তাহলে আপনাকে আপনার 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() দিয়ে একটি লোড অনুরোধ তৈরি করতে পারেন।

অ্যান্ড্রয়েড
কোটলিন
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);
iOS
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() কল করার আগে কলব্যাকটি অবশ্যই নিবন্ধিত হতে হবে (এটি একটি অ্যাক্টিভিটি বা অ্যাপ্লিকেশন 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());

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

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

কোটলিন
class MyMediaCommandCallback : MediaCommandCallback() {
    override fun onSkipAd(requestData: RequestData?): Task {
        // 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 সবসময় MediaSession এ কাজ করবে যা আপনি CastReceiverContext এ সেট করেছেন।

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 নির্দিষ্ট করতে পারেন। আমরা একটি MediaStatusWriter এ পাস করি MediaStatus পাঠানোর আগে ম্যানিপুলেট করার জন্য।

কোটলিন
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 অ্যাপটিকে তাদের শংসাপত্রগুলি পরিচালনা করতে হবে যাতে তাদের অগ্রগতি এবং অন্যান্য ব্যবহারকারীর ডেটা সঠিকভাবে ট্র্যাক করা যায়।

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

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

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

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

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

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

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

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

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

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

বিকল্পগুলি সেট করার পরে যে কোনও সময় কল করা যেতে পারে: 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);

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

যখন একজন প্রেরক লঞ্চ বা যোগদানের চেষ্টা করেন তখন আপনার Android TV অ্যাপে CredentialsData পাঠানো হয়। আপনি একটি 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 আপনার ওয়েব রিসিভার অ্যাপ চালু হয়।

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

কাস্ট প্রোটোকল আপনাকে প্রেরক এবং আপনার রিসিভার অ্যাপ্লিকেশনের মধ্যে কাস্টম স্ট্রিং বার্তা পাঠাতে দেয়। আপনার 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();
  }
}

Android TV—মেসেজ পাঠানো

কোটলিন
// 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);

Android TV—কাস্টম নেমস্পেস মেসেজ পান

কোটলিন
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());