این صفحه حاوی تکهکدها و شرح ویژگیهای دردسترس برای سفارشیسازی برنامه «گیرنده Android TV» است.
درحال پیکربندی کتابخانهها
برای دردسترس قرار دادن «میاناهای برنامهسازی کاربردی اتصال پخش محتوا» برای برنامه 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:22.3.1' }
-
برای برنامه «فرستنده Android»:
dependencies { implementation 'com.google.android.gms:play-services-cast:21.1.1' implementation 'com.google.android.gms:play-services-cast-framework:22.3.1' }
-
برای برنامه 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 را که از فرستندگان متصل میآیند بپذیرد.
راهاندازی 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 استفاده میشود.
بافت گیرنده پخش محتوا
وقتی برنامهتان ایجاد شد،
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 فراخوانی کنید.
بهشدت توصیه میکنیم از کتابخانه
androidx.lifecycle
از LifecycleObserver برای مدیریت تماس
CastReceiverContext.start()
و
CastReceiverContext.stop() استفاده کنید،
بهویژه اگر برنامه بومی شما چندین فعالیت دارد. این کار از شرایط رقابت
هنگام فراخوانی start() و stop() از فعالیتهای مختلف جلوگیری میکند.
// Create a LifecycleObserver class. class MyLifecycleObserver : DefaultLifecycleObserver { override fun onStart(owner: LifecycleOwner) { // App prepares to enter foreground. CastReceiverContext.getInstance().start() } override fun onStop(owner: LifecycleOwner) { // App has moved to the background or has terminated. CastReceiverContext.getInstance().stop() } } // Add the observer when your application is being created. class MyApplication : Application() { fun onCreate() { super.onCreate() // Initialize CastReceiverContext. CastReceiverContext.initInstance(this /* android.content.Context */) // Register LifecycleObserver ProcessLifecycleOwner.get().lifecycle.addObserver( MyLifecycleObserver()) } }
// Create a LifecycleObserver class. public class MyLifecycleObserver implements DefaultLifecycleObserver { @Override public void onStart(LifecycleOwner owner) { // App prepares to enter foreground. CastReceiverContext.getInstance().start(); } @Override public void onStop(LifecycleOwner owner) { // App has moved to the background or has terminated. CastReceiverContext.getInstance().stop(); } } // Add the observer when your application is being created. public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); // Initialize CastReceiverContext. CastReceiverContext.initInstance(this /* android.content.Context */); // Register LifecycleObserver ProcessLifecycleOwner.get().getLifecycle().addObserver( new MyLifecycleObserver()); } }
// In AndroidManifest.xml set MyApplication as the application class
<application
...
android:name=".MyApplication">
درحال اتصال MediaSession به 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
میتواند برای مدیریت رویدادهای «دکمه رسانه» با فراخوانی
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، میتوانید آمادگی آن را با تنظیم پرچم
androidReceiverCompatible
روی
LaunchOptions
بهصورت درست اعلام کنید.
به نسخه 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 شما راهاندازی شود، کیت توسعه نرمافزار (SDK)
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().
همچنین، برخیاز دستورات صف باید در اینجا پیادهسازی شوند زیرا صف «پخش محتوا»
با صف 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 شما باید مشخص کند که از کدام دستورات پشتیبانی میکند،
تا فرستندگان بتوانند کنترلهای خاص رابط کاربری را فعال یا غیرفعال کنند. برای فرمانهایی که بخشی از
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 قبلاز ارسال
همانند «کیت توسعه نرمافزار گیرنده وب»، اگر میخواهید قبلاز ارسال، تغییرات نهایی را انجام دهید، میتوانید 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 برنامه «گیرنده وب» شما را راهاندازی میکند.
ارسال و دریافت پیامهای سفارشی
پروتکل «پخش محتوا» به شما امکان میدهد پیامهای رشتهای سفارشی بین فرستندگان و
برنامه گیرنده خود ارسال کنید. باید فضای نامی (کانال) را برای ارسال پیامها
قبلاز مقداردهی اولیه CastReceiverContext
ثبت کنید.
Android TV—فضای نام سفارشی را مشخص کنید
باید جاینامهای پشتیبانیشدهتان را در
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());