광고 시점
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); } } }
자동재생 지원
자동재생 및 대기열 API 섹션을 참고하세요.
UX 위젯의 이미지 선택 재정의
프레임워크의 다양한 구성요소 (예: 전송 대화상자, 미니 컨트롤러, UIMediaController가 구성된 경우)에는 현재 전송 중인 미디어의 아트워크가 표시됩니다. 이미지 아트워크의 URL은 일반적으로 미디어의 MediaMetadata
에 포함되어 있지만 발신기 앱에는 이 URL의 대체 소스가 있을 수 있습니다.
ImagePicker
클래스는 이미지 사용에 따라 MediaMetadata
의 이미지 목록에서 적절한 이미지(예: 알림 썸네일 또는 전체 화면 배경)를 선택하는 수단을 정의합니다. 기본 ImagePicker
구현은 항상 첫 번째 이미지를 선택합니다. MediaMetadata
에 사용 가능한 이미지가 없으면 null을 반환합니다. 앱은 ImagePicker
를 서브클래스로 분류하고 onPickImage(MediaMetadata, ImageHints)
메서드를 재정의하여 대체 구현을 제공한 다음, CastMediaOptions.Builder
의 setImagePicker
메서드를 사용하여 서브클래스를 선택할 수 있습니다.
ImageHints
은 UI에 표시되도록 선택할 이미지의 유형과 크기에 관한 힌트를 ImagePicker
에 제공합니다.
전송 대화상자 맞춤설정
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
에서 경로 선택 상태를 업데이트해야 합니다.
다음 단계
이것으로 Android Sender 앱에 추가할 수 있는 기능을 마칩니다. 이제 다른 플랫폼(iOS 또는 웹)의 발신자 앱을 빌드하거나 웹 수신기 앱을 빌드할 수 있습니다.