این صفحه شامل قطعه کد و توضیحاتی از ویژگی های موجود برای سفارشی کردن برنامه گیرنده تلویزیون Android است.
پیکربندی کتابخانه ها
برای در دسترس قرار دادن Cast Connect API برای برنامه Android TV:
- فایل
build.gradle
را در دایرکتوری ماژول برنامه خود باز کنید. - بررسی کنید که
google()
درrepositories
فهرست شده گنجانده شده باشد.repositories { google() }
- بسته به نوع دستگاه مورد نظر خود برای برنامه خود، آخرین نسخه های کتابخانه ها را به وابستگی های خود اضافه کنید:
- برای برنامه گیرنده اندروید:
dependencies { implementation 'com.google.android.gms:play-services-cast-tv:21.1.0' implementation 'com.google.android.gms:play-services-cast:21.5.0' }
- برای برنامه فرستنده اندروید:
dependencies { implementation 'com.google.android.gms:play-services-cast:21.1.0' implementation 'com.google.android.gms:play-services-cast-framework:21.5.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 یا بالاتر نیاز دارد.
- کتابخانه 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 | شناسه محتوا |
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>
ارائه دهنده گزینه های گیرنده را مشخص کنید
برای ارائه 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" />
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
فراخوانی کنید.
ما قویاً توصیه می کنیم از 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
خود را به دلیل پخش غیرفعال منتشر می کنید، باید یک توکن null در 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
، آمادگی آن را اعلام کنید.
به 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(); } }
به نسخه v4.4.8
یا بالاتر google-cast-sdk
نیاز دارد.
پرچم 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 Developer Console اضافه کنید تا با Cast App ID خود مرتبط شود.
ثبت دستگاه های توسعه دهنده
شماره سریال دستگاه Android TV را که قرار است برای توسعه استفاده کنید در Cast Developer Console ثبت کنید.
بدون ثبت نام، Cast Connect به دلایل امنیتی فقط برای برنامه های نصب شده از فروشگاه Google Play کار می کند.
برای اطلاعات بیشتر در مورد ثبت یک دستگاه Cast یا Android TV برای توسعه Cast، صفحه ثبت نام را ببینید.
در حال بارگیری رسانه
اگر قبلاً پشتیبانی از پیوند عمیق را در برنامه Android TV خود اجرا کرده اید، باید تعریف مشابهی را در Manifest 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);
دستور load از طریق یک intent با لینک عمیق شما و نام بسته ای که در کنسول توسعه دهنده تعریف کرده اید ارسال می شود.
تنظیم اعتبار 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);
اگر برنامه Web Receiver راهاندازی شود، از entity
و credentials
در درخواست بارگیری استفاده میکند. اما اگر برنامه Android TV شما راهاندازی شود، SDK entity
و credentials
را با atvEntity
و atvCredentials
شما لغو میکند (در صورت مشخص شدن).
بارگیری توسط 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
را از intent استخراج کرده و MediaLoadCommandCallback.onLoad()
را فراخوانی می کند. برای رسیدگی به درخواست بارگیری باید این روش را لغو کنید. قبل از فراخوانی MediaManager.onNewIntent()
باید تماس برگشتی ثبت شود (توصیه میشود روی یک متد Activity یا Application onCreate()
باشد).
class MyActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val mediaManager = CastReceiverContext.getInstance().getMediaManager() mediaManager.setMediaLoadCommandCallback(MyMediaLoadCommandCallback()) } } class MyMediaLoadCommandCallback : MediaLoadCommandCallback() { override fun onLoad( senderId: String?, loadRequestData: MediaLoadRequestData ): Task{ return Tasks.call { // Resolve the entity into your data structure and load media. val mediaInfo = loadRequestData.getMediaInfo() if (!checkMediaInfoSupported(mediaInfo)) { // Throw MediaException to indicate load failure. throw MediaException( MediaError.Builder() .setDetailedErrorCode(DetailedErrorCode.LOAD_FAILED) .setReason(MediaError.ERROR_REASON_INVALID_REQUEST) .build() ) } myFillMediaInfo(MediaInfoWriter(mediaInfo)) myPlayerLoad(mediaInfo.getContentUrl()) // Update media metadata and state (this clears all previous status // overrides). castReceiverContext.getMediaManager() .setDataFromLoad(loadRequestData) ... castReceiverContext.getMediaManager().broadcastMediaStatus() // Return the resolved MediaLoadRequestData to indicate load success. return loadRequestData } } private fun myPlayerLoad(contentURL: String) { myPlayer.load(contentURL) // Update the MediaSession state. val playbackState: PlaybackStateCompat = Builder() .setState( player.getState(), player.getPosition(), System.currentTimeMillis() ) ... .build() mediaSession.setPlaybackState(playbackState) }
public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MediaManager mediaManager = CastReceiverContext.getInstance().getMediaManager(); mediaManager.setMediaLoadCommandCallback(new MyMediaLoadCommandCallback()); } } public class MyMediaLoadCommandCallback extends MediaLoadCommandCallback { @Override public 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());
پشتیبانی از دستورات کنترل Cast
برخی از دستورات Cast وجود دارند که در MediaSession
در دسترس نیستند، مانند skipAd()
یا setActiveMediaTracks()
. همچنین، برخی از دستورات صف باید در اینجا پیاده سازی شوند زیرا صف Cast به طور کامل با صف MediaSession
سازگار نیست.
class MyMediaCommandCallback : MediaCommandCallback() { override fun onSkipAd(requestData: RequestData?): Task{ // Skip your ad ... return Tasks.forResult(null) } } val mediaManager = CastReceiverContext.getInstance().getMediaManager() mediaManager.setMediaCommandCallback(MyMediaCommandCallback())
public class MyMediaCommandCallback extends MediaCommandCallback { @Override public TaskonSkipAd(RequestData requestData) { // Skip your ad ... return Tasks.forResult(null); } } MediaManager mediaManager = CastReceiverContext.getInstance().getMediaManager(); mediaManager.setMediaCommandCallback(new MyMediaCommandCallback());
دستورات رسانه پشتیبانی شده را مشخص کنید
همانند گیرنده Cast، برنامه 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 شما در حالی که برنامه Web Receiver شما از تغییر نرخ پخش پشتیبانی نمی کند، باید اقدامات پشتیبانی شده را به درستی در هر پلتفرم تنظیم کنید و مطمئن شوید که برنامه فرستنده شما رابط کاربری را به درستی ارائه می کند.
تغییر وضعیت رسانه
برای پشتیبانی از ویژگیهای پیشرفته مانند آهنگها، تبلیغات، پخش زنده و صفبندی، برنامه 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 قبل از ارسال
همانند Web Receiver 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());
به نسخه v4.8.3
یا بالاتر google-cast-sdk
نیاز دارد.
میتوان در هر زمان پس از تنظیم گزینهها تماس گرفت: 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 - فضای نام سفارشی را مشخص کنید
شما باید فضاهای نام پشتیبانی شده خود را در 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());