Android TV alıcınıza temel özellikler ekleme

Bu sayfada, Android TV alıcı uygulamasını özelleştirmek için kullanılabilecek özelliklerin kod snippet'leri ve açıklamaları yer almaktadır.

Kitaplıkları yapılandırma

Cast Connect API'lerini Android TV uygulamanızda kullanıma sunmak için:

Android
  1. Uygulama modülü dizininizdeki build.gradle dosyasını açın.
  2. google() değerinin listelenen repositories içinde yer aldığını doğrulayın.
      repositories {
        google()
      }
  3. Uygulamanızın hedef cihaz türüne bağlı olarak, kitaplıkların en yeni sürümlerini bağımlılıklarınıza ekleyin:
    • Android alıcı uygulaması için:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast-tv:21.1.1'
          implementation 'com.google.android.gms:play-services-cast:22.1.0'
        }
    • Android Sender uygulaması için:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast:21.1.1'
          implementation 'com.google.android.gms:play-services-cast-framework:22.1.0'
        }
    Hizmetler her güncellendiğinde bu sürüm numarasını güncellediğinizden emin olun.
  4. Değişiklikleri kaydedin ve araç çubuğunda Sync Project with Gradle Files simgesini tıklayın.
iOS
  1. Podfile sürümünün google-cast-sdk 4.8.3 veya sonraki bir sürümü hedeflediğinden emin olun.
  2. iOS 14 veya sonraki sürümleri hedefleyin. Daha fazla bilgi için Sürüm Notları'na bakın.
      platform: ios, '14'
    
      def target_pods
         pod 'google-cast-sdk', '~>4.8.3'
      end
Web
  1. Chromium tarayıcının M87 veya sonraki bir sürümü gerekir.
  2. Web Sender API kitaplığını projenize ekleme
      <script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

AndroidX şartı

Google Play Hizmetleri'nin yeni sürümlerinde, uygulamaların androidx ad alanını kullanmak için güncellenmesi gerekir. AndroidX'e taşıma talimatlarını uygulayın.

Android TV uygulaması ön koşulları

Android TV uygulamanızda Cast Connect'i desteklemek için bir medya oturumundan etkinlikler oluşturup desteklemeniz gerekir. Medya oturumunuz tarafından sağlanan veriler, medya durumunuzla ilgili temel bilgileri (ör. konum, oynatma durumu vb.) sağlar. Medya oturumunuz, gönderenden gelen belirli mesajları (ör. duraklatma) aldığında sinyal vermek için Cast Connect kitaplığı tarafından da kullanılır.

Medya oturumu ve medya oturumunun nasıl başlatılacağı hakkında daha fazla bilgi için Medya oturumuyla çalışma kılavuzu'na bakın.

Medya oturumu yaşam döngüsü

Uygulamanız, oynatma başladığında bir medya oturumu oluşturmalı ve kontrol edilemediğinde bu oturumu serbest bırakmalıdır. Örneğin, uygulamanız bir video uygulamasıysa kullanıcı, diğer içeriklere göz atmak için "geri"yi seçerek veya uygulamayı arka plana alarak oynatma etkinliğinden çıktığında oturumu serbest bırakmanız gerekir. Uygulamanız bir müzik uygulamasıysa artık herhangi bir medya oynatmadığında oturumu serbest bırakmanız gerekir.

Oturum durumu güncelleniyor

Medya oturumunuzdaki veriler, oynatıcınızın durumuyla güncel tutulmalıdır. Örneğin, oynatma duraklatıldığında oynatma durumunu ve desteklenen işlemleri de güncellemeniz gerekir. Aşağıdaki tablolarda, güncel tutmaktan sorumlu olduğunuz durumlar listelenmiştir.

MediaMetadataCompat

Meta veri alanı Açıklama
METADATA_KEY_TITLE (zorunlu) Medya başlığı.
METADATA_KEY_DISPLAY_SUBTITLE Alt başlık.
METADATA_KEY_DISPLAY_ICON_URI Simge URL'si.
METADATA_KEY_DURATION (zorunlu) Medya süresi.
METADATA_KEY_MEDIA_URI Content ID.
METADATA_KEY_ARTIST Sanatçı
METADATA_KEY_ALBUM Albüm

PlaybackStateCompat

Gerekli Yöntem Açıklama
setActions() Desteklenen medya komutlarını ayarlar.
setState() Oynatma durumunu ve mevcut konumu ayarlayın.

MediaSessionCompat

Gerekli Yöntem Açıklama
setRepeatMode() Tekrarlama modunu ayarlar.
setShuffleMode() Karıştırma modunu ayarlar.
setMetadata() Medya meta verilerini ayarlar.
setPlaybackState() Oynatma durumunu ayarlar.
Kotlin
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)
}
Java
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);
}

Aktarım kontrolünü işleme

Uygulamanızda medya oturumu aktarım kontrolü geri çağırma işlevi uygulanmalıdır. Aşağıdaki tabloda, hangi aktarım kontrolü işlemlerini gerçekleştirmeleri gerektiği gösterilmektedir:

MediaSessionCompat.Callback

İşlemler Açıklama
onPlay() Devam ettir
onPause() Duraklat
onSeekTo() Bir konuma gitme
onStop() Mevcut medyayı durdurma
Kotlin
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() );
Java
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());

Yayınlama desteğini yapılandırma

Gönderen uygulama tarafından bir başlatma isteği gönderildiğinde, uygulama ad alanıyla bir amaç oluşturulur. Uygulamanız, bu durumu işlemeyle ve TV uygulaması başlatıldığında CastReceiverContext nesnesinin bir örneğini oluşturmayla sorumludur. TV uygulaması çalışırken Cast ile etkileşim kurmak için CastReceiverContext nesnesi gerekir. Bu nesne, TV uygulamanızın bağlı gönderenlerden gelen Cast medya mesajlarını kabul etmesini sağlar.

Android TV kurulumu

Başlatma amacı filtresi ekleme

Gönderen uygulamanızdan başlatma intent'ini işlemek istediğiniz etkinliğe yeni bir intent filtresi ekleyin:

<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>

Alıcı seçenekleri sağlayıcısını belirtin

ReceiverOptionsProvider uygulamanız gerekir. CastReceiverOptions sağlamak için:

Kotlin
class MyReceiverOptionsProvider : ReceiverOptionsProvider {
  override fun getOptions(context: Context?): CastReceiverOptions {
    return CastReceiverOptions.Builder(context)
          .setStatusText("My App")
          .build()
    }
}
Java
public class MyReceiverOptionsProvider implements ReceiverOptionsProvider {
  @Override
  public CastReceiverOptions getOptions(Context context) {
    return new CastReceiverOptions.Builder(context)
        .setStatusText("My App")
        .build();
  }
}

Ardından, AndroidManifest içinde seçenek sağlayıcıyı belirtin:

 <meta-data
    android:name="com.google.android.gms.cast.tv.RECEIVER_OPTIONS_PROVIDER_CLASS_NAME"
    android:value="com.example.mysimpleatvapplication.MyReceiverOptionsProvider" />

ReceiverOptionsProvider, CastReceiverContext başlatıldığında CastReceiverOptions değerini sağlamak için kullanılır.

Yayın alıcısı bağlamı

Uygulamanız oluşturulduğunda CastReceiverContext öğesini başlatın:

Kotlin
override fun onCreate() {
  CastReceiverContext.initInstance(this)

  ...
}
Java
@Override
public void onCreate() {
  CastReceiverContext.initInstance(this);

  ...
}

Uygulamanız ön plana taşındığında CastReceiverContext başlatın:

Kotlin
CastReceiverContext.getInstance().start()
Java
CastReceiverContext.getInstance().start();

Arama stop() Uygulama, video uygulamaları veya arka planda oynatmayı desteklemeyen uygulamalar için arka plana alındıktan sonra CastReceiverContext üzerinde:

Kotlin
// Player has stopped.
CastReceiverContext.getInstance().stop()
Java
// Player has stopped.
CastReceiverContext.getInstance().stop();

Ayrıca, uygulamanız arka planda oynatmayı destekliyorsa arka planda oynatma durduğunda stop() işlevini CastReceiverContext üzerinde çağırın.

Özellikle yerel uygulamanızda birden fazla etkinlik varsa androidx.lifecycle kitaplığındaki LifecycleObserver'ı kullanarak CastReceiverContext.start() ve CastReceiverContext.stop() çağrılarını yönetmenizi önemle tavsiye ederiz. Bu, farklı etkinliklerden start() ve stop() işlevlerini çağırdığınızda yarış durumlarını önler.

Kotlin
// 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())
  }
}
Java
// 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'a bağlama

MediaSession oluşturduğunuzda, komutları nereye göndereceğini ve medya oynatma durumunu nereden alacağını bilmesi için mevcut MediaSession jetonunu CastReceiverContext'a da sağlamanız gerekir:

Kotlin
val mediaManager: MediaManager = receiverContext.getMediaManager()
mediaManager.setSessionCompatToken(currentMediaSession.getSessionToken())
Java
MediaManager mediaManager = receiverContext.getMediaManager();
mediaManager.setSessionCompatToken(currentMediaSession.getSessionToken());

Oynatma etkin olmadığı için MediaSession öğenizi serbest bıraktığınızda MediaManager üzerinde boş bir jeton ayarlamanız gerekir:

Kotlin
myPlayer.stop()
mediaSession.release()
mediaManager.setSessionCompatToken(null)
Java
myPlayer.stop();
mediaSession.release();
mediaManager.setSessionCompatToken(null);

Uygulamanız arka plandayken medya oynatmayı destekliyorsa uygulamanız arka plana gönderildiğinde CastReceiverContext.stop() işlevini çağırmak yerine bu işlevi yalnızca uygulamanız arka plandayken ve artık medya oynatmadığında çağırmalısınız. Örneğin:

Kotlin
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()
  }
}
Java
public class MyLifecycleObserver implements DefaultLifecycleObserver {
  ...
  // App has moved to the background.
  @Override
  public void onPause(LifecycleOwner owner) {
    mIsBackground = true;

    myStopCastReceiverContextIfNeeded();
  }
}

// Stop playback on the player.
private void myStopPlayback() {
  myPlayer.stop();

  myStopCastReceiverContextIfNeeded();
}

// Stop the CastReceiverContext when both the player has
// stopped and the app has moved to the background.
private void myStopCastReceiverContextIfNeeded() {
  if (mIsBackground && myPlayer.isStopped()) {
    CastReceiverContext.getInstance().stop();
  }
}

Cast Connect ile ExoPlayer'ı kullanma

Exoplayer kullanıyorsanız değişiklikleri manuel olarak izlemek yerine oturumu ve oynatma durumu da dahil olmak üzere tüm ilgili bilgileri otomatik olarak korumak için MediaSessionConnector kullanabilirsiniz.

MediaSessionConnector.MediaButtonEventHandler normalde MediaSessionCompat.Callback tarafından işlenen MediaButton etkinliklerini setMediaButtonEventHandler(MediaButtonEventHandler) çağırarak işlemek için kullanılabilir.

Uygulamanıza MediaSessionConnector entegre etmek için aşağıdaki kodu oynatıcı etkinliği sınıfınıza veya medya oturumunuzu yönettiğiniz yere ekleyin:

Kotlin
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)
    ...
  }
}
Java
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);
    ...
  }
}

Gönderen uygulaması kurulumu

Cast Connect desteğini etkinleştirme

Gönderen uygulamanızı Cast Connect desteğiyle güncelledikten sonra, androidReceiverCompatible işaretini LaunchOptions üzerinde true olarak ayarlayarak uygulamanın hazır olduğunu bildirebilirsiniz.

Android

play-services-cast-framework sürümü 19.0.0 veya daha yeni bir sürüm gerektirir.

androidReceiverCompatible işareti, LaunchOptions (CastOptions'ın bir parçası) içinde ayarlanır:

Kotlin
class CastOptionsProvider : OptionsProvider {
  override fun getCastOptions(context: Context?): CastOptions {
    val launchOptions: LaunchOptions = Builder()
          .setAndroidReceiverCompatible(true)
          .build()
    return CastOptions.Builder()
          .setLaunchOptions(launchOptions)
          ...
          .build()
    }
}
Java
public class CastOptionsProvider implements OptionsProvider {
  @Override
  public CastOptions getCastOptions(Context context) {
    LaunchOptions launchOptions = new LaunchOptions.Builder()
              .setAndroidReceiverCompatible(true)
              .build();
    return new CastOptions.Builder()
        .setLaunchOptions(launchOptions)
        ...
        .build();
  }
}
iOS

google-cast-sdk sürüm v4.4.8 veya daha yeni bir sürüm gerektirir.

androidReceiverCompatible işareti, GCKLaunchOptions (GCKCastOptions'ın bir parçası) içinde ayarlanır:

let options = GCKCastOptions(discoveryCriteria: GCKDiscoveryCriteria(applicationID: kReceiverAppID))
...
let launchOptions = GCKLaunchOptions()
launchOptions.androidReceiverCompatible = true
options.launchOptions = launchOptions
GCKCastContext.setSharedInstanceWith(options)
Web

Chromium tarayıcının M87 veya sonraki bir sürümü gerekir.

const context = cast.framework.CastContext.getInstance();
const castOptions = new cast.framework.CastOptions();
castOptions.receiverApplicationId = kReceiverAppID;
castOptions.androidReceiverCompatible = true;
context.setOptions(castOptions);

Cast Developer Console kurulumu

Android TV uygulamasını yapılandırma

Android TV uygulamanızın paket adını Cast Geliştirici Konsolu'na ekleyerek Cast uygulama kimliğinizle ilişkilendirin.

Geliştirici cihazlarını kaydetme

Geliştirme için kullanacağınız Android TV cihazının seri numarasını Cast Developer Console'a kaydedin.

Cast Connect, güvenlik nedeniyle kayıt olmadan yalnızca Google Play Store'dan yüklenen uygulamalarda çalışır.

Cast veya Android TV cihazını Cast geliştirme için kaydetme hakkında daha fazla bilgi edinmek için kayıt sayfasına bakın.

Medya yükleniyor

Android TV uygulamanızda derin bağlantı desteğini zaten uyguladıysanız Android TV manifestinizde benzer bir tanım yapılandırılmış olmalıdır:

<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>

Gönderen üzerinde varlığa göre yükleme

Gönderenlerde, yükleme isteği için medya bilgilerinde entity değerini ayarlayarak derin bağlantıyı iletebilirsiniz:

Kotlin
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)
Android
Java
MediaInfo mediaToLoad =
    new MediaInfo.Builder("some-id")
        .setEntity("https://example.com/watch/some-id")
        ...
        .build();
MediaLoadRequestData loadRequest =
    new MediaLoadRequestData.Builder()
        .setMediaInfo(mediaToLoad)
        .setCredentials("user-credentials")
        ...
        .build();
remoteMediaClient.load(loadRequest);
iOS
let mediaInfoBuilder = GCKMediaInformationBuilder(entity: "https://example.com/watch/some-id")
...
mediaInformation = mediaInfoBuilder.build()

let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
mediaLoadRequestDataBuilder.mediaInformation = mediaInformation
mediaLoadRequestDataBuilder.credentials = "user-credentials"
...
let mediaLoadRequestData = mediaLoadRequestDataBuilder.build()

remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
Web

Chromium tarayıcının M87 veya sonraki bir sürümü gerekir.

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

Yükleme komutu, derin bağlantınız ve geliştirici konsolunda tanımladığınız paket adıyla birlikte bir amaç aracılığıyla gönderilir.

Gönderende ATV kimlik bilgilerini ayarlama

Web alıcı uygulamanız ve Android TV uygulamanızın farklı derin bağlantıları ve credentials desteklemesi mümkündür (örneğin, kimlik doğrulamayı iki platformda farklı şekilde yapıyorsanız). Bu sorunu gidermek için Android TV'ye yönelik alternatif entity ve credentials sağlayabilirsiniz:

Android
Kotlin
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)
Java
MediaInfo mediaToLoad =
    new MediaInfo.Builder("some-id")
        .setEntity("https://example.com/watch/some-id")
        .setAtvEntity("myscheme://example.com/atv/some-id")
        ...
        .build();
MediaLoadRequestData loadRequest =
    new MediaLoadRequestData.Builder()
        .setMediaInfo(mediaToLoad)
        .setCredentials("user-credentials")
        .setAtvCredentials("atv-user-credentials")
        ...
        .build();
remoteMediaClient.load(loadRequest);
iOS
let mediaInfoBuilder = GCKMediaInformationBuilder(entity: "https://example.com/watch/some-id")
mediaInfoBuilder.atvEntity = "myscheme://example.com/atv/some-id"
...
mediaInformation = mediaInfoBuilder.build()

let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
mediaLoadRequestDataBuilder.mediaInformation = mediaInformation
mediaLoadRequestDataBuilder.credentials = "user-credentials"
mediaLoadRequestDataBuilder.atvCredentials = "atv-user-credentials"
...
let mediaLoadRequestData = mediaLoadRequestDataBuilder.build()

remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
Web

Chromium tarayıcının M87 veya sonraki bir sürümü gerekir.

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 alıcı uygulaması başlatılırsa yükleme isteğinde entity ve credentials kullanılır. Ancak Android TV uygulamanız başlatılırsa SDK, entity ve credentials değerlerini atvEntity ve atvCredentials değerlerinizle (belirtilmişse) geçersiz kılar.

Content ID veya MediaQueueData ile yükleme

entity veya atvEntity kullanmıyorsanız ve Medya Bilgilerinizde Content ID ya da İçerik URL'si kullanıyorsanız veya daha ayrıntılı Medya Yükleme İsteği Verileri'ni kullanıyorsanız Android TV uygulamanıza aşağıdaki önceden tanımlanmış amaç filtresini eklemeniz gerekir:

<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>

Gönderen tarafında, load by entity'ye benzer şekilde, içerik bilgilerinizle bir yükleme isteği oluşturabilir ve load()'ı çağırabilirsiniz.

Android
Kotlin
val mediaToLoad = MediaInfo.Builder("some-id").build()
val loadRequest = MediaLoadRequestData.Builder()
    .setMediaInfo(mediaToLoad)
    .setCredentials("user-credentials")
    ...
    .build()
remoteMediaClient.load(loadRequest)
Java
MediaInfo mediaToLoad =
    new MediaInfo.Builder("some-id").build();
MediaLoadRequestData loadRequest =
    new MediaLoadRequestData.Builder()
        .setMediaInfo(mediaToLoad)
        .setCredentials("user-credentials")
        ...
        .build();
remoteMediaClient.load(loadRequest);
iOS
let mediaInfoBuilder = GCKMediaInformationBuilder(contentId: "some-id")
...
mediaInformation = mediaInfoBuilder.build()

let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
mediaLoadRequestDataBuilder.mediaInformation = mediaInformation
mediaLoadRequestDataBuilder.credentials = "user-credentials"
...
let mediaLoadRequestData = mediaLoadRequestDataBuilder.build()

remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
Web

Chromium tarayıcının M87 veya sonraki bir sürümü gerekir.

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

Yükleme isteklerini işleme

Etkinliğinizde bu yükleme isteklerini işlemek için etkinlik yaşam döngüsü geri çağırma yöntemlerindeki amaçları işlemeniz gerekir:

Kotlin
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.
    ...
  }
}
Java
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, amacın yükleme amacı olduğunu algılarsa amaçtan bir MediaLoadRequestData nesnesi çıkarır ve MediaLoadCommandCallback.onLoad()'ı çağırır. Yük isteğini işlemek için bu yöntemi geçersiz kılmanız gerekir. Geri çağırma, MediaManager.onNewIntent() çağrılmadan önce kaydedilmelidir (bir Etkinlik veya Uygulama onCreate() yönteminde olması önerilir).

Kotlin
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)
  }
Java
public class MyActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    MediaManager mediaManager =
        CastReceiverContext.getInstance().getMediaManager();
    mediaManager.setMediaLoadCommandCallback(new MyMediaLoadCommandCallback());
  }
}

public class MyMediaLoadCommandCallback extends MediaLoadCommandCallback {
  @Override
  public Task onLoad(String senderId, MediaLoadRequestData loadRequestData) {
    return Tasks.call(() -> {
        // Resolve the entity into your data structure and load media.
        MediaInfo mediaInfo = loadRequestData.getMediaInfo();
        if (!checkMediaInfoSupported(mediaInfo)) {
          // Throw MediaException to indicate load failure.
          throw new MediaException(
              new MediaError.Builder()
                  .setDetailedErrorCode(DetailedErrorCode.LOAD_FAILED)
                  .setReason(MediaError.ERROR_REASON_INVALID_REQUEST)
                  .build());
        }
        myFillMediaInfo(new MediaInfoWriter(mediaInfo));
        myPlayerLoad(mediaInfo.getContentUrl());

        // Update media metadata and state (this clears all previous status
        // overrides).
        castReceiverContext.getMediaManager()
            .setDataFromLoad(loadRequestData);
        ...
        castReceiverContext.getMediaManager().broadcastMediaStatus();

        // Return the resolved MediaLoadRequestData to indicate load success.
        return loadRequestData;
    });
}

private void myPlayerLoad(String contentURL) {
  myPlayer.load(contentURL);

  // Update the MediaSession state.
  PlaybackStateCompat playbackState =
      new PlaybackStateCompat.Builder()
          .setState(
              player.getState(), player.getPosition(), System.currentTimeMillis())
          ...
          .build();
  mediaSession.setPlaybackState(playbackState);
}

Yükleme amacını işlemek için amacı tanımladığımız veri yapılarına ayrıştırabilirsiniz (MediaLoadRequestData yükleme istekleri için).

Medya komutlarını destekleme

Temel oynatma kontrolü desteği

Temel entegrasyon komutları, medya oturumuyla uyumlu komutları içerir. Bu komutlar, medya oturumu geri çağırmaları aracılığıyla bildirilir. Bunu desteklemek için medya oturumuna geri arama kaydetmeniz gerekir (bunu zaten yapıyor olabilirsiniz).

Kotlin
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())
Java
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 kontrol komutlarını destekleme

MediaSession'da kullanılamayan bazı Cast komutları vardır. Örneğin, skipAd() veya setActiveMediaTracks(). Ayrıca, Cast sırası MediaSession sırasıyla tam olarak uyumlu olmadığından burada bazı sıra komutlarının uygulanması gerekir.

Kotlin
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())
Java
public class MyMediaCommandCallback extends MediaCommandCallback {
  @Override
  public Task onSkipAd(RequestData requestData) {
    // Skip your ad
    ...
    return Tasks.forResult(null);
  }
}

MediaManager mediaManager =
    CastReceiverContext.getInstance().getMediaManager();
mediaManager.setMediaCommandCallback(new MyMediaCommandCallback());

Desteklenen medya komutlarını belirtme

Yayın alıcınızda olduğu gibi, Android TV uygulamanız da hangi komutların desteklendiğini belirtmelidir. Böylece gönderenler belirli kullanıcı arayüzü kontrollerini etkinleştirebilir veya devre dışı bırakabilir. MediaSession kapsamındaki komutlar için PlaybackStateCompat içinde komutları belirtin. Ek komutlar MediaStatusModifier içinde belirtilmelidir.

Kotlin
// 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)
Java
// 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);

Desteklenmeyen düğmeleri gizleme

Android TV uygulamanız yalnızca temel medya kontrolünü destekliyorsa ancak Web Alıcı uygulamanız daha gelişmiş kontrolü destekliyorsa gönderen uygulamanızın Android TV uygulamasına yayın yaparken doğru şekilde davrandığından emin olmanız gerekir. Örneğin, Android TV uygulamanız oynatma hızını değiştirmeyi desteklemiyorsa ancak Web Alıcı uygulamanız destekliyorsa her platformda desteklenen işlemleri doğru şekilde ayarlamalı ve gönderen uygulamanızın kullanıcı arayüzünü düzgün şekilde oluşturduğundan emin olmalısınız.

Modifying MediaStatus

Parçalar, reklamlar, canlı yayın ve sıralama gibi gelişmiş özellikleri desteklemek için Android TV uygulamanızın MediaSession üzerinden belirlenemeyen ek bilgiler sağlaması gerekir.

Bunu başarmanız için MediaStatusModifier sınıfını sunuyoruz. MediaStatusModifier, her zaman CastReceiverContext içinde ayarladığınız MediaSession üzerinde çalışır.

MediaStatus oluşturmak ve yayınlamak için:

Kotlin
val mediaManager: MediaManager = castReceiverContext.getMediaManager()
val statusModifier: MediaStatusModifier = mediaManager.getMediaStatusModifier()

statusModifier
    .setLiveSeekableRange(seekableRange)
    .setAdBreakStatus(adBreakStatus)
    .setCustomData(customData)

mediaManager.broadcastMediaStatus()
Java
MediaManager mediaManager = castReceiverContext.getMediaManager();
MediaStatusModifier statusModifier = mediaManager.getMediaStatusModifier();

statusModifier
    .setLiveSeekableRange(seekableRange)
    .setAdBreakStatus(adBreakStatus)
    .setCustomData(customData);

mediaManager.broadcastMediaStatus();

İstemci kitaplığımız, MediaSession kaynağından temel MediaStatus değerini alır. Android TV uygulamanız, MediaStatus değiştiricisi aracılığıyla ek durum belirtebilir ve durumu geçersiz kılabilir.

Bazı durumlar ve meta veriler hem MediaSession hem de MediaStatusModifier içinde ayarlanabilir. Bu ayarları yalnızca MediaSession bölümünde yapmanızı kesinlikle öneririz. MediaSession içindeki durumları geçersiz kılmak için değiştiriciyi kullanmaya devam edebilirsiniz. Ancak değiştiricideki durum her zaman MediaSession tarafından sağlanan değerlerden daha yüksek önceliğe sahip olduğundan bu işlem önerilmez.

MediaStatus'u göndermeden önce yakalama

Web Receiver SDK'sında olduğu gibi, göndermeden önce son rötuşları yapmak istiyorsanız gönderilecek MediaStatus öğesini işlemek için bir MediaStatusInterceptor belirtebilirsiniz. MediaStatus gönderilmeden önce üzerinde değişiklik yapmak için MediaStatusWriter iletiriz.

Kotlin
mediaManager.setMediaStatusInterceptor(object : MediaStatusInterceptor {
    override fun intercept(mediaStatusWriter: MediaStatusWriter) {
      // Perform customization.
        mediaStatusWriter.setCustomData(JSONObject("{data: \"my Hello\"}"))
    }
})
Java
mediaManager.setMediaStatusInterceptor(new MediaStatusInterceptor() {
    @Override
    public void intercept(MediaStatusWriter mediaStatusWriter) {
        // Perform customization.
        mediaStatusWriter.setCustomData(new JSONObject("{data: \"my Hello\"}"));
    }
});

Kullanıcı kimlik bilgilerini işleme

Android TV uygulamanız, yalnızca belirli kullanıcıların uygulama oturumunu başlatmasına veya oturuma katılmasına izin veriyor olabilir. Örneğin, yalnızca aşağıdaki durumlarda gönderenin başlatmasına veya katılmasına izin verin:

  • Gönderen uygulama, ATV uygulamasıyla aynı hesap ve profille giriş yapmış olmalıdır.
  • Gönderen uygulaması, ATV uygulamasıyla aynı hesaba ancak farklı bir profile giriş yapmış.

Uygulamanız birden fazla veya anonim kullanıcıyı destekliyorsa ek kullanıcıların ATV oturumuna katılmasına izin verebilirsiniz. Kullanıcı kimlik bilgileri sağlarsa ATV uygulamanız, ilerleme durumu ve diğer kullanıcı verilerinin düzgün şekilde izlenebilmesi için bu kimlik bilgilerini işlemesi gerekir.

Gönderen uygulamanız başlatıldığında veya Android TV uygulamanıza katıldığında, oturuma katılan kullanıcıyı temsil eden kimlik bilgilerini sağlamalıdır.

Gönderen başlatılıp Android TV uygulamanıza katılmadan önce, gönderen kimlik bilgilerine izin verilip verilmediğini görmek için bir başlatma denetleyicisi belirleyebilirsiniz. Aksi takdirde Cast Connect SDK, Web Alıcınızı başlatmaya geri döner.

Gönderen uygulamasının başlatma kimlik bilgileri verileri

Gönderen tarafında, oturuma kimin katıldığını temsil etmek için CredentialsData belirtebilirsiniz.

credentials, ATV uygulamanızın anlayabileceği sürece kullanıcı tarafından tanımlanabilen bir dizedir. credentialsType, CredentialsData öğesinin hangi platformdan geldiğini tanımlar veya özel bir değer olabilir. Varsayılan olarak, gönderildiği platforma ayarlanır.

CredentialsData yalnızca başlatma veya katılma sırasında Android TV uygulamanıza iletilir. Bağlıyken tekrar ayarlarsanız bu ayar Android TV uygulamanıza aktarılmaz. Göndereniniz bağlıyken profili değiştirirse oturumda kalabilir veya yeni profilin oturumla uyumsuz olduğunu düşünüyorsanız SessionManager.endCurrentCastSession(boolean stopCasting) numaralı telefonu arayabilirsiniz.

Her gönderenin CredentialsData değeri, CastReceiverContext üzerinde getSenders kullanılarak alınabilir. SenderInfo değerini almak için getCastLaunchRequest(), CastLaunchRequest değerini almak için getCredentialsData() kullanılır.

Android

play-services-cast-framework sürümü 19.0.0 veya daha yeni bir sürüm gerektirir.

Kotlin
CastContext.getSharedInstance().setLaunchCredentialsData(
    CredentialsData.Builder()
        .setCredentials("{\"userId\": \"abc\"}")
        .build()
)
Java
CastContext.getSharedInstance().setLaunchCredentialsData(
    new CredentialsData.Builder()
        .setCredentials("{\"userId\": \"abc\"}")
        .build());
iOS

google-cast-sdk sürüm v4.8.3 veya daha yeni bir sürüm gerektirir.

Seçenekler ayarlandıktan sonra dilediğiniz zaman çağrılabilir: GCKCastContext.setSharedInstanceWith(options).

GCKCastContext.sharedInstance().setLaunch(
    GCKCredentialsData(credentials: "{\"userId\": \"abc\"}")
Web

Chromium tarayıcının M87 veya sonraki bir sürümü gerekir.

Seçenekler ayarlandıktan sonra dilediğiniz zaman çağrılabilir: cast.framework.CastContext.getInstance().setOptions(options);.

let credentialsData =
    new chrome.cast.CredentialsData("{\"userId\": \"abc\"}");
cast.framework.CastContext.getInstance().setLaunchCredentialsData(credentialsData);

ATV başlatma isteği denetleyicisini uygulama

Gönderen bir yayını başlatmaya veya yayına katılmaya çalıştığında CredentialsData Android TV uygulamanıza iletilir. Aşağıdakileri yapabilirsiniz: LaunchRequestChecker uygulayabilirsiniz. Bu isteği onaylayabilir veya reddedebilirsiniz.

Bir istek reddedilirse ATV uygulamasında yerel olarak başlatmak yerine Web Alıcı yüklenir. ATV'niz, başlatma veya katılma isteğinde bulunan kullanıcıyı işleyemiyorsa isteği reddetmeniz gerekir. Örneğin, ATV uygulamasında istekte bulunan kullanıcıdan farklı bir kullanıcı oturum açmış olabilir ve uygulamanız kimlik bilgilerini değiştiremeyebilir veya ATV uygulamasında şu anda oturum açmış bir kullanıcı olmayabilir.

İsteğe izin verilirse ATV uygulaması başlatılır. Uygulamanız, kullanıcı ATV uygulamasında oturum açmadığında yükleme isteği göndermeyi destekleyip desteklemediğine veya kullanıcı uyuşmazlığı olup olmadığına bağlı olarak bu davranışı özelleştirebilirsiniz. Bu davranış, LaunchRequestChecker içinde tamamen özelleştirilebilir.

CastReceiverOptions.LaunchRequestChecker arayüzünü uygulayan bir sınıf oluşturun:

Kotlin
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.
}
Java
public class MyLaunchRequestChecker
    implements CastReceiverOptions.LaunchRequestChecker {
  @Override
  public Task checkLaunchRequestSupported(CastLaunchRequest launchRequest) {
    return Tasks.call(() -> myCheckLaunchRequest(launchRequest));
  }
}

private boolean myCheckLaunchRequest(CastLaunchRequest launchRequest) {
  CredentialsData credentialsData = launchRequest.getCredentialsData();
  if (credentialsData == null) {
    return false;  // or true if you allow anonymous users to join.
  }

  // The request comes from a mobile device, e.g. checking user match.
  if (credentialsData.getCredentialsType().equals(CredentialsData.CREDENTIALS_TYPE_ANDROID)) {
    return myCheckMobileCredentialsAllowed(credentialsData.getCredentials());
  }

  // Unrecognized credentials type.
  return false;
}

Ardından, ReceiverOptionsProvider uygulamanızda ayarlayın:

Kotlin
class MyReceiverOptionsProvider : ReceiverOptionsProvider {
  override fun getOptions(context: Context?): CastReceiverOptions {
    return CastReceiverOptions.Builder(context)
        ...
        .setLaunchRequestChecker(MyLaunchRequestChecker())
        .build()
  }
}
Java
public class MyReceiverOptionsProvider implements ReceiverOptionsProvider {
  @Override
  public CastReceiverOptions getOptions(Context context) {
    return new CastReceiverOptions.Builder(context)
        ...
        .setLaunchRequestChecker(new MyLaunchRequestChecker())
        .build();
  }
}

LaunchRequestChecker'de true sorununu çözme LaunchRequestChecker, ATV uygulamasını başlatır ve false, Web Alıcısı uygulamanızı başlatır.

Özel Mesaj Gönderme ve Alma

Cast protokolü, gönderenler ile alıcı uygulamanız arasında özel dize mesajları göndermenize olanak tanır. CastReceiverContext başlatmadan önce mesaj göndermek için bir ad alanı (kanal) kaydetmeniz gerekir.

Android TV: Özel Ad Alanı Belirtme

Kurulum sırasında CastReceiverOptions dosyanızda desteklenen ad alanlarınızı belirtmeniz gerekir:

Kotlin
class MyReceiverOptionsProvider : ReceiverOptionsProvider {
  override fun getOptions(context: Context?): CastReceiverOptions {
    return CastReceiverOptions.Builder(context)
        .setCustomNamespaces(
            Arrays.asList("urn:x-cast:com.example.cast.mynamespace")
        )
        .build()
  }
}
Java
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'de Mesaj Gönderme

Kotlin
// If senderId is null, then the message is broadcasted to all senders.
CastReceiverContext.getInstance().sendMessage(
    "urn:x-cast:com.example.cast.mynamespace", senderId, customString)
Java
// 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'de Özel Ad Alanı Mesajları Alma

Kotlin
class MyCustomMessageListener : MessageReceivedListener {
    override fun onMessageReceived(
        namespace: String, senderId: String?, message: String ) {
        ...
    }
}

CastReceiverContext.getInstance().setMessageReceivedListener(
    "urn:x-cast:com.example.cast.mynamespace", new MyCustomMessageListener());
Java
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());