Wichtige Funktionen zu Ihrem Android TV-Receiver hinzufügen

Diese Seite enthält Code-Snippets und Beschreibungen der Funktionen, mit denen sich eine Android TV-Receiver-App anpassen lässt.

Bibliotheken konfigurieren

So machen Sie Cast Connect APIs für Ihre Android TV App verfügbar:

Android
  1. Öffnen Sie die Datei build.gradle im Verzeichnis des Anwendungsmoduls.
  2. Prüfen Sie, ob google() in den aufgeführten repositories enthalten ist.
      repositories {
        google()
      }
  3. Fügen Sie je nach Zielgerättyp Ihrer App die neuesten Versionen der Bibliotheken zu den Abhängigkeiten hinzu:
    • Für die Android-Empfänger-App:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast-tv:21.1.1'
          implementation 'com.google.android.gms:play-services-cast:22.0.0'
        }
    • Für die Sender-App für Android:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast:21.1.1'
          implementation 'com.google.android.gms:play-services-cast-framework:22.0.0'
        }
    Aktualisieren Sie diese Versionsnummer jedes Mal, wenn die Dienste aktualisiert werden.
  4. Speichern Sie die Änderungen und klicken Sie in der Symbolleiste auf Sync Project with Gradle Files.
iOS
  1. Achten Sie darauf, dass Ihre Podfile auf google-cast-sdk 4.8.3 oder höher ausgerichtet ist.
  2. Richten Sie Ihre Anzeigen auf iOS 14 oder höher aus. Weitere Informationen finden Sie in den Versionshinweisen.
      platform: ios, '14'
    
      def target_pods
         pod 'google-cast-sdk', '~>4.8.3'
      end
Web
  1. Erfordert die Chromium-Browserversion M87 oder höher.
  2. Web Sender API-Bibliothek zum Projekt hinzufügen
      <script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

AndroidX-Anforderung

Für neue Versionen der Google Play-Dienste muss eine App aktualisiert werden, damit sie den androidx-Namensraum verwenden kann. Folgen Sie der Anleitung zur Migration zu AndroidX.

Android TV-App – Voraussetzungen

Wenn Sie Cast Connect in Ihrer Android TV-App unterstützen möchten, müssen Sie Ereignisse aus einer Mediensitzung erstellen und unterstützen. Die von Ihrer Mediensitzung bereitgestellten Daten enthalten die grundlegenden Informationen für den Medienstatus, z. B. Position und Wiedergabestatus. Die Mediensitzung wird auch von der Cast Connect-Bibliothek verwendet, um anzuzeigen, dass bestimmte Nachrichten von einem Absender empfangen wurden, z. B. „Pause“.

Weitere Informationen zu Mediensitzungen und zur Initialisierung einer Mediensitzung findest du im Leitfaden zur Arbeit mit Mediensitzungen.

Mediensitzungslebenszyklus

Ihre App sollte beim Starten der Wiedergabe eine Mediensitzung erstellen und sie freigeben, wenn sie nicht mehr gesteuert werden kann. Wenn es sich beispielsweise um eine Video-App handelt, sollten Sie die Sitzung freigeben, wenn der Nutzer die Wiedergabeaktivität beendet – entweder durch Auswahl von „Zurück“, um andere Inhalte aufzurufen, oder durch Auslagern der App in den Hintergrund. Bei einer Musik-App sollten Sie die Sitzung freigeben, wenn in der App keine Medien mehr wiedergegeben werden.

Sitzungsstatus wird aktualisiert

Die Daten in deiner Mediensitzung sollten dem Status deines Players entsprechen. Wenn die Wiedergabe beispielsweise pausiert ist, solltest du den Wiedergabestatus sowie die unterstützten Aktionen aktualisieren. In den folgenden Tabellen sind die Status aufgeführt, die Sie auf dem neuesten Stand halten müssen.

MediaMetadataCompat

Metadatenfeld Beschreibung
METADATA_KEY_TITLE (erforderlich) Der Medientitel.
METADATA_KEY_DISPLAY_SUBTITLE Der Untertitel.
METADATA_KEY_DISPLAY_ICON_URI Die Symbol-URL.
METADATA_KEY_DURATION (erforderlich) Mediendauer
METADATA_KEY_MEDIA_URI Die Content ID.
METADATA_KEY_ARTIST Der Künstler.
METADATA_KEY_ALBUM Das Album.

PlaybackStateCompat

Erforderliche Methode Beschreibung
setActions() Hier legen Sie die unterstützten Medienbefehle fest.
setState() Legen Sie den Wiedergabestatus und die aktuelle Position fest.

MediaSessionCompat

Erforderliche Methode Beschreibung
setRepeatMode() Legt den Wiederholungsmodus fest.
setShuffleMode() Legt den Zufallsmix fest.
setMetadata() Legt Medienmetadaten fest.
setPlaybackState() Legt den Wiedergabestatus fest.
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);
}

Transportsteuerung verarbeiten

Ihre App sollte den Rückruf für die Mediensitzungs-Transportsteuerung implementieren. In der folgenden Tabelle sind die Aktionen der Transportsteuerung aufgeführt, die verarbeitet werden müssen:

MediaSessionCompat.Callback

Aktionen Beschreibung
onPlay() Fortsetzen
onPause() Pausieren
onSeekTo() Zu einer Position springen
onStop() Aktuelle Medien anhalten
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());

Unterstützung für Google Cast konfigurieren

Wenn eine Startanfrage von einer Absenderanwendung gesendet wird, wird eine Intent-Anfrage mit einem Anwendungs-Namespace erstellt. Deine Anwendung ist dafür verantwortlich, die Anfrage zu verarbeiten und beim Starten der TV-App eine Instanz des Objekts CastReceiverContext zu erstellen. Das CastReceiverContext-Objekt ist erforderlich, um mit Google Cast zu interagieren, während die TV-App ausgeführt wird. Mit diesem Objekt kann Ihre Fernseher-App Cast-Mediennachrichten von allen verbundenen Absendern akzeptieren.

Android TV-Einrichtung

Filter für Startabsicht hinzufügen

Fügen Sie der Aktivität, für die Sie den Intent zum Starten Ihrer Sender-App verarbeiten möchten, einen neuen Intent-Filter hinzu:

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

Anbieter von Empfängeroptionen angeben

Sie müssen eine ReceiverOptionsProvider implementieren, um CastReceiverOptions bereitzustellen:

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

Geben Sie dann in AndroidManifest den Optionsanbieter an:

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

Die ReceiverOptionsProvider wird verwendet, um die CastReceiverOptions bereitzustellen, wenn CastReceiverContext initialisiert wird.

Kontext des Streamingempfängers

Initialisieren Sie CastReceiverContext, wenn Sie die App erstellen:

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

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

  ...
}

Starten Sie CastReceiverContext, wenn Ihre App in den Vordergrund wechselt:

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

Wenn die App in den Hintergrund wechselt, können Sie bei Video-Apps oder Apps, die die Hintergrundwiedergabe nicht unterstützen, auf CastReceiverContext tippen, um stop() aufzurufen:

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

Wenn Ihre App die Hintergrundwiedergabe unterstützt, können Sie außerdem auf dem CastReceiverContext die Taste stop() drücken, wenn die Wiedergabe im Hintergrund stoppt.

Wir empfehlen Ihnen dringend, den LifecycleObserver aus der Bibliothek androidx.lifecycle zu verwenden, um das Aufrufen von CastReceiverContext.start() und CastReceiverContext.stop() zu verwalten, insbesondere wenn Ihre native App mehrere Aktivitäten hat. So werden Race-Bedingungen vermieden, wenn start() und stop() aus verschiedenen Aktivitäten aufgerufen werden.

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 mit MediaManager verbinden

Wenn du eine MediaSession erstellst, musst du auch das aktuelle MediaSession-Token an CastReceiverContext übergeben, damit es weiß, wohin die Befehle gesendet und der Status der Medienwiedergabe abgerufen werden soll:

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

Wenn du deine MediaSession aufgrund von Inaktivität freigibst, solltest du ein Null-Token für MediaManager festlegen:

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

Wenn Ihre App die Wiedergabe von Medien unterstützt, während sie im Hintergrund ausgeführt wird, sollten Sie CastReceiverContext.stop() nicht aufrufen, wenn Ihre App in den Hintergrund verschoben wird, sondern nur, wenn sie im Hintergrund ausgeführt wird und keine Medien mehr wiedergegeben werden. Beispiel:

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

Exoplayer mit Cast Connect verwenden

Wenn du Exoplayer verwendest, kannst du mit MediaSessionConnector die Sitzung und alle zugehörigen Informationen, einschließlich des Wiedergabestatus, automatisch verwalten, anstatt die Änderungen manuell zu erfassen.

Mit MediaSessionConnector.MediaButtonEventHandler können MediaButton-Ereignisse verarbeitet werden, indem setMediaButtonEventHandler(MediaButtonEventHandler) aufgerufen wird. Diese werden standardmäßig von MediaSessionCompat.Callback verarbeitet.

Wenn du MediaSessionConnector in deine App einbinden möchtest, füge deiner Player-Aktivitätsklasse oder dem Ort, an dem du deine Mediensitzung verwaltest, Folgendes hinzu:

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

Einrichtung der Absender-App

Unterstützung für Cast Connect aktivieren

Nachdem du deine Sender-App mit Cast Connect-Unterstützung aktualisiert hast, kannst du ihre Verfügbarkeit angeben, indem du das Flag LaunchOptions auf androidReceiverCompatible setze.

Android

Erfordert play-services-cast-framework Version 19.0.0 oder höher.

Das Flag androidReceiverCompatible ist in LaunchOptions (Teil von CastOptions) gesetzt:

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

Erfordert google-cast-sdk Version v4.4.8 oder höher.

Das Flag androidReceiverCompatible ist in GCKLaunchOptions (Teil von GCKCastOptions) gesetzt:

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

Erfordert die Chromium-Browserversion M87 oder höher.

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

Cast Developer Console einrichten

Android TV App konfigurieren

Fügen Sie den Paketnamen Ihrer Android TV-App in der Cast Developer Console hinzu, um ihn mit Ihrer Cast App-ID zu verknüpfen.

Entwicklergeräte registrieren

Registrieren Sie die Seriennummer des Android TV-Geräts, das Sie für die Entwicklung verwenden möchten, in der Cast Developer Console.

Ohne Registrierung funktioniert Cast Connect aus Sicherheitsgründen nur für Apps, die über den Google Play Store installiert wurden.

Weitere Informationen zur Registrierung eines Chromecast- oder Android TV-Geräts für die Entwicklung von Chromecast-Apps findest du auf der Registrierungsseite.

Medien werden geladen

Wenn Sie in Ihrer Android TV App bereits Deeplink-Unterstützung implementiert haben, sollte in Ihrem Android TV-Manifest eine ähnliche Definition konfiguriert sein:

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

Nach Entität des Absenders laden

Auf den Absenderseiten kannst du den Deeplink übergeben, indem du die entity in den Medieninformationen für die Ladeanfrage festlegst:

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

Erfordert die Chromium-Browserversion M87 oder höher.

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

Der Befehl zum Laden wird über einen Intent mit Ihrem Deeplink und dem Paketnamen gesendet, den Sie in der Entwicklerkonsole definiert haben.

ATV-Anmeldedaten für den Absender festlegen

Es ist möglich, dass deine Web-Empfänger-App und deine Android TV-App unterschiedliche Deeplinks und credentials unterstützen (z. B. wenn du die Authentifizierung auf den beiden Plattformen unterschiedlich handhabst). Sie können für Android TV alternative entity und credentials angeben:

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

Erfordert die Chromium-Browserversion M87 oder höher.

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

Wenn die Web Receiver App gestartet wird, verwendet sie entity und credentials in der Ladeanfrage. Wenn deine Android TV-App jedoch gestartet wird, überschreibt das SDK entity und credentials mit deinen atvEntity und atvCredentials (falls angegeben).

Laden nach Content ID oder MediaQueueData

Wenn du entity oder atvEntity nicht verwendest, sondern die Content-ID oder die Content-URL in deinen Medieninformationen oder die detaillierteren Daten für die Medienladeanfrage verwendest, musst du in deiner Android TV-App den folgenden vordefinierten Intent-Filter hinzufügen:

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

Auf der Absenderseite kannst du ähnlich wie bei nach Entität laden eine Ladeanfrage mit deinen Inhaltsinformationen erstellen und load() aufrufen.

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

Erfordert die Chromium-Browserversion M87 oder höher.

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

Ladeanfragen verarbeiten

Um diese Ladeanfragen in Ihrer Aktivität zu verarbeiten, müssen Sie die Intents in Ihren Lifecycle-Callbacks für die Aktivität verarbeiten:

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

Wenn MediaManager erkennt, dass es sich um einen Lade-Intent handelt, wird ein MediaLoadRequestData-Objekt aus dem Intent extrahiert und MediaLoadCommandCallback.onLoad() aufgerufen. Sie müssen diese Methode überschreiben, um die Ladeanfrage zu verarbeiten. Der Callback muss registriert werden, bevor MediaManager.onNewIntent() aufgerufen wird. Wir empfehlen, ihn in einer onCreate()-Methode für Aktivitäten oder Anwendungen zu verwenden.

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

Zum Verarbeiten der Ladeabsicht kannst du sie in die von uns definierten Datenstrukturen parsen (MediaLoadRequestData für Ladeanfragen).

Unterstützte Medienbefehle

Unterstützung der grundlegenden Wiedergabesteuerung

Zu den grundlegenden Integrationsbefehlen gehören die Befehle, die mit der Mediensitzung kompatibel sind. Diese Befehle werden über Rückrufe für Mediensitzungen benachrichtigt. Dazu musst du einen Rückruf zur Mediensitzung registrieren. Möglicherweise hast du das bereits getan.

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

Unterstützte Befehle für die Übertragungssteuerung

Einige Streamingbefehle sind in MediaSession nicht verfügbar, z. B. skipAd() oder setActiveMediaTracks(). Außerdem müssen hier einige Befehle für die Warteschlange implementiert werden, da die Cast-Warteschlange nicht vollständig mit der MediaSession-Warteschlange kompatibel ist.

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

Unterstützte Medienbefehle angeben

Wie bei Ihrem Cast-Receiver sollte auch Ihre Android TV-App angeben, welche Befehle unterstützt werden, damit Absender bestimmte Steuerelemente der Benutzeroberfläche aktivieren oder deaktivieren können. Geben Sie Befehle, die zu MediaSession gehören, in PlaybackStateCompat an. Zusätzliche Befehle sollten in der MediaStatusModifier angegeben werden.

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

Nicht unterstützte Schaltflächen ausblenden

Wenn deine Android TV-App nur grundlegende Mediensteuerung unterstützt, deine Web-Receiver-App aber eine erweiterte Steuerung, solltest du dafür sorgen, dass sich deine Sender-App beim Streamen an die Android TV-App anpasst. Wenn deine Android TV-App beispielsweise die Wiedergabegeschwindigkeit nicht ändern kann, deine Web-Receiver-App aber schon, solltest du die unterstützten Aktionen auf jeder Plattform richtig festlegen und dafür sorgen, dass die Benutzeroberfläche deiner Sender-App richtig gerendert wird.

MediaStatus ändern

Damit erweiterte Funktionen wie Titel, Anzeigen, Livestreams und Wiedergabelisten unterstützt werden können, muss deine Android TV-App zusätzliche Informationen bereitstellen, die nicht über MediaSession ermittelt werden können.

Dazu stellen wir die Klasse MediaStatusModifier bereit. MediaStatusModifier verwendet immer die MediaSession, die Sie in CastReceiverContext festgelegt haben.

So erstellst du MediaStatus und sendest sie:

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

Unsere Clientbibliothek erhält die Basis-MediaStatus von MediaSession. Deine Android TV-App kann einen zusätzlichen Status angeben und den Status über einen MediaStatus-Modifikator überschreiben.

Einige Status und Metadaten können sowohl in MediaSession als auch in MediaStatusModifier festgelegt werden. Wir empfehlen dringend, sie nur in MediaSession festzulegen. Sie können die Status in MediaSession weiterhin mit dem Modifikator überschreiben. Wir raten davon ab, da der Status im Modifikator immer eine höhere Priorität hat als die Werte, die von MediaSession bereitgestellt werden.

MediaStatus vor dem Senden abfangen

Wie beim Web Receiver SDK kannst du vor dem Senden letzte Änderungen vornehmen, indem du eine MediaStatusInterceptor angibst, um die zu sendende MediaStatus zu verarbeiten. Wir übergeben einen MediaStatusWriter, um die MediaStatus vor dem Senden zu manipulieren.

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\"}"));
    }
});

Umgang mit Nutzeranmeldedaten

Möglicherweise können nur bestimmte Nutzer die App-Sitzung starten oder ihr beitreten. Sie können beispielsweise festlegen, dass ein Absender eine Videokonferenz nur starten oder beitreten darf, wenn:

  • Die Absender-App ist im selben Konto und Profil wie die ATV-App angemeldet.
  • Die Sender-App ist im selben Konto, aber in einem anderen Profil als die ATV-App angemeldet.

Wenn Ihre App mehrere oder anonyme Nutzer verarbeiten kann, können Sie zusätzlichen Nutzern erlauben, der ATV-Sitzung beizutreten. Wenn der Nutzer Anmeldedaten angibt, muss deine ATV-App diese Anmeldedaten verarbeiten, damit sein Fortschritt und andere Nutzerdaten richtig erfasst werden können.

Wenn die Sender-App gestartet oder mit deiner Android TV-App verbunden wird, sollte sie die Anmeldedaten für die Person angeben, die an der Sitzung teilnimmt.

Bevor ein Sender deine Android TV-App startet und verbindet, kannst du eine Startprüfung angeben, um zu sehen, ob die Anmeldedaten des Senders zulässig sind. Andernfalls startet das Cast Connect SDK deinen Webempfänger.

Anmeldedaten für den App-Start des Absenders

Auf der Absenderseite können Sie die CredentialsData angeben, um anzugeben, wer an der Sitzung teilnimmt.

credentials ist ein String, der vom Nutzer definiert werden kann, solange er von deiner ATV-App verstanden wird. Mit credentialsType wird definiert, von welcher Plattform CredentialsData stammt. Es kann sich auch um einen benutzerdefinierten Wert handeln. Standardmäßig ist dies die Plattform, von der aus die Daten gesendet werden.

Die CredentialsData wird nur beim Starten oder Beitreten an deine Android TV-App übergeben. Wenn du es während einer Verbindung noch einmal festlegst, wird es nicht an deine Android TV App übergeben. Wenn der Sender das Profil während einer Verbindung wechselt, kannst du entweder in der Sitzung bleiben oder SessionManager.endCurrentCastSession(boolean stopCasting) drücken, wenn du der Meinung bist, dass das neue Profil nicht mit der Sitzung kompatibel ist.

Die CredentialsData für jeden Absender kann mit getSenders auf der CastReceiverContext abgerufen werden, um die SenderInfo, mit getCastLaunchRequest(), um die CastLaunchRequest und dann mit getCredentialsData() zu erhalten.

Android

Erfordert play-services-cast-framework Version 19.0.0 oder höher.

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

Erfordert google-cast-sdk Version v4.8.3 oder höher.

Kann jederzeit nach der Einstellung der Optionen aufgerufen werden: GCKCastContext.setSharedInstanceWith(options).

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

Erfordert die Chromium-Browserversion M87 oder höher.

Kann jederzeit nach der Einstellung der Optionen aufgerufen werden: cast.framework.CastContext.getInstance().setOptions(options);.

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

Implementierung einer Überprüfung von ATV-Startanfragen

Die CredentialsData wird an deine Android TV App übergeben, wenn ein Sender versucht, eine Übertragung zu starten oder daran teilzunehmen. Sie können einen LaunchRequestChecker implementieren. , um diese Anfrage zuzulassen oder abzulehnen.

Wenn eine Anfrage abgelehnt wird, wird der Webreceiver geladen, anstatt die ATV-App nativ gestartet zu werden. Du solltest eine Anfrage ablehnen, wenn dein ATV die Anfrage des Nutzers zum Starten oder Beitreten nicht verarbeiten kann. Mögliche Ursachen sind beispielsweise, dass ein anderer Nutzer als der angeforderte in der ATV App angemeldet ist und deine App das Wechseln der Anmeldedaten nicht verarbeiten kann oder dass derzeit kein Nutzer in der ATV App angemeldet ist.

Wenn eine Anfrage zulässig ist, wird die ATV-App gestartet. Du kannst dieses Verhalten anpassen, je nachdem, ob deine App das Senden von Ladeanfragen unterstützt, wenn ein Nutzer nicht in der ATV App angemeldet ist oder es eine Nutzerabweichung gibt. Dieses Verhalten kann in der LaunchRequestChecker vollständig angepasst werden.

Erstellen Sie eine Klasse, die die CastReceiverOptions.LaunchRequestChecker-Schnittstelle implementiert:

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

Legen Sie sie dann in Ihrer ReceiverOptionsProvider fest:

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

Wenn du true in LaunchRequestChecker auflöst, wird die ATV-App gestartet und false startet die Web-Receiver-App.

Benutzerdefinierte Nachrichten senden und empfangen

Mit dem Cast-Protokoll können Sie benutzerdefinierte Stringnachrichten zwischen Absendern und Ihrer Empfängeranwendung senden. Sie müssen einen Namespace (Kanal) registrieren, um Nachrichten zu senden, bevor Sie Ihre CastReceiverContext initialisieren.

Android TV – Benutzerdefinierten Namespace angeben

Sie müssen die unterstützten Namespaces während der Einrichtung in CastReceiverOptions angeben:

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 – Nachrichten senden

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 – Nachrichten mit benutzerdefiniertem Namensraum empfangen

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