এই পৃষ্ঠাটিতে কোড স্নিপেট এবং একটি Android TV রিসিভার অ্যাপ কাস্টমাইজ করার জন্য উপলব্ধ বৈশিষ্ট্যগুলির বিবরণ রয়েছে৷
লাইব্রেরি কনফিগার করা হচ্ছে
আপনার Android TV অ্যাপে কাস্ট কানেক্ট API গুলি উপলব্ধ করতে:
- আপনার অ্যাপ্লিকেশন মডিউল ডিরেক্টরির ভিতরে
build.gradle
ফাইলটি খুলুন। - যাচাই করুন যে
google()
তালিকাভুক্তrepositories
অন্তর্ভুক্ত করা হয়েছে।repositories { google() }
- আপনার অ্যাপের জন্য আপনার টার্গেট ডিভাইসের প্রকারের উপর নির্ভর করে, আপনার নির্ভরতাগুলিতে লাইব্রেরির সর্বশেষ সংস্করণ যোগ করুন:
- অ্যান্ড্রয়েড রিসিভার অ্যাপের জন্য:
dependencies { implementation 'com.google.android.gms:play-services-cast-tv:21.1.1' implementation 'com.google.android.gms:play-services-cast:22.0.0' }
- অ্যান্ড্রয়েড প্রেরক অ্যাপের জন্য:
dependencies { implementation 'com.google.android.gms:play-services-cast:21.1.1' implementation 'com.google.android.gms:play-services-cast-framework:22.0.0' }
- অ্যান্ড্রয়েড রিসিভার অ্যাপের জন্য:
- পরিবর্তনগুলি সংরক্ষণ করুন এবং টুলবারে
Sync Project with Gradle Files
ক্লিক করুন।
- নিশ্চিত করুন যে আপনি
Podfile
google-cast-sdk
4.8.3 বা উচ্চতরকে লক্ষ্য করছেন৷ - লক্ষ্য iOS 14 বা উচ্চতর। আরো বিস্তারিত জানার জন্য রিলিজ নোট দেখুন.
platform: ios, '14' def target_pods pod 'google-cast-sdk', '~>4.8.3' end
- Chromium ব্রাউজার সংস্করণ M87 বা উচ্চতর প্রয়োজন৷
- আপনার প্রকল্পে ওয়েব প্রেরক API লাইব্রেরি যোগ করুন
<script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
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();
অতিরিক্তভাবে, যদি আপনার অ্যাপটি ব্যাকগ্রাউন্ডে বাজানো সমর্থন করে, তাহলে পটভূমিতে থাকাকালীন বাজানো বন্ধ হয়ে গেলে CastReceiverContext
এ stop()
কল করুন।
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); ... } }
প্রেরক অ্যাপ সেটআপ
কাস্ট সংযোগ সমর্থন সক্ষম করুন৷
একবার আপনি কাস্ট কানেক্ট সমর্থন সহ আপনার প্রেরক অ্যাপ আপডেট করলে, আপনি LaunchOptions
এ androidReceiverCompatible
পতাকাকে সত্যে সেট করে এর প্রস্তুতি ঘোষণা করতে পারেন।
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 অ্যাপ আইডির সাথে যুক্ত করতে যোগ করুন।
বিকাশকারী ডিভাইসগুলি নিবন্ধন করুন
কাস্ট ডেভেলপার কনসোলে আপনি যে 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);
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);
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);
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 TaskonLoad(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<Void?> { // Skip your ad ... return Tasks.forResult(null) } } val mediaManager = CastReceiverContext.getInstance().getMediaManager() mediaManager.setMediaCommandCallback(MyMediaCommandCallback())
public class MyMediaCommandCallback extends MediaCommandCallback { @Override public TaskonSkipAd(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 অ্যাপ লঞ্চ করে বা যোগ দেয়, তখন আপনার প্রেরক অ্যাপটিকে সেই শংসাপত্রগুলি প্রদান করা উচিত যা প্রতিনিধিত্ব করে কে সেশনে যোগ দিচ্ছে।
একজন প্রেরক আপনার Android TV অ্যাপটি লঞ্চ করার এবং যোগদান করার আগে, প্রেরকের শংসাপত্রগুলি অনুমোদিত কিনা তা দেখতে আপনি একটি লঞ্চ চেকার নির্দিষ্ট করতে পারেন৷ যদি না হয়, কাস্ট কানেক্ট SDK আপনার ওয়েব রিসিভার চালু করতে ফিরে আসে।
প্রেরক অ্যাপ লঞ্চ শংসাপত্র ডেটা
প্রেরকের পক্ষ থেকে, আপনি সেশনে কে যোগদান করছেন তা প্রতিনিধিত্ব করার জন্য CredentialsData
নির্দিষ্ট করতে পারেন।
credentials
একটি স্ট্রিং যা ব্যবহারকারী-সংজ্ঞায়িত হতে পারে, যতক্ষণ না আপনার ATV অ্যাপ এটি বুঝতে পারে। credentialsType
সংজ্ঞায়িত করে কোন প্লাটফর্ম থেকে CredentialsData
আসছে বা একটি কাস্টম মান হতে পারে। ডিফল্টরূপে এটি যে প্ল্যাটফর্ম থেকে পাঠানো হচ্ছে সেখানে সেট করা আছে।
CredentialsData
শুধুমাত্র লঞ্চ বা যোগদানের সময় আপনার Android TV অ্যাপে পাঠানো হয়। আপনি সংযুক্ত থাকাকালীন এটি আবার সেট করলে, এটি আপনার Android TV অ্যাপে পাঠানো হবে না। যদি আপনার প্রেরক সংযুক্ত থাকা অবস্থায় প্রোফাইলটি স্যুইচ করে, আপনি হয় সেশনে থাকতে পারেন, অথবা যদি আপনি মনে করেন যে নতুন প্রোফাইলটি সেশনের সাথে বেমানান SessionManager.endCurrentCastSession(boolean stopCasting)
প্রেরকের SenderInfo
পেতে CastReceiverContext
এ getSenders
ব্যবহার করে, 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());
google-cast-sdk
সংস্করণ v4.8.3
বা উচ্চতর প্রয়োজন৷
বিকল্পগুলি সেট করার পরে যে কোনও সময় কল করা যেতে পারে: 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 TaskcheckLaunchRequestSupported(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(); } }
LaunchRequestChecker
এ true
সমাধান করলে 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());