این صفحه حاوی تکهکدها و شرح ویژگیهای دردسترس برای سفارشیسازی برنامه «گیرنده Android TV» است.
درحال پیکربندی کتابخانهها
برای دردسترس قرار دادن Cast Connect API برای برنامه Android TV:
-
فایل
build.gradleرا در فهرست راهنمای واحد برنامه باز کنید. -
تأیید کنید که
google()درrepositoriesفهرستشده گنجانده شده است.repositories { google() } -
بسته به نوع دستگاه هدف برای برنامهتان، جدیدترین نسخههای
کتابخانهها را به وابستگیهایتان اضافه کنید:
-
برای برنامه Android Receiver:
dependencies { implementation 'com.google.android.gms:play-services-cast-tv:21.1.1' implementation 'com.google.android.gms:play-services-cast:23.0.0' }
-
برای برنامه «فرستنده Android»:
dependencies { implementation 'com.google.android.gms:play-services-cast:21.1.1' implementation 'com.google.android.gms:play-services-cast-framework:23.0.0' }
-
برای برنامه Android Receiver:
-
تغییرات را ذخیره کنید و روی
Sync Project with Gradle Filesدر نوارابزار کلیک کنید.
-
مطمئن شوید
Podfileشماgoogle-cast-sdkنسخه ۴.۸.۶ یا بالاتر را هدف قرار میدهد -
iOS 16 یا بالاتر را هدف قرار دهد. برای جزئیات بیشتر، یادداشتهای انتشار را ببینید.
platform: ios, '16' def target_pods pod 'google-cast-sdk', '~>4.8.6' end
- به مرورگر Chromium نسخه M87 یا بالاتر نیاز دارد.
-
کتابخانه Web Sender API را به پروژهتان اضافه کنید
<script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
الزامات AndroidX
نسخههای جدید «خدمات Google Play» مستلزم این است که برنامه برای استفاده از فضای نام androidx بهروز شده باشد. دستورالعملهای
انتقال به AndroidX را دنبال کنید.
برنامه Android TV—پیشنیازها
برای پشتیبانی از Cast Connect در برنامه Android TV، باید رویدادها را از جلسه رسانه ایجاد و پشتیبانی کنید. دادههای ارائهشده توسط جلسه رسانه شما اطلاعات اولیه (مثلاً موقعیت، وضعیت بازپخش، و غیره) را برای وضعیت رسانه شما ارائه میدهد. جلسه رسانه شما همچنین توسط کتابخانه Cast Connect استفاده میشود تا زمانیکه پیامهای خاصی را از فرستنده دریافت کرده است، مانند مکث، سیگنال دهد.
برای اطلاعات بیشتر درباره جلسه رسانه و نحوه مقداردهی اولیه جلسه رسانه، راهنمای کار با جلسه رسانه را ببینید.
چرخه حیات جلسه رسانه
برنامه شما باید هنگام شروع بازپخش، جلسه رسانه ایجاد کند و وقتی دیگر قابلکنترل نیست، آن را رها کند. برای مثال، اگر برنامهتان برنامه ویدیو است، باید وقتی کاربر از فعالیت بازپخش خارج میشود (با انتخاب «برگشت» برای مرور محتوای دیگر یا با بردن برنامه به پسزمینه)، جلسه را رها کنید. اگر برنامهتان برنامه موسیقی است، باید وقتی برنامهتان دیگر رسانهای پخش نمیکند، آن را رها کنید.
درحال بهروزرسانی وضعیت جلسه
دادههای موجود در جلسه رسانه شما باید با وضعیت پخشکننده شما بهروز نگه داشته شود. برای مثال، وقتی بازپخش موقتاً متوقف میشود، باید وضعیت بازپخش و همچنین کنشهای پشتیبانیشده را بهروز کنید. جدولهای زیر نشان میدهند که مسئول بهروز نگه داشتن کدام ایالتها هستید.
MediaMetadataCompat
| فیلد فراداده | شرح |
|---|---|
| METADATA_KEY_TITLE (الزامی) | عنوان رسانه. |
| METADATA_KEY_DISPLAY_SUBTITLE | زیرنویس. |
| METADATA_KEY_DISPLAY_ICON_URI | نشانی وب نماد. |
| METADATA_KEY_DURATION (الزامی) | مدتزمان رسانه. |
| METADATA_KEY_MEDIA_URI | Content ID. |
| METADATA_KEY_ARTIST | هنرمند. |
| METADATA_KEY_ALBUM | آلبوم. |
PlaybackStateCompat
| روش الزامی | شرح |
|---|---|
| setActions() | فرمانهای رسانهای پشتیبانیشده را تنظیم میکند. |
| setState() | وضعیت پخش و موقعیت فعلی را تنظیم کنید. |
MediaSessionCompat
| روش الزامی | شرح |
|---|---|
| setRepeatMode() | حالت تکرار را تنظیم میکند. |
| setShuffleMode() | حالت پخش درهم را تنظیم میکند. |
| setMetadata() | فرادادههای رسانه را تنظیم میکند. |
| setPlaybackState() | وضعیت بازپخش را تنظیم میکند. |
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
| کنشها | شرح |
|---|---|
| onPlay() | ازسرگیری |
| onPause() | مکث |
| onSeekTo() | رفتن به موقعیت |
| onStop() | متوقف کردن رسانه فعلی |
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());
درحال پیکربندی پشتیبانی Cast
وقتی درخواست راهاندازی توسط برنامه فرستنده ارسال میشود، قصدی با فضای نام برنامه ایجاد میشود. برنامه شما مسئول رسیدگی به آن
و ایجاد نمونهای از
شیء CastReceiverContext
هنگام راهاندازی برنامه تلویزیون است. شیء CastReceiverContext برای تعامل با Cast درحین اجرای برنامه تلویزیون لازم است. این شیء به برنامه تلویزیون شما امکان میدهد پیامهای رسانه Cast را که از هر فرستنده متصلی میآید بپذیرد.
راهاندازی Android TV
درحال افزودن فیلتر قصد راهاندازی
فیلتر هدف جدیدی به فعالیتی که میخواهید هدف راهاندازی را از برنامه فرستنده شما مدیریت کند اضافه کنید:
<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>
ارائهدهنده گزینههای گیرنده را مشخص کنید
باید
ReceiverOptionsProvider
را پیادهسازی کنید تا
CastReceiverOptions
را ارائه دهید:
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" />
از ReceiverOptionsProvider برای ارائه CastReceiverOptions هنگام مقداردهی اولیه CastReceiverContext استفاده میشود.
بافت گیرنده Cast
وقتی برنامهتان ایجاد شد،
CastReceiverContext
را مقداردهی اولیه کنید:
override fun onCreate() { CastReceiverContext.initInstance(this) ... }
@Override public void onCreate() { CastReceiverContext.initInstance(this); ... }
وقتی برنامهتان به پیشزمینه منتقل میشود، CastReceiverContext را شروع کنید:
CastReceiverContext.getInstance().start()
CastReceiverContext.getInstance().start();
برای برنامههای ویدیویی یا برنامههایی که از بازپخش پسزمینهای پشتیبانی نمیکنند،
stop()
را در
CastReceiverContext
فراخوانی کنید:
// Player has stopped. CastReceiverContext.getInstance().stop()
// Player has stopped. CastReceiverContext.getInstance().stop();
علاوهبراین، اگر برنامهتان از پخش در پسزمینه پشتیبانی میکند، وقتی پخش در پسزمینه متوقف میشود، stop() را در CastReceiverContext فراخوانی کنید.
اکیداً توصیه میکنیم از LifecycleObserver از کتابخانه
androidx.lifecycle
برای مدیریت تماس
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 به MediaManager
وقتی
MediaSession ایجاد میکنید،
باید کد MediaSession فعلی را نیز به
CastReceiverContext
ارائه دهید تا بداند فرمانها را به کجا ارسال کند و وضعیت بازپخش رسانه را بازیابی کند:
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(); } }
استفاده از Exoplayer با Cast Connect
اگر از
Exoplayer استفاده میکنید، میتوانید از
MediaSessionConnector
استفاده کنید تا بهطور خودکار جلسه و همه اطلاعات مربوطه ازجمله
وضعیت بازپخش را بهجای ردیابی دستی تغییرات حفظ کنید.
MediaSessionConnector.MediaButtonEventHandler
میتواند برای رسیدگی به رویدادهای MediaButton با فراخوانی
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); ... } }
راهاندازی برنامه فرستنده
فعال کردن پشتیبانی از Cast Connect
پساز بهروزرسانی برنامه فرستنده با پشتیبانی Cast Connect، میتوانید با تنظیم پرچم
androidReceiverCompatible
روی
LaunchOptions
بهصورت 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);
راهاندازی «کنسول توسعهدهندگان Cast»
پیکربندی برنامه Android TV
نام بسته برنامه Android TV خود را در کنسول توسعهدهنده Cast اضافه کنید تا آن را با شناسه برنامه Cast خود مرتبط کنید.

ثبت دستگاههای توسعهدهنده
شماره سریال دستگاه Android TV را که میخواهید برای توسعه استفاده کنید در کنسول توسعهدهنده Cast ثبت کنید.

بدون ثبت، Cast Connect بهدلایل امنیتی فقط برای برنامههای نصبشده از «فروشگاه Google Play» کار خواهد کرد.
برای اطلاعات بیشتر درباره ثبت دستگاه Cast یا Android TV برای توسعه Cast، به صفحه ثبتنام مراجعه کنید.
درحال بار کردن رسانه
اگر قبلاً پشتیبانی از پیوند عمیق را در برنامه 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 در فرستنده
ممکن است برنامه «گیرنده وب» و برنامه Android TV شما از پیوندهای عمیق و credentials متفاوتی پشتیبانی کنند (برای مثال اگر اصالتسنجی را در دو پلاتفرم بهطور متفاوتی انجام میدهید). برای رفع این مشکل، میتوانید
entity و credentials جایگزین برای Android TV ارائه دهید:
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 شما راهاندازی شود، کیت توسعه نرمافزار
entity و credentials را با atvEntity و atvCredentials شما
(درصورت مشخص شدن) لغو میکند.
بار کردن با Content ID یا MediaQueueData
اگر از entity یا atvEntity استفاده نمیکنید و از Content ID یا
نشانی وب محتوا در «اطلاعات رسانه» خود استفاده میکنید یا از «دادههای درخواست بارگیری رسانه»
با جزئیات بیشتر استفاده میکنید، باید فیلتر قصد ازپیش تعریفشده زیر را در
برنامه 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().
همچنین، برخیاز فرمانهای صف باید در اینجا پیادهسازی شوند زیرا صف 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 TaskonSkipAd(RequestData requestData) { // Skip your ad ... return Tasks.forResult(null); } } MediaManager mediaManager = CastReceiverContext.getInstance().getMediaManager(); mediaManager.setMediaCommandCallback(new MyMediaCommandCallback());
فرمانهای رسانهای پشتیبانیشده را مشخص کنید
همانند گیرنده Cast، برنامه Android TV شما باید مشخص کند کدام فرمانها
پشتیبانی میشوند تا فرستندهها بتوانند برخیاز کنترلهای میانای کاربر را فعال یا غیرفعال کنند. برای
فرمانهایی که بخشی از
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 شما از تغییر نرخ بازپخش پشتیبانی نمیکند اما برنامه «گیرنده وب» شما پشتیبانی میکند، باید کنشهای پشتیبانیشده را بهدرستی در هر پلاتفرم تنظیم کنید و مطمئن شوید که برنامه فرستنده شما واسط کاربر را بهدرستی ارائه میکند.
درحال اصلاح MediaStatus
برای پشتیبانی از ویژگیهای پیشرفته مانند قطعهها، آگهیها، پخش زنده، و صفبندی، برنامه 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();کتابخانه مشتری ما MediaStatus پایه را از MediaSession دریافت خواهد کرد،
برنامه Android TV شما میتواند وضعیت اضافی را مشخص کند و وضعیت را ازطریق
اصلاحکننده MediaStatus لغو کند.
برخیاز حالتها و فرادادهها را میتوان هم در MediaSession و هم در
MediaStatusModifier تنظیم کرد. اکیداً توصیه میکنیم آنها را فقط در
MediaSession تنظیم کنید. همچنان میتوانید از اصلاحکننده برای لغو کردن وضعیتها در
MediaSession استفاده کنید—این کار توصیه نمیشود زیرا وضعیت در اصلاحکننده همیشه
اولویت بالاتری نسبت به مقادیر ارائهشده توسط MediaSession دارد.
رهگیری MediaStatus قبلاز ارسال
همانند SDK گیرنده وب، اگر میخواهید قبلاز ارسال، کارهای نهایی را انجام دهید، میتوانید یک
MediaStatusInterceptor
را برای پردازش
MediaStatus
که قرار است ارسال شود، مشخص کنید. ما یک
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 بپیوندد. اگر کاربر اطلاعات کاربری ارائه دهد، برنامه ATV شما باید اطلاعات کاربری او را مدیریت کند تا پیشرفت او و سایر دادههای کاربر بتواند بهدرستی ردیابی شود.
وقتی برنامه فرستنده شما برنامه Android TV شما را راهاندازی میکند یا به آن میپیوندد، برنامه فرستنده شما باید اعتبارنامهای را ارائه دهد که نشاندهنده فردی است که به جلسه میپیوندد.
قبلاز اینکه فرستنده برنامه Android TV شما را راهاندازی کند و به آن بپیوندد، میتوانید بررسیکننده راهاندازی را مشخص کنید تا ببینید آیا اطلاعات کاربری فرستنده مجاز است یا نه. اگر اینطور نباشد، Cast Connect SDK به راهاندازی «گیرنده وب» شما برمیگردد.
دادههای اعتبارنامه راهاندازی برنامه فرستنده
در سمت فرستنده، میتوانید CredentialsData را برای نشان دادن فردی که به جلسه میپیوندد مشخص کنید.
credentials رشتهای است که میتواند توسط کاربر تعریف شود، بهشرطی که برنامه ATV شما بتواند آن را درک کند. credentialsType مشخص میکند که CredentialsData از کدام پلاتفرم میآید یا میتواند مقدار سفارشی باشد. بهطور پیشفرض روی پلاتفرمی تنظیم شده است که از آن ارسال میشود.
CredentialsData فقط درطول زمان راهاندازی یا پیوستن به برنامه Android TV شما ارسال میشود. اگر دوباره آن را درحین اتصال تنظیم کنید، به برنامه Android TV شما منتقل نخواهد شد. اگر فرستنده شما درحین اتصال نمایه را تغییر دهد، میتوانید در جلسه بمانید یا اگر فکر میکنید نمایه جدید با جلسه ناسازگار است، SessionManager.endCurrentCastSession(boolean stopCasting) را فراخوانی کنید.
CredentialsData
برای هر فرستنده را میتوان بااستفاده از
getSenders
در
CastReceiverContext
برای دریافت 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.6 یا بالاتر نیاز دارد.
هرزمان پساز تنظیم گزینهها میتوان آن را فراخوانی کرد:
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
وقتی فرستندهای تلاش میکند راهاندازی کند یا بپیوندد،
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 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(); } }
حل کردن true در
LaunchRequestChecker
برنامه ATV را راهاندازی میکند و false برنامه «گیرنده وب» شما را راهاندازی میکند.
ارسال و دریافت پیامهای سفارشی
پروتکل Cast به شما امکان میدهد پیامهای رشتهای سفارشی را بین فرستندگان و برنامه گیرنده خود ارسال کنید. برای ارسال پیام در سراسر CastReceiverContext، باید قبلاز مقداردهی اولیه آن، یک فضای نام (کانال) ثبت کنید.
Android TV—Specify Custom Namespace
باید جاینامهای پشتیبانیشدهتان را در
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—Sending Messages
// 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—Receive Custom Namespace Messages
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());