Рекламные паузы
Android Sender SDK обеспечивает поддержку рекламных пауз и сопутствующей рекламы в рамках заданного медиапотока.
Для получения более подробной информации о том, как работают рекламные паузы, см. раздел «Обзор рекламных пауз в Web Receiver» .
Хотя прерывания можно указать как на отправителе, так и на получателе, рекомендуется указывать их на веб-приемнике и приемнике 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 автовоспроизведения и постановки в очередь» .
Переопределение выбора изображения для виджетов пользовательского интерфейса
Различные компоненты фреймворка (а именно диалоговое окно Cast, мини-контроллер и UIMediaController, если он настроен соответствующим образом) будут отображать обложки для текущего транслируемого медиаконтента. URL-адреса обложек изображений обычно включаются в MediaMetadata для медиафайла, но приложение-отправитель может иметь альтернативный источник URL-адресов.
Класс ImagePicker определяет способ выбора подходящего изображения из списка изображений в MediaMetadata в зависимости от назначения изображения, например, миниатюра уведомления или полноэкранный фон. Реализация ImagePicker по умолчанию всегда выбирает первое изображение или возвращает null, если в MediaMetadata нет подходящего изображения. Ваше приложение может создать подкласс ImagePicker и переопределить метод onPickImage(MediaMetadata, ImageHints) , чтобы предоставить альтернативную реализацию, а затем выбрать этот подкласс с помощью метода setImagePicker класса CastMediaOptions.Builder . ImageHints предоставляет ImagePicker подсказки о типе и размере изображения, которое будет выбрано для отображения в пользовательском интерфейсе.
Настройка диалоговых окон Cast
Управление жизненным циклом сессии
SessionManager — это центральный элемент управления жизненным циклом сессии. SessionManager отслеживает изменения состояния выбора маршрута в Android MediaRouter , чтобы запускать, возобновлять и завершать сессии. Когда маршрут выбран, SessionManager создает объект Session и пытается запустить или возобновить его. Когда маршрут отменен, SessionManager завершает текущую сессию.
Следовательно, для обеспечения корректного управления жизненным циклом сессий с SessionManager необходимо убедиться в следующем:
- В диалоговом окне выбора маршрута вызовите метод
MediaRouter.selectRoute(MediaRouter.RouteInfo)когда пользователь выберет устройство. - В диалоговом окне контроллера маршрутизации (в состоянии подключения или в состоянии трансляции ) вызовите метод
MediaRouter.unselect(int), когда пользователь прекратит трансляцию.
В зависимости от способа создания диалоговых окон преобразования, может потребоваться выполнение дополнительных действий:
- Если вы создадите диалоги Cast с использованием
MediaRouteChooserDialogиMediaRouteControllerDialog, то эти диалоги автоматически обновят выбор маршрута вMediaRouter, поэтому ничего делать не потребуется. - Если вы настраиваете кнопку Cast с помощью
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)илиCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton), то диалоговые окна фактически создаются с помощьюMediaRouteChooserDialogиMediaRouteControllerDialog, поэтому ничего делать не нужно. - В других случаях вам потребуется создавать пользовательские диалоги Cast, поэтому необходимо следовать приведенным выше инструкциям, чтобы обновить состояние выбора маршрута в
MediaRouter.
Состояние «Ноль устройств»
Если вы создаете пользовательские диалоги Cast, ваш пользовательский диалог MediaRouteChooserDialog должен корректно обрабатывать случай, когда ни одно устройство не найдено. Диалог должен содержать индикаторы, которые ясно показывают пользователям, когда ваше приложение все еще пытается найти устройства, а когда попытка обнаружения больше не активна.
Если вы используете диалоговое окно MediaRouteChooserDialog по умолчанию, состояние «ноль устройств» уже обрабатывается.
Следующие шаги
На этом завершается описание функций, которые вы можете добавить в свое приложение-отправитель для Android. Теперь вы можете создать приложение-отправитель для другой платформы ( iOS или веб ) или веб-приложение-получатель .