Android TV-Receiver mit den wichtigsten Funktionen erweitern

Diese Seite enthält Code-Snippets und Beschreibungen der Funktionen, die zum Anpassen einer Android TV Receiver App verfügbar sind.

Bibliotheken konfigurieren

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

Android
  1. Öffnen Sie die Datei build.gradle im Verzeichnis Ihres Anwendungsmoduls.
  2. google() muss in der repositories enthalten sein.
      repositories {
        google()
      }
  3. Fügen Sie je nach Zielgerätetyp für Ihre Anwendung den Abhängigkeiten die neuesten Versionen der Bibliotheken hinzu:
    • Für die Android Receiver App:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast-tv:21.0.0'
          implementation 'com.google.android.gms:play-services-cast:21.3.0'
        }
    • Für die Android Sender App:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast:21.0.0'
          implementation 'com.google.android.gms:play-services-cast-framework:21.3.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. Podfile muss auf google-cast-sdk 4.7.0 oder höher ausgerichtet sein
  2. Ausrichtung auf iOS 12 oder höher. Weitere Informationen finden Sie in den Versionshinweisen.
      platform: ios, '12'
    
      def target_pods
         pod 'google-cast-sdk', '~>4.7.0'
      end
Web
  1. Erfordert Chromium-Browser Version M87 oder höher.
  2. Web Sender API-Bibliothek Ihrem Projekt hinzufügen
      <script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

AndroidX-Anforderung

Bei neuen Versionen der Google Play-Dienste muss eine App aktualisiert werden, damit der Namespace androidx verwendet werden kann. Folgen Sie der Anleitung für die Migration zu AndroidX.

Android TV App – Voraussetzungen

Damit Cast Connect in Ihrer Android TV App unterstützt wird, müssen Sie Ereignisse aus einer Mediensitzung erstellen und unterstützen. Die von Ihrer Mediensitzung bereitgestellten Daten enthalten die grundlegenden Informationen für Ihren Medienstatus, zum Beispiel Position, Wiedergabestatus usw. Ihre Mediensitzung wird auch von der Cast Connect-Bibliothek verwendet, um zu signalisieren, wenn sie bestimmte Nachrichten von einem Absender erhalten hat, z. B. Pause.

Weitere Informationen zu Mediensitzungen und zum Initialisieren einer Mediensitzung finden Sie unter Arbeit mit einer Mediensitzung.

Lebenszyklus von Mediensitzungen

Ihre App sollte zu Beginn der Wiedergabe eine Mediensitzung erstellen und freigeben, wenn sie nicht mehr gesteuert werden kann. Wenn Ihre App beispielsweise eine Video-App ist, sollten Sie die Sitzung freigeben, wenn der Nutzer die Wiedergabeaktivität beendet – entweder durch Auswahl von „Zurück“ für die Suche nach anderen Inhalten oder durch Hintergrundwiedergabe. Wenn Ihre App eine Musik-App ist, sollten Sie sie veröffentlichen, wenn Ihre App keine Medien mehr abspielt.

Sitzungsstatus wird aktualisiert

Die Daten in Ihrer Mediensitzung sollten den aktuellen Status Ihres Players widerspiegeln. Wenn die Wiedergabe beispielsweise pausiert ist, sollten Sie den Wiedergabestatus und 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_UNTERTITEL Der Untertitel
METADATA_KEY_DISPLAY_ICON_URI Symbol-URL
METADATA_KEY_DURATION (erforderlich) Mediendauer.
METADATA_KEY_MEDIA_URI Content ID
METADATA_KEY_ARTIST Der Künstler
METADATA_KEY_ALBUM Das Album

Wiedergabestatus-Compat

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

MediaSessionCompat (in englischer Sprache)

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

In Ihrer App sollte ein Callback für die Steuerung der Mediensitzungsübertragung implementiert sein. In der folgenden Tabelle sehen Sie, welche Transportkontrollaktionen verarbeitet werden müssen:

MediaSessionCompat.Callback

Aktionen Beschreibung
onPlay() Fortsetzen
onPause() Pause
onSeekTo() Zu Position springen
OnStop() Aktuelle Medienwiedergabe beenden
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());

Streaming-Unterstützung konfigurieren

Wenn eine Startanfrage von einer Absenderanwendung gesendet wird, wird ein Intent mit einem Anwendungs-Namespace erstellt. Ihre Anwendung ist für den Umgang mit dem Objekt und das Erstellen einer Instanz des Objekts CastReceiverContext verantwortlich, wenn die TV-App gestartet wird. Das CastReceiverContext-Objekt ist erforderlich, um mit Cast zu interagieren, während die TV-App ausgeführt wird. Mit diesem Objekt kann Ihre TV-Anwendung Cast-Mediennachrichten von allen verbundenen Absendern akzeptieren.

Einrichtung von Android TV

Filter für Launch-Intent hinzufügen

Fügen Sie der Aktivität, mit der der Start-Intent von der Absender-App verarbeitet werden soll, 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>

Anbieteroptionen für Empfänger 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 den Optionsanbieter in AndroidManifest an:

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

Mit ReceiverOptionsProvider wird das CastReceiverOptions angegeben, wenn CastReceiverContext initialisiert wird.

Streamingempfängerkontext

Initialisieren Sie den CastReceiverContext, wenn die Anwendung erstellt wird:

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

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

  ...
}

CastReceiverContext starten, wenn die App in den Vordergrund verschoben wird:

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

Rufen Sie stop() in der CastReceiverContext auf, nachdem die App in den Hintergrund für Video-Apps oder Apps gestartet wurde, die die Hintergrundwiedergabe nicht unterstützen:

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

Wenn Ihre App die Wiedergabe im Hintergrund unterstützt, können Sie außerdem stop() für CastReceiverContext aufrufen, wenn die Wiedergabe im Hintergrund beendet wird.

Wir empfehlen dringend, den LifecycleObserver aus der androidx.lifecycle-Bibliothek zum Verwalten von Aufrufen von CastReceiverContext.start() und CastReceiverContext.stop() zu verwenden, insbesondere wenn Ihre native App mehrere Aktivitäten hat. So vermeiden Sie Race-Bedingungen, wenn Sie start() und stop() aus verschiedenen Aktivitäten aufrufen.

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 Sie eine MediaSession erstellen, müssen Sie auch das aktuelle MediaSession-Token an CastReceiverContext angeben, damit die Anwendung erkennt, 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 Sie Ihr MediaSession wegen inaktiver Wiedergabe freigeben, sollten Sie für MediaManager ein Null-Token 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 die App im Hintergrund ausgeführt wird, sollten Sie nur dann auf CastReceiverContext.stop() zugreifen, wenn die App im Hintergrund ausgeführt wird, und diese nur aufrufen, wenn die App im Hintergrund ausgeführt wird und keine Medien mehr abgespielt wird. 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 Sie Exoplayer verwenden, können Sie die MediaSessionConnector verwenden, um die Sitzung und alle zugehörigen Informationen automatisch zu verwalten, einschließlich des Wiedergabestatus, anstatt die Änderungen manuell zu erfassen.

MediaSessionConnector.MediaButtonEventHandler kann verwendet werden, um MediaButton-Ereignisse durch Aufrufen von setMediaButtonEventHandler(MediaButtonEventHandler) zu verarbeiten, die ansonsten standardmäßig von MediaSessionCompat.Callback verarbeitet werden.

Wenn Sie MediaSessionConnector in Ihre App einbinden möchten, fügen Sie der Klasse der Spieleraktivität oder überall dort, wo Sie Ihre Mediensitzung verwalten, 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

Cast Connect-Unterstützung aktivieren

Nachdem Sie die Absender-App mit Cast Connect-Unterstützung aktualisiert haben, können Sie ihre Bereitschaft deklarieren, indem Sie das Flag androidReceiverCompatible auf LaunchOptions auf „true“ setzen.

Android

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

Das Flag androidReceiverCompatible wird in LaunchOptions festgelegt (das ist Teil von CastOptions):

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 wird in GCKLaunchOptions festgelegt (das ist Teil von GCKCastOptions):

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

Android TV App konfigurieren

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

Entwicklergeräte registrieren

Registriere die Seriennummer des Android TV-Geräts, das du für die Entwicklung in der Cast-Entwicklerkonsole verwenden möchtest.

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

Weitere Informationen zur Registrierung eines Cast- oder Android TV-Geräts für die Cast-Entwicklung finden Sie auf der Registrierungsseite.

Medien werden geladen

Wenn du in deiner Android TV App bereits Deeplink-Unterstützung unterstützt hast, solltest du in deinem Android TV-Manifest eine ähnliche Definition konfiguriert haben:

<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 beim Absender laden

Bei den Absendern können Sie den Deeplink übergeben, indem Sie entity in den Medieninformationen für die Ladeanfrage festlegen:

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 „load“ wird über einen Intent mit Ihrem Deeplink und dem Paketnamen gesendet, den Sie in der Entwicklerkonsole festgelegt haben.

ATV-Anmeldedaten für Absender festlegen

Es ist möglich, dass deine Web Receiver App und die Android TV App unterschiedliche Deeplinks und credentials unterstützen, z. B. wenn die Authentifizierung auf den beiden Plattformen unterschiedlich verarbeitet wird. Um das zu erreichen, kannst du 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 gestartet ist, überschreibt das SDK jedoch entity und credentials mit deiner atvEntity und deiner atvCredentials (sofern angegeben).

Anhand von Content ID oder MediaQueueData laden

Wenn du weder entity noch atvEntity verwendest und in deinen Medieninformationen Content ID oder Content-URLs verwendest oder detailliertere Daten zu Medienladeanfragen verwendest, musst du der 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>

Ähnlich wie Load nach Entität können Sie auf Absenderseite eine Ladeanfrage mit Ihren 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);

Lastanfragen verarbeiten

Zur Verarbeitung dieser Ladeanfragen müssen Sie die Intents in den Callbacks Ihres Aktivitätslebenszyklus 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 Load-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. Es wird empfohlen, für eine Aktivitäts- oder Anwendungs-onCreate()methode 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);
}

Zur Verarbeitung des Load-Intents können Sie den Intent in die von uns definierten Datenstrukturen parsen (MediaLoadRequestData für Ladeanfragen).

Unterstützung für Medienbefehle

Grundlegende Unterstützung für die Wiedergabesteuerung

Grundlegende Integrationsbefehle enthalten die Befehle, die mit Mediensitzungen kompatibel sind. Diese Befehle werden über Callbacks für Mediensitzungen benachrichtigt. Dazu müssen Sie einen Callback für die Mediensitzung registrieren.

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ützung von Cast-Steuerbefehlen

Es gibt einige Cast-Befehle, die in MediaSession nicht verfügbar sind, z. B. skipAd() oder setActiveMediaTracks(). Außerdem müssen hier einige Warteschlangenbefehle 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 {
        // 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 festlegen

Genau wie bei Ihrem Streamingempfänger sollte Ihre Android TV App angeben, welche Befehle unterstützt werden, damit Absender bestimmte UI-Steuerelemente aktivieren oder deaktivieren können. Für Befehle, die Teil von MediaSession sind, geben Sie die Befehle 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 Ihre Android TV App nur die einfache Mediensteuerung unterstützt, die Web Receiver App aber eine erweiterte Kontrolle unterstützt, sollten Sie dafür sorgen, dass die App des Absenders beim Streamen an die Android TV App korrekt funktioniert. Wenn die Android TV App beispielsweise keine Änderung der Wiedergabegeschwindigkeit unterstützt, während die Web Receiver App dies unterstützt, sollten Sie die unterstützten Aktionen auf jeder Plattform richtig festlegen und dafür sorgen, dass die Benutzeroberfläche des Senders korrekt gerendert wird.

MediaStatus ändern

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

Wir bieten die Klasse MediaStatusModifier, mit der Sie dies erreichen. MediaStatusModifier wird immer im MediaSession ausgeführt, den Sie in CastReceiverContext festgelegt haben.

So erstellen und übertragen Sie MediaStatus:

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 mit einem MediaStatus-Modifikator überschreiben.

Für einige Zustände und Metadaten können sowohl in MediaSession als auch in MediaStatusModifier festgelegt werden. Wir empfehlen dringend, sie nur in MediaSession festzulegen. Sie können den Modifikator weiterhin verwenden, um die Status in MediaSession zu überschreiben. Das wird nicht empfohlen, weil der Status im Modifikator immer eine höhere Priorität hat als die Werte, die von MediaSession bereitgestellt werden.

Vor dem Senden wird „MediaStatus“ abgefangen

Ähnlich wie mit dem Web Receiver SDK gilt: Wenn Sie vor dem Senden einige Änderungen vornehmen möchten, können Sie einen MediaStatusInterceptor angeben, um den zu sendenden MediaStatus zu verarbeiten. Wir übergeben eine MediaStatusWriter, um die MediaStatus zu bearbeiten, bevor sie gesendet wird.

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

Ihre Android TV App lässt möglicherweise nur bestimmte Nutzer zu, um die App-Sitzung zu starten oder daran teilzunehmen. So erlauben Sie beispielsweise dem Absender die Teilnahme am Programm nur in folgenden Fällen:

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

Wenn Ihre App mehrere oder anonyme Nutzer verarbeiten kann, können Sie zulassen, dass weitere Nutzer an der ATV-Sitzung teilnehmen können. Wenn der Nutzer Anmeldedaten zur Verfügung stellt, muss diese von deiner ATV-App verarbeitet werden, damit ihr Fortschritt und andere Nutzerdaten korrekt erfasst werden.

Wenn die Absender-App deine Android TV-App startet oder beitritt, sollte die Absender-App die Anmeldedaten angeben, die angeben, wer an der Sitzung teilnimmt.

Bevor ein Absender startet und deiner Android TV App beitritt, kannst du eine Startprüfung festlegen, um zu prüfen, ob die Anmeldedaten des Absenders zulässig sind. Ist dies nicht der Fall, wird mit dem Cast Connect SDK der Webempfänger gestartet.

App-Startdaten des Absenders

Auf Absenderseite können Sie den CredentialsData angeben, der angibt, wer der Sitzung beitritt.

credentials ist ein String, der vom Nutzer definiert werden kann, solange er von deiner ATV-App verstanden wird. credentialsType definiert, von welcher Plattform die CredentialsData stammt oder ein benutzerdefinierter Wert sein kann. Standardmäßig ist sie auf die Plattform eingestellt, von der sie gesendet wird.

Die CredentialsData wird nur während der Einführung oder bei der Registrierung an deine Android TV App übergeben. Wenn Sie das Profil noch einmal einrichten, während Sie verbunden sind, wird es nicht an Ihre Android TV App übergeben. Wenn der Absender das Profil wechselt, während Sie verbunden sind, können Sie entweder in der Sitzung bleiben oder SessionManager.endCurrentCastSession(boolean stopCasting) aufrufen, wenn Sie der Meinung sind, dass das neue Profil mit der Sitzung nicht kompatibel ist.

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

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.7.0 oder höher.

Kann jederzeit aufgerufen werden, nachdem die Optionen festgelegt wurden: GCKCastContext.setSharedInstanceWith(options).

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

Erfordert die Chromium-Browserversion M87 oder höher.

Kann jederzeit aufgerufen werden, nachdem die Optionen festgelegt wurden: cast.framework.CastContext.getInstance().setOptions(options);.

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

Anfrageprüfung für ATV-Startanfrage implementieren

Die CredentialsData wird an deine Android TV App übergeben, wenn ein Absender versucht, die App zu starten oder beizutreten. Sie können eine LaunchRequestChecker implementieren. zum Zulassen oder Ablehnen der Anfrage.

Wenn eine Anfrage abgelehnt wird, wird der Webempfänger geladen, anstatt nativ in die ATV-App zu starten. Sie sollten eine Anfrage ablehnen, wenn Ihr ATV nicht in der Lage ist, den Nutzer zu verarbeiten, der die Aktivierung oder Aufnahme anfordert. Das kann beispielsweise der Fall sein, wenn ein anderer Nutzer bei der ATV-App angemeldet ist als die angeforderte Anfrage und Ihre App nicht mit dem Wechsel von Anmeldedaten umgehen kann oder dass aktuell kein Nutzer in der ATV-App angemeldet ist.

Wenn eine Anfrage zulässig ist, wird die ATV-App gestartet. Sie können dieses Verhalten anpassen, je nachdem, ob Ihre App das Senden von Lastanfragen unterstützt, wenn ein Nutzer nicht in der ATV-App angemeldet ist, oder wenn es eine Nutzerabweichung gibt. Dieses Verhalten kann in LaunchRequestChecker vollständig konfiguriert werden.

Erstellen Sie eine Klasse, mit der die Schnittstelle CastReceiverOptions.LaunchRequestChecker implementiert wird:

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 der 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 Sie true in der LaunchRequestChecker auflösen, wird die ATV-App und false die Web Receiver App gestartet.

Benutzerdefinierte Nachrichten senden und empfangen

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

Android TV: benutzerdefinierten Namespace angeben

Sie müssen die unterstützten Namespaces bei der Einrichtung in der 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 zum benutzerdefinierten Namespace erhalten

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