Android TV レシーバーに主要な機能を追加する

このページには、コード スニペットと利用可能な機能の説明が掲載されています。 Android TV Receiver アプリをカスタマイズします。

ライブラリの構成

Android TV アプリで Cast Connect API を利用できるようにするには:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Android
  1. アプリ モジュール ディレクトリ内の build.gradle ファイルを開きます。
  2. リストされた repositoriesgoogle() が含まれていることを確認します。
      repositories {
        google()
      }
  3. アプリの対象デバイスタイプに応じて、最新バージョンを追加してください 依存関係に追加します。 <ph type="x-smartling-placeholder">
      </ph>
    • Android Receiver アプリの場合:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast-tv:21.1.0'
          implementation 'com.google.android.gms:play-services-cast:21.5.0'
        }
    • Android の送信者アプリの場合:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast:21.1.0'
          implementation 'com.google.android.gms:play-services-cast-framework:21.5.0'
        }
    で確認できます。 サービスを更新するたびに、このバージョン番号を更新してください。
  4. 変更を保存して [Sync Project with Gradle Files] をクリックします。 をクリックします。
で確認できます。
<ph type="x-smartling-placeholder">
</ph>
iOS
  1. Podfilegoogle-cast-sdk 4.8.1 をターゲットにしていることを確認してください 以上
  2. iOS 14 以降がターゲットであること。リリースノートをご覧ください。 をご覧ください。
      platform: ios, '14'
    
      def target_pods
         pod 'google-cast-sdk', '~>4.8.1'
      end
で確認できます。
<ph type="x-smartling-placeholder">
</ph>
ウェブ
  1. Chromium ブラウザ バージョン M87 以降が必要です。
  2. Web Sender API ライブラリをプロジェクトに追加する
      <script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

AndroidX の要件

新しいバージョンの Google Play 開発者サービスを使用するには、アプリを更新する必要があります androidx Namespace。手順については、 AndroidX への移行をご覧ください。

Android TV アプリ - 前提条件

Android TV アプリで Cast Connect をサポートするには、 イベントをサポートしています。メディア セッションによって提供されるデータ 再生状態などの基本情報を 確認できます。メディア セッションは Cast Connect ライブラリによっても使用されます を使用して、送信者から特定のメッセージ(一時停止など)を受け取ったことを通知します。

メディア セッションとメディア セッションを初期化する方法について詳しくは、 詳しくは、 メディア セッション ガイドをご覧ください。

メディア セッションのライフサイクル

再生の開始時にアプリでメディア セッションを作成し、再生が開始されたらメディア セッションを解放する必要があります。 制御できなくなります。たとえば、アプリが動画アプリの場合、 は、ユーザーが再生アクティビティを終了したときにセッションを解放する必要があります。 [戻る] を選択して他のコンテンツをブラウジングしたり、アプリをバックグラウンドで実行したりできます。お使いの アプリが音楽アプリの場合は、アプリで再生されなくなったらリリースする必要があります。 できます。

セッションのステータスを更新しています

メディア セッションのデータは、 表示されます。たとえば、再生が一時停止している場合は、再生を更新して サポートされているアクションを定義します。次の表に、 常に最新の状態に保つ責任はお客様にあります。

MediaMetadataCompat

メタデータ フィールド 説明
METADATA_KEY_TITLE (必須) メディアのタイトル。
METADATA_KEY_DISPLAY_SUBTITLE サブタイトル。
METADATA_KEY_DISPLAY_ICON_URI アイコンの URL。
METADATA_KEY_DURATION (必須) メディアの時間。
METADATA_KEY_MEDIA_URI Content ID。
METADATA_KEY_ARTIST アーティスト。
METADATA_KEY_ALBUM アルバム。

PlaybackStateCompat

必須のメソッド 説明
setActions() サポートされているメディア コマンドを設定します。
setState() 再生状態と現在の位置を設定します。

MediaSessionCompat

必須のメソッド 説明
setRepeatMode() リピートモードを設定します。
setShuffleMode() シャッフル モードを設定します。
setMetadata() メディアのメタデータを設定します。
setPlaybackState() 再生状態を設定します。
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);
}

トランスポート コントロールの処理

アプリにメディア セッション トランスポート コントロール コールバックを実装する必要があります。「 次の表に、処理する必要があるトランスポート コントロールのアクションを示します。

MediaSessionCompat.Callback

操作 説明
onPlay() 再開
onPause() 一時停止
onSeekTo() 特定の位置に移動
onStop() 現在のメディアを停止する
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
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());

キャスト サポートの設定

送信側アプリからリリース リクエストが送信されると、インテントが作成される 関連付けられていますアプリケーションの処理で 新しい Pod を作成する CastReceiverContext オブジェクトを宣言します。CastReceiverContext オブジェクトは必須です を使用して、TV アプリの実行中に Cast を操作できます。このオブジェクトを使用すると、テレビの アプリで、接続されているすべての送信者からのキャスト メディア メッセージを受け付けることができます。

Android TV のセットアップ

起動インテント フィルタの追加

起動を処理するアクティビティに新しいインテント フィルタを追加する インテントを受信できます。

<activity android:name="com.example.activity">
  <intent-filter>
      <action android:name="com.google.android.gms.cast.tv.action.LAUNCH" />
      <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

レシーバ オプション プロバイダを指定する

新しい P-MAX キャンペーンを ReceiverOptionsProvider 提供する CastReceiverOptions:

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

次に、AndroidManifest でオプション プロバイダを指定します。

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

ReceiverOptionsProvider は、次の場合に CastReceiverOptions を指定するために使用されます。 CastReceiverContext が初期化されています。

キャスト レシーバーのコンテキスト

初期化 CastReceiverContext 作成すると次のような処理が行われます。

Kotlin
で確認できます。
override fun onCreate() {
  CastReceiverContext.initInstance(this)

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

  ...
}

アプリがフォアグラウンドに移行したら、CastReceiverContext を開始します。

Kotlin
で確認できます。
CastReceiverContext.getInstance().start()
Java
CastReceiverContext.getInstance().start();

発信 stop() 日付 CastReceiverContext 動画アプリやサポート対象外のアプリでバックグラウンドに移行した後 バックグラウンド再生:

Kotlin
で確認できます。
// Player has stopped.
CastReceiverContext.getInstance().stop()
Java
// Player has stopped.
CastReceiverContext.getInstance().stop();

また、アプリがバックグラウンドでの再生をサポートしている場合は、stop() を呼び出します。 CastReceiverContext に出力されます。

次のように LifecycleObserver を androidx.lifecycle 通話を管理するライブラリ CastReceiverContext.start() および CastReceiverContext.stop()、 特にネイティブアプリに 複数のアクティビティがある場合はなおさらですこれにより 異なるアクティビティから start()stop() を呼び出す場合の条件。

Kotlin
で確認できます。
// Create a LifecycleObserver class.
class MyLifecycleObserver : DefaultLifecycleObserver {
  override fun onStart(owner: LifecycleOwner) {
    // App prepares to enter foreground.
    CastReceiverContext.getInstance().start()
  }

  override fun onStop(owner: LifecycleOwner) {
    // App has moved to the background or has terminated.
    CastReceiverContext.getInstance().stop()
  }
}

// Add the observer when your application is being created.
class MyApplication : Application() {
  fun onCreate() {
    super.onCreate()

    // Initialize CastReceiverContext.
    CastReceiverContext.initInstance(this /* android.content.Context */)

    // Register LifecycleObserver
    ProcessLifecycleOwner.get().lifecycle.addObserver(
        MyLifecycleObserver())
  }
}
Java
// Create a LifecycleObserver class.
public class MyLifecycleObserver implements DefaultLifecycleObserver {
  @Override
  public void onStart(LifecycleOwner owner) {
    // App prepares to enter foreground.
    CastReceiverContext.getInstance().start();
  }

  @Override
  public void onStop(LifecycleOwner owner) {
    // App has moved to the background or has terminated.
    CastReceiverContext.getInstance().stop();
  }
}

// Add the observer when your application is being created.
public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();

    // Initialize CastReceiverContext.
    CastReceiverContext.initInstance(this /* android.content.Context */);

    // Register LifecycleObserver
    ProcessLifecycleOwner.get().getLifecycle().addObserver(
        new MyLifecycleObserver());
  }
}
// In AndroidManifest.xml set MyApplication as the application class
<application
    ...
    android:name=".MyApplication">

MediaSession を MediaManager に接続する

新しい MediaSession 現在の MediaSession トークンを CastReceiverContext これにより、コマンドの送信先とメディアの再生状態の取得先がわかります。

Kotlin
で確認できます。
val mediaManager: MediaManager = receiverContext.getMediaManager()
mediaManager.setSessionCompatToken(currentMediaSession.getSessionToken())
Java
MediaManager mediaManager = receiverContext.getMediaManager();
mediaManager.setSessionCompatToken(currentMediaSession.getSessionToken());

非アクティブな再生が原因で MediaSession を解放する場合は、 null トークンがオン MediaManager:

Kotlin
で確認できます。
myPlayer.stop()
mediaSession.release()
mediaManager.setSessionCompatToken(null)
Java
myPlayer.stop();
mediaSession.release();
mediaManager.setSessionCompatToken(null);

アプリがバックグラウンドで実行されているときのメディア再生をサポートしている場合は、 通話 CastReceiverContext.stop() バックグラウンドに移動されるときは、必ず バックグラウンドにあり、メディアを再生しなくなっています。例:

Kotlin
で確認できます。
class MyLifecycleObserver : DefaultLifecycleObserver {
  ...
  // App has moved to the background.
  override fun onPause(owner: LifecycleOwner) {
    mIsBackground = true
    myStopCastReceiverContextIfNeeded()
  }
}

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

  myStopCastReceiverContextIfNeeded()
}

// Stop the CastReceiverContext when both the player has
// stopped and the app has moved to the background.
private fun myStopCastReceiverContextIfNeeded() {
  if (mIsBackground && myPlayer.isStopped()) {
    CastReceiverContext.getInstance().stop()
  }
}
Java
public class MyLifecycleObserver implements DefaultLifecycleObserver {
  ...
  // App has moved to the background.
  @Override
  public void onPause(LifecycleOwner owner) {
    mIsBackground = true;

    myStopCastReceiverContextIfNeeded();
  }
}

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

  myStopCastReceiverContextIfNeeded();
}

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

Cast Connect で Exoplayer を使用する

以下を使用している場合: Exoplayer を使用している場合は、 MediaSessionConnector セッションと、関連するすべての情報(セッション、 再生状態を手動でトラッキングする代わりに、

MediaSessionConnector.MediaButtonEventHandler これを使用して MediaButton イベントを処理するために、 setMediaButtonEventHandler(MediaButtonEventHandler) それ以外の処理は MediaSessionCompat.Callback できます。

統合するには MediaSessionConnector で、プレーヤーのアクティビティ クラスまたは メディア セッションの管理:

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

送信側アプリの設定

Cast Connect のサポートを有効にする

Cast Connect のサポートを有効にして送信側アプリを更新したら、 その準備状況を示すために androidReceiverCompatible フラグがオン LaunchOptions true に設定します。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Android

play-services-cast-framework のバージョンが必要 19.0.0 以上。

androidReceiverCompatible フラグが設定されていると、 LaunchOptionsCastOptions の一部):

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
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();
  }
}
<ph type="x-smartling-placeholder">
</ph>
iOS

google-cast-sdk バージョン v4.4.8 または 高くなります。

androidReceiverCompatible フラグが設定されていると、 GCKLaunchOptionsGCKCastOptions):

let options = GCKCastOptions(discoveryCriteria: GCKDiscoveryCriteria(applicationID: kReceiverAppID))
...
let launchOptions = GCKLaunchOptions()
launchOptions.androidReceiverCompatible = true
options.launchOptions = launchOptions
GCKCastContext.setSharedInstanceWith(options)
<ph type="x-smartling-placeholder">
</ph>
ウェブ

Chromium ブラウザのバージョンが必要です M87 以降。

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

Cast Developer Console のセットアップ

Android TV アプリを設定する

Android TV アプリのパッケージ名を Cast デベロッパー コンソール キャストアプリ ID と関連付けます。

デベロッパー デバイスを登録する

使用する Android TV デバイスのシリアル番号を登録する 開発環境では、 Cast デベロッパー コンソール

登録しない場合、Cast Connect は セキュリティ上の理由により Google Play ストアにアクセスすることはできません。

Cast デバイスまたは Android TV デバイスを Cast に登録する方法の詳細 登録ページをご覧ください。

メディアの読み込み

Android TV アプリにディープリンクのサポートをすでに実装している場合は、次の手順を実施します。 Android TV マニフェストに同様の定義が設定されているはずです。

<activity android:name="com.example.activity">
  <intent-filter>
     <action android:name="android.intent.action.VIEW" />
     <category android:name="android.intent.category.DEFAULT" />
     <data android:scheme="https"/>
     <data android:host="www.example.com"/>
     <data android:pathPattern=".*"/>
  </intent-filter>
</activity>

送信者のエンティティ別に読み込む

送信者では、メディアに entity を設定することでディープリンクを渡すことができます。 次の読み込みリクエストに関する情報を提供します。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
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
で確認できます。 <ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
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);
<ph type="x-smartling-placeholder">
</ph>
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)
ウェブ

Chromium ブラウザのバージョンが必要です M87 以降。

let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4');
mediaInfo.entity = 'https://example.com/watch/some-id';
...

let request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
...

cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);

読み込みコマンドは、ディープリンクとパッケージ名を含むインテントを介して送信されます。 定義した値を使用します。

送信者に ATV 認証情報を設定する

Web Receiver アプリと Android TV アプリは、 ディープリンクと credentials(認証を処理する場合など) 違います)。これに対処するために、VM の Android TV の場合: entitycredentials:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Android
で確認できます。 <ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
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);
<ph type="x-smartling-placeholder">
</ph>
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)
ウェブ

Chromium ブラウザのバージョンが必要です M87 以降。

let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4');
mediaInfo.entity = 'https://example.com/watch/some-id';
mediaInfo.atvEntity = 'myscheme://example.com/atv/some-id';
...

let request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
request.atvCredentials = 'atv-user-credentials';
...

cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);

Web Receiver アプリが起動されると、アプリは entitycredentials を使用します。 呼び出すことができます。ただし、Android TV アプリが起動されると、SDK は entitycredentialsatvEntityatvCredentials に置き換えます (指定された場合)。

Content ID または MediaQueueData による読み込み

entity または atvEntity を使用しておらず、Content ID または メディア情報にコンテンツの URL を指定するか、より詳細なメディア読み込みを使用します。 [Request Data] で、次の定義済みのインテント フィルタを Android TV アプリ:

<activity android:name="com.example.activity">
  <intent-filter>
     <action android:name="com.google.android.gms.cast.tv.action.LOAD"/>
     <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

送信者側では、エンティティごとの読み込みと同様に、次の操作を行います。 コンテンツ情報を使用して読み込みリクエストを作成し、load() を呼び出すことができます。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Android
で確認できます。 <ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
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);
<ph type="x-smartling-placeholder">
</ph>
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)
ウェブ

Chromium ブラウザのバージョンが必要です M87 以降。

let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4');
...

let request = new chrome.cast.media.LoadRequest(mediaInfo);
...

cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);

読み込みリクエストの処理

アクティビティでは、これらの読み込みリクエストを処理するために、 次のように指定します。

Kotlin
で確認できます。
class MyActivity : Activity() {
  override fun onStart() {
    super.onStart()
    val mediaManager = CastReceiverContext.getInstance().getMediaManager()
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(intent)) {
        // If the SDK recognizes the intent, you should early return.
        return
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }

  // For some cases, a new load intent triggers onNewIntent() instead of
  // onStart().
  override fun onNewIntent(intent: Intent) {
    val mediaManager = CastReceiverContext.getInstance().getMediaManager()
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(intent)) {
        // If the SDK recognizes the intent, you should early return.
        return
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }
}
Java
public class MyActivity extends Activity {
  @Override
  protected void onStart() {
    super.onStart();
    MediaManager mediaManager =
        CastReceiverContext.getInstance().getMediaManager();
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(getIntent())) {
      // If the SDK recognizes the intent, you should early return.
      return;
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }

  // For some cases, a new load intent triggers onNewIntent() instead of
  // onStart().
  @Override
  protected void onNewIntent(Intent intent) {
    MediaManager mediaManager =
        CastReceiverContext.getInstance().getMediaManager();
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(intent)) {
      // If the SDK recognizes the intent, you should early return.
      return;
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }
}

MediaManager の場合 読み込みインテントであることが検出されると、 MediaLoadRequestData インテントからオブジェクトを取得し、 MediaLoadCommandCallback.onLoad()。 読み込みリクエストを処理するには、このメソッドをオーバーライドする必要があります。このコールバックは 次の日付より前に登録 MediaManager.onNewIntent() が呼び出される(Activity または App onCreate() で実行されることが推奨されます) メソッドをご覧ください)。

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

読み込みインテントを処理するために、インテントを解析してデータ構造に変換します。 定義 (MediaLoadRequestData 使用されます。

メディア コマンドのサポート

基本的な再生コントロールのサポート

メディアと互換性のあるコマンドを含む基本的な統合コマンド あります。これらのコマンドは、メディア セッション コールバックを介して通知されます。必要なこと メディア セッションへのコールバックを登録してこれをサポートします( です)。

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

キャスト コントロール コマンドのサポート

一部のキャスト コマンドは、 MediaSession skipAd() または setActiveMediaTracks()。 また、いくつかのキューコマンドをここに実装する必要があります。これは、Cast キューが MediaSession キューと完全な互換性がありません。

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

サポートされているメディア コマンドを指定する

キャスト レシーバーと同様に、Android TV アプリでどのコマンドを サポートされているため、送信者は特定の UI コントロールを有効または無効にできます。対象 コマンドを MediaSession コマンドを PlaybackStateCompat。 その他のコマンドは、 MediaStatusModifier

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

サポートされていないボタンを非表示にする

Android TV アプリが基本的なメディア コントロールしかサポートしていないにもかかわらず、ウェブ レシーバーが より高度な制御をサポートしているため、送信側のアプリが Android TV アプリにキャストする際に正しく機能する。たとえば、Android TV が ウェブ レシーバー アプリでは再生速度の変更がサポートされていませんが、 各プラットフォームでサポートされているアクションを正しく設定し、 UI が適切にレンダリングされます。

MediaStatus の変更

トラック、広告、ライブ、キューなどの高度な機能をサポートするために、Android TV アプリは、以下では確認できない追加情報を提供する必要があります。 MediaSession

Google は、 MediaStatusModifier クラスをご覧ください。MediaStatusModifier は常に 設定したMediaSession CastReceiverContext

作成してブロードキャストする 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();

クライアント ライブラリは MediaSession からベース MediaStatus を取得します。 Android TV アプリは、 MediaStatus 修飾子。

一部の状態とメタデータは、MediaSessionMediaStatusModifier。Google Cloud コンソールのみを設定することを強くおすすめします。 MediaSession。引き続き修飾子を使用して、 MediaSession - 修飾子のステータスは常に同じであるため、この方法はおすすめしません。 MediaSession で指定された値よりも優先度が高くなります。

送信前に MediaStatus をインターセプトする

Web Receiver SDK と同様、 送信するメッセージには、 MediaStatusInterceptor 処理し、 MediaStatus~ あります。関数を渡します。 MediaStatusWriter 送信前に MediaStatus を操作します。

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

ユーザー認証情報の処理

Android TV アプリで、特定のユーザーのみにアプリの起動や参加を許可している場合があります あります。たとえば、次の場合にのみ、送信者に開始や参加を許可します。

  • 送信側アプリが ATV アプリと同じアカウントとプロファイルにログインしていること。
  • 送信側アプリが、ATV アプリと同じアカウントにログインしていますが、プロファイルは異なります。

アプリで複数または匿名のユーザーが処理できる場合は、必要に応じて ATV セッションに参加するようユーザーに指示できます。ユーザーが認証情報を提供すると、ATV アプリは 進捗状況やその他のユーザーデータにアクセスできるように、 適切にトラッキングされます

送信側アプリが Android TV アプリを起動または Android TV アプリを起動すると、送信側アプリが セッションに参加するユーザーを表す認証情報を提供する必要があります。

送信者が Android TV アプリを起動して参加する前に、 チェッカーを起動して、送信者の認証情報が許可されているかどうかを確認します。そうでない場合、キャストは Connect SDK がフォールバックして Web Receiver を起動します。

送信側アプリの起動認証情報データ

送信者側では、CredentialsData を指定して 記録されます。

credentials は、ATV である限り、ユーザーが定義できる文字列です。 理解できます。credentialsType は、ユーザーがアクセスするプラットフォームを CredentialsData はカスタム値から取得するか、カスタム値にすることができます。デフォルトでは 送信側のプラットフォームに 送信することがあります

CredentialsData は、Android TV アプリの起動時にのみ渡されます。 記録されます。接続中に再度設定した場合、その設定は Android TV アプリ。接続中に送信者がプロフィールを切り替えた場合、 セッションにとどまるか、 SessionManager.endCurrentCastSession(boolean stopCasting) (新しいプロファイルがセッションに対応していないと思われる場合)。

CredentialsData 各送信者のメッセージは、 getSenders 日付 CastReceiverContext SenderInfo を取得する、 getCastLaunchRequest()CastLaunchRequest, 次に getCredentialsData()

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Android

play-services-cast-framework のバージョンが必要 19.0.0 以上。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Kotlin
で確認できます。
CastContext.getSharedInstance().setLaunchCredentialsData(
    CredentialsData.Builder()
        .setCredentials("{\"userId\": \"abc\"}")
        .build()
)
Java
で確認できます。
CastContext.getSharedInstance().setLaunchCredentialsData(
    new CredentialsData.Builder()
        .setCredentials("{\"userId\": \"abc\"}")
        .build());
<ph type="x-smartling-placeholder">
</ph>
iOS

google-cast-sdk バージョン v4.8.1 または 高くなります。

オプションの設定後、いつでも呼び出すことができます。 GCKCastContext.setSharedInstanceWith(options)

GCKCastContext.sharedInstance().setLaunch(
    GCKCredentialsData(credentials: "{\"userId\": \"abc\"}")
<ph type="x-smartling-placeholder">
</ph>
ウェブ

Chromium ブラウザのバージョンが必要です M87 以降。

オプションの設定後、いつでも呼び出すことができます。 cast.framework.CastContext.getInstance().setOptions(options);

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

ATV リリース リクエスト チェッカーの実装

CredentialsData 送信側が起動または参加しようとしたときに、Android TV アプリに渡されます。Google Chat では 実装 LaunchRequestChecker。 リクエストを許可または拒否できます

リクエストが拒否された場合、Web Receiver は起動されずに読み込まれます ATV アプリにネイティブに統合できますATV が対応できない場合、リクエストを拒否する必要があります。 開始または参加をリクエストしたユーザーを処理しますたとえば ユーザーがリクエストしたよりも ATV アプリにログインしており、アプリが 認証情報の切り替えを処理しているか、現在ログイン中のユーザーがいない ATV アプリ。

リクエストが許可されると、ATV アプリが起動します。これは ユーザーがリクエストしたときの読み込みリクエストの送信をアプリがサポートしているかどうかに応じて、 ユーザーが ATV アプリにログインしていない場合や、ユーザーが一致していない場合。この動作は、 LaunchRequestChecker で自由にカスタマイズ可能です。

実装するクラスを作成します。 CastReceiverOptions.LaunchRequestChecker インターフェース:

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

次に、 ReceiverOptionsProvider:

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

trueLaunchRequestChecker が ATV アプリを起動し、false が Web Receiver アプリを起動します。

送信とカスタム メッセージの受信

キャスト プロトコルを使用すると、送信者とメッセージの間でカスタム文字列のメッセージを送信できます。 受信します。送信する名前空間(チャンネル)を登録する必要があります。 初期化する前に CastReceiverContext

Android TV - カスタム名前空間を指定する

アプリケーションでサポートされている名前空間を CastReceiverOptions セットアップ中:

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 - メッセージの送信

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 - カスタム名前空間メッセージを受信する

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