Как перенести приложение отправителя для Android с Cast SDK версии 2 на Cast Application Framework (CAF)

Ниже описано, как преобразовать приложение отправителя для Android с Cast SDK версии 2 в CAF Sender, который основан на одноэлементном объекте CastContext.

В CAF Sender SDK для Cast используется CastContext, чтобы управлять GoogleAPIClient от вашего имени. CastContext управляет жизненными циклами, ошибками и обратными вызовами, что значительно упрощает разработку приложений Cast.

Введение

  • CAF Sender по-прежнему распространяется в составе сервисов Google Play с помощью Android SDK Manager.
  • Добавлены новые пакеты, которые отвечают за соблюдение требований контрольного списка Google Cast Design (com.google.android.gms.cast.framework.*).
  • CAF Sender предоставляет виджеты, соответствующие требованиям Cast UX. В версии 2 не было компонентов пользовательского интерфейса, и вам приходилось реализовывать эти виджеты самостоятельно.
  • Для использования Cast API больше не требуется GoogleApiClient.
  • Субтитры в CAF Sender работают так же, как и в версии 2.

Зависимости

Версии 2 и CAF имеют одинаковые зависимости от библиотек поддержки и сервисов Google Play (9.2.0 или более поздней версии), как описано в руководстве по функциям библиотеки поддержки.

Минимальная версия Android SDK, поддерживаемая CAF, – 9 (Gingerbread).

Инициализация

В CAF для фреймворка Cast требуется явный шаг инициализации. Для этого нужно инициализировать объект-одиночку CastContext, используя подходящий объект OptionsProvider, чтобы указать идентификатор приложения веб-приемника и другие глобальные параметры.

public class CastOptionsProvider implements OptionsProvider {

    @Override
    public CastOptions getCastOptions(Context context) {
        return new CastOptions.Builder()
                .setReceiverApplicationId(context.getString(R.string.app_id))
                .build();
    }

    @Override
    public List<SessionProvider> getAdditionalSessionProviders(Context context) {
        return null;
    }
}

Объявите OptionsProvider в теге application файла AndroidManifest.xml:

<application>
...
    <meta-data
        android:name=
            "com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
        android:value="com.google.sample.cast.refplayer.CastOptionsProvider" />
</application>

Выполните ленивую инициализацию CastContext в методе onCreate каждого класса Activity:

private CastContext mCastContext;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.video_browser);
    setupActionBar();

    mCastContext = CastContext.getSharedInstance(this);
}

В версии 2 эти шаги не требовались.

Обнаружение устройств

В CAF процесс обнаружения запускается и останавливается автоматически, когда приложение переходит в активный или фоновый режим. Не используйте MediaRouteSelector и MediaRouter.Callback.

Кнопка трансляции и диалоговое окно трансляции

Как и в версии 2, эти компоненты предоставляются библиотекой поддержки MediaRouter.

Кнопка трансляции по-прежнему реализуется с помощью MediaRouteButton и может быть добавлена в действие (с помощью ActionBar или Toolbar) в качестве пункта меню.

<item
    android:id="@+id/media_route_menu_item"
    android:title="@string/media_route_menu_title"
    app:actionProviderClass="android.support.v7.app.MediaRouteActionProvider"
    app:showAsAction="always"/>

Переопределите метод onCreateOptionMenu() каждого Activity, используя CastButtonFactory, чтобы подключить MediaRouteButton к фреймворку Cast:

private MenuItem mediaRouteMenuItem;

public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    getMenuInflater().inflate(R.menu.browse, menu);
    mediaRouteMenuItem =
        CastButtonFactory.setUpMediaRouteButton(getApplicationContext(),
                                                menu,
                                                R.id.media_route_menu_item);
    return true;
}

Когда пользователь нажимает на кнопку, автоматически открывается диалоговое окно Cast.

Управление устройством

В CAF управление устройствами в основном осуществляется с помощью фреймворка. Приложению отправителя не нужно (и не следует пытаться) подключаться к устройству и запускать приложение веб-приемника с помощью GoogleApiClient. Взаимодействие между отправителем и веб-приемником теперь называется сеансом. Класс SessionManager управляет жизненным циклом сеанса и автоматически запускает и останавливает сеансы в ответ на действия пользователя: сеанс начинается, когда пользователь выбирает устройство Cast в диалоговом окне Cast, и заканчивается, когда пользователь нажимает кнопку "Остановить трансляцию" в диалоговом окне Cast или когда завершается работа приложения отправителя. Приложение отправителя может получать уведомления о событиях жизненного цикла сеанса, зарегистрировав SessionManagerListener в SessionManager. Функции обратного вызова SessionManagerListener определяют методы обратного вызова для всех событий жизненного цикла сеанса.

Класс CastSession представляет сеанс с устройством Cast. В этом классе есть методы для управления громкостью устройства и отключения звука, которые ранее выполнялись в версии 2 с помощью методов в Cast.CastApi.

В версии 2 Cast.Listener обратные вызовы предоставляли уведомления об изменениях состояния устройства, включая громкость, статус отключения звука, статус ожидания и т. д.

В CAF уведомления об изменении состояния громкости или отключения звука по-прежнему передаются с помощью методов обратного вызова в Cast.Listener. Эти прослушиватели регистрируются с помощью CastSession. Остальные уведомления о состоянии устройства передаются через обратные вызовы CastStateListener. Эти слушатели регистрируются с помощью CastSession. Не забывайте отменять регистрацию слушателей, когда связанные с ними фрагменты, действия или приложения переходят в фоновый режим.

Логика повторного подключения

Как и в версии 2, CAF пытается восстановить сетевые подключения, которые были потеряны из-за временной потери сигнала Wi-Fi или других ошибок сети. Теперь это делается на уровне сеанса. Сеанс может перейти в состояние "приостановлен", когда соединение потеряно, и вернуться в состояние "подключено", когда связь восстановлена. Фреймворк автоматически повторно подключается к приложению Web Receiver и каналам Cast.

Кроме того, в CAF добавлено автоматическое возобновление сеанса, которое включено по умолчанию (его можно отключить с помощью CastOptions). Если приложение отправителя переходит в фоновый режим или закрывается (из-за сбоя или если пользователь провел по экрану), когда сеанс Cast активен, фреймворк попытается возобновить этот сеанс, когда приложение отправителя вернется на передний план или будет перезапущено. Это происходит автоматически с помощью SessionManager, который вызывает подходящие обратные вызовы для всех зарегистрированных экземпляров SessionManagerListener.

Регистрация клиентского канала

В версии 2 пользовательские каналы (реализованные с помощью тега Cast.MessageReceivedCallback) регистрируются с помощью тега Cast.CastApi. В CAF клиентские каналы регистрируются в экземпляре CastSession. Регистрацию можно выполнить в методе обратного вызова SessionManagerListener.onSessionStarted. В медиаприложениях больше не нужно явно регистрировать канал управления мультимедиа с помощью Cast.CastApi.setMessageReceivedCallbacks. Подробнее об этом рассказывается в следующем разделе.

Управление мультимедиа

Класс RemoteMediaPlayer из версии 2 больше не поддерживается, и его нельзя использовать. В CAF его заменяет новый класс RemoteMediaClient, который предоставляет аналогичные функции в более удобном API. Инициализировать или регистрировать этот объект не нужно. Фреймворк автоматически создаст экземпляр объекта и зарегистрирует базовый медиаканал при запуске сеанса, если приложение веб-приемника, к которому устанавливается подключение, поддерживает пространство имен мультимедиа.

Доступ к RemoteMediaClient можно получить как к методу getRemoteMediaClient объекта CastSession.

В версии 2 все запросы медиаконтента, отправленные в RemoteMediaPlayer, возвращали RemoteMediaPlayer.MediaChannelResult через обратный вызов PendingResult.

В CAF все запросы медиаконтента, отправленные в RemoteMediaClient, возвращают RemoteMediaClient.MediaChannelResult через обратный вызов PendingResult, который можно использовать для отслеживания хода выполнения и результата запроса.

В версии 2 RemoteMediaPlayer уведомления об изменениях состояния медиапроигрывателя на веб-приемнике отправлялись через RemoteMediaPlayer.OnStatusUpdatedListener.

В CAF RemoteMediaClient предоставляет эквивалентные обратные вызовы через интерфейс RemoteMediaClient.Listener. В RemoteMediaClient можно зарегистрировать любое количество слушателей, что позволяет нескольким компонентам отправителя использовать один экземпляр RemoteMediaClient, связанный с сеансом.

В версии 2 приложение-отправитель должно было синхронизировать пользовательский интерфейс с состоянием медиапроигрывателя в веб-приемнике.

В CAF большую часть этой ответственности берет на себя класс UIMediaController.

Оверлей с вводной информацией

В версии 2 нет интерфейса с вводным оверлеем.

В CAF есть специальный вид IntroductoryOverlay, который позволяет выделить кнопку трансляции, когда она впервые показывается пользователям.

Мини-контроллер

В версии 2 вам нужно реализовать мини-контроллер с нуля в приложении отправителя.

В CAF SDK предоставляет специальное представление MiniControllerFragment, которое можно добавить в файл макета приложения для тех действий, в которых вы хотите показывать мини-контроллер.

Уведомления и заблокированный экран

В версии 2 SDK не предоставляет контроллеры для уведомлений и заблокированного экрана. Для этого SDK вам нужно будет реализовать эти функции в приложении отправителя, используя API фреймворка Android.

В CAF SDK предоставляет NotificationsOptions.Builder, чтобы помочь вам создать элементы управления медиаконтентом для уведомлений и заблокированного экрана в приложении отправителя. Элементы управления уведомлениями и заблокированным экраном можно включить с помощью CastOptions при инициализации CastContext.

public CastOptions getCastOptions(Context context) {
    NotificationOptions notificationOptions = new NotificationOptions.Builder()
            .setTargetActivityClassName(VideoBrowserActivity.class.getName())
            .build();
    CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
            .setNotificationOptions(notificationOptions)
            .build();

    return new CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .setCastMediaOptions(mediaOptions)
            .build();
}

Расширенный контроллер

В версии 2 необходимо реализовать расширенный контроллер с нуля в приложении отправителя.

В CAF есть вспомогательный класс UIMediaController, который позволяет легко создать собственный расширенный контроллер.

В CAF есть готовый виджет расширенного контроллера ExpandedControllerActivity, который можно просто добавить в приложение. Вам больше не нужно реализовывать собственный расширенный контроллер с помощью UIMediaController.

Аудиофокус

В версии 2 для управления фокусом аудио нужно использовать MediaSessionCompat.

В CAF фокус звука управляется автоматически.

Журнал отладки

В CAF нет настроек ведения журналов.

Примеры приложений

У нас есть практические руководства и примеры приложений, в которых используется CAF.