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

Ниже описано, как преобразовать приложение-отправитель для Android, созданное с помощью Cast SDK версии 2, в приложение-отправитель CAF, основанное на синглтоне CastContext.

Cast CAF Sender SDK использует 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.

Зависимости

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

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

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

В CAF требуется явный шаг инициализации для Cast framework. Для этого нужно инициализировать одноэлементный объект 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.

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

Как и во второй версии, эти компоненты предоставляются библиотекой поддержки 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 управление устройствами в основном осуществляется фреймворком. Приложению-отправителю не нужно обрабатывать подключение к устройству и запуск приложения Web Receiver с помощью 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 или других ошибок сети. Теперь это делается на уровне сеанса. При потере подключения сеанс может перейти в состояние "приостановлен", а при восстановлении подключения – в состояние "подключен". Фреймворк берет на себя повторное подключение к приложению веб-приемника и повторное подключение любых каналов 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.