ミッドロール挿入点
Android Sender SDK は、特定のメディア ストリーム内のミッドロール挿入点とコンパニオン広告をサポートしています。
ミッドロール挿入点の仕組みについて詳しくは、ウェブ レシーバーのミッドロール挿入点の概要をご覧ください。
挿入点はセンダーとレシーバの両方に指定できますが、プラットフォーム間で一貫した動作を維持するために、ウェブ レシーバーと Android TV レシーバーで指定することをおすすめします。
Android では、AdBreakClipInfo
と AdBreakInfo
を使用して、読み込みコマンドでミッドロール挿入点を指定します。
val breakClip1: AdBreakClipInfo = AdBreakClipInfo.Builder("bc0") .setTitle("Clip title") .setPosterUrl("https://www.some.url") .setDuration(60000) .setWhenSkippableInMs(5000) // Set this field so that the ad is skippable .build() val breakClip2: AdBreakClipInfo = … val breakClip3: AdBreakClipInfo = … val break1: AdBreakClipInfo = AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000) .setId("b0") .setBreakClipIds({"bc0","bc1","bc2"}) … .build() val mediaInfo: MediaInfo = MediaInfo.Builder() … .setAdBreaks({break1}) .setAdBreakClips({breakClip1, breakClip2, breakClip3}) .build() val mediaLoadRequestData: MediaLoadRequestData = MediaInfo.Builder() … .setMediaInfo(mediaInfo) .build() remoteMediaClient.load(mediaLoadRequestData)
AdBreakClipInfo breakClip1 = new AdBreakClipInfo.Builder("bc0") .setTitle("Clip title") .setPosterUrl("https://www.some.url") .setDuration(60000) .setWhenSkippableInMs(5000) // Set this field so that the ad is skippable .build(); AdBreakClipInfo breakClip2 = … AdBreakClipInfo breakClip3 = … AdBreakInfo break1 = new AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000) .setId("b0") .setBreakClipIds({"bc0","bc1","bc2"}) … .build(); MediaInfo mediaInfo = new MediaInfo.Builder() … .setAdBreaks({break1}) .setAdBreakClips({breakClip1, breakClip2, breakClip3}) .build(); MediaLoadRequestData mediaLoadRequestData = new MediaInfo.Builder() … .setMediaInfo(mediaInfo) .build(); remoteMediaClient.load(mediaLoadRequestData);
カスタム アクションを追加する
送信アプリは、MediaIntentReceiver
を拡張して、カスタム アクションの処理や、その動作のオーバーライドを行えます。独自の MediaIntentReceiver
を実装している場合は、マニフェストに追加し、その名前を CastMediaOptions
に設定する必要があります。この例では、リモートのメディア再生の切り替え、メディアボタンの押下などのアクションをオーバーライドするカスタム アクションを提供します。
// In AndroidManifest.xml
<receiver android:name="com.example.MyMediaIntentReceiver" />
// In your OptionsProvider var mediaOptions = CastMediaOptions.Builder() .setMediaIntentReceiverClassName(MyMediaIntentReceiver::class.java.name) .build() // Implementation of MyMediaIntentReceiver internal class MyMediaIntentReceiver : MediaIntentReceiver() { override fun onReceiveActionTogglePlayback(currentSession: Session) { } override fun onReceiveActionMediaButton(currentSession: Session, intent: Intent) { } override fun onReceiveOtherAction(context: Context?, action: String, intent: Intent) { } }
// In your OptionsProvider CastMediaOptions mediaOptions = new CastMediaOptions.Builder() .setMediaIntentReceiverClassName(MyMediaIntentReceiver.class.getName()) .build(); // Implementation of MyMediaIntentReceiver class MyMediaIntentReceiver extends MediaIntentReceiver { @Override protected void onReceiveActionTogglePlayback(Session currentSession) { } @Override protected void onReceiveActionMediaButton(Session currentSession, Intent intent) { } @Override protected void onReceiveOtherAction(Context context, String action, Intent intent) { } }
カスタム チャネルを追加する
送信側アプリが受信側アプリと通信するには、アプリでカスタム チャネルを作成する必要があります。送信者はカスタム チャネルを使用して、文字列メッセージを受信者に送信できます。各カスタム チャネルは一意の名前空間で定義され、接頭辞 urn:x-cast:
で始める必要があります(例: urn:x-cast:com.example.custom
)。それぞれに一意の名前空間を持つ複数のカスタム チャネルを設定できます。受信側アプリは、同じ名前空間を使用してメッセージを送受信することもできます。
カスタム チャネルは、Cast.MessageReceivedCallback
インターフェースを使用して実装されます。
class HelloWorldChannel : MessageReceivedCallback { val namespace: String get() = "urn:x-cast:com.example.custom" override fun onMessageReceived(castDevice: CastDevice, namespace: String, message: String) { Log.d(TAG, "onMessageReceived: $message") } }
class HelloWorldChannel implements Cast.MessageReceivedCallback { public String getNamespace() { return "urn:x-cast:com.example.custom"; } @Override public void onMessageReceived(CastDevice castDevice, String namespace, String message) { Log.d(TAG, "onMessageReceived: " + message); } }
送信側アプリが受信側アプリに接続されると、setMessageReceivedCallbacks
メソッドを使用してカスタム チャネルを作成できます。
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.namespace, mHelloWorldChannel) } catch (e: IOException) { Log.e(TAG, "Exception while creating channel", e) }
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.getNamespace(), mHelloWorldChannel); } catch (IOException e) { Log.e(TAG, "Exception while creating channel", e); }
カスタム チャネルを作成したら、送信者は sendMessage
メソッドを使用して、そのチャネルを介して文字列メッセージをレシーバに送信できます。
private fun sendMessage(message: String) { if (mHelloWorldChannel != null) { try { mCastSession.sendMessage(mHelloWorldChannel.namespace, message) .setResultCallback { status -> if (!status.isSuccess) { Log.e(TAG, "Sending message failed") } } } catch (e: Exception) { Log.e(TAG, "Exception while sending message", e) } } }
private void sendMessage(String message) { if (mHelloWorldChannel != null) { try { mCastSession.sendMessage(mHelloWorldChannel.getNamespace(), message) .setResultCallback( status -> { if (!status.isSuccess()) { Log.e(TAG, "Sending message failed"); } }); } catch (Exception e) { Log.e(TAG, "Exception while sending message", e); } } }
自動再生をサポートする
Autoplay API と Queueing API のセクションをご覧ください。
UX ウィジェットの画像選択をオーバーライドする
フレームワークのさまざまなコンポーネント(キャスト ダイアログ、ミニ コントローラ、UIMediaController で構成されている場合)は、現在キャスト中のメディアのアートワークを表示します。画像アートワークへの URL は通常、メディアの MediaMetadata
に含まれていますが、送信側アプリに URL の代替ソースがある場合があります。
ImagePicker
クラスは、画像の使用(通知サムネイルや全画面表示の背景など)に基づいて、MediaMetadata
内の画像のリストから適切な画像を選択する手段を定義します。デフォルトの ImagePicker
実装は常に最初の画像を選択するか、MediaMetadata
に使用可能な画像がない場合は null を返します。アプリでは、ImagePicker
をサブクラス化して onPickImage(MediaMetadata, ImageHints)
メソッドをオーバーライドし、別の実装を提供してから、CastMediaOptions.Builder
の setImagePicker
メソッドを使用してそのサブクラスを選択できます。ImageHints
は、UI での表示用に選択する画像のタイプとサイズに関する情報を ImagePicker
に提供します。
Cast ダイアログのカスタマイズ
セッション ライフサイクルの管理
SessionManager
は、セッションのライフサイクルを一元的に管理できる場所です。SessionManager
は、Android MediaRouter
のルート選択状態の変化をリッスンし、セッションの開始、再開、終了を行います。ルートが選択されると、SessionManager
は Session
オブジェクトを作成し、その開始または再開を試みます。ルートの選択を解除すると、SessionManager
は現在のセッションを終了します。
したがって、SessionManager
がセッション ライフサイクルを適切に管理するには、次のことを確認する必要があります。
- ルートセレクタ ダイアログで、ユーザーがデバイスを選択したときに
MediaRouter.selectRoute(MediaRouter.RouteInfo)
を呼び出します。 - ルート コントローラのダイアログ(接続状態またはキャスト状態)で、ユーザーがキャストを停止したときに
MediaRouter.unselect(int)
を呼び出します。
キャスト ダイアログの作成方法によっては、追加の操作が必要になることがあります。
MediaRouteChooserDialog
とMediaRouteControllerDialog
を使用してキャスト ダイアログを作成した場合、これらのダイアログはMediaRouter
でのルート選択を自動的に更新するため、何もする必要はありません。CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)
またはCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton)
を使用してキャスト アイコンをセットアップした場合、実際にはMediaRouteChooserDialog
とMediaRouteControllerDialog
を使用してダイアログが作成されるため、何もする必要はありません。- それ以外の場合は、カスタムの Cast ダイアログを作成するため、上記の手順に沿って
MediaRouter
でルート選択の状態を更新する必要があります。
ゼロデバイスの状態
カスタムのキャスト ダイアログを作成する場合、カスタム MediaRouteChooserDialog
はデバイスが見つからないケースを適切に処理する必要があります。ダイアログには、アプリがデバイスの検出を試行中であるか、検出の試行がアクティブでなくなったときに、ユーザーがそれを明確に示すインジケーターを表示する必要があります。
デフォルトの MediaRouteChooserDialog
を使用している場合、ゼロデバイスの状態はすでに処理されています。
次のステップ
これで、Android の送信者アプリに追加できる機能は終わりです。これで、別のプラットフォーム(iOS またはウェブ)用の送信者アプリ、または Web Receiver アプリを構築できるようになりました。