Migra la app emisora de CCL al framework de aplicaciones de Cast (CAF)

El siguiente procedimiento te permite convertir tu app emisora de Android de Versión 2 del SDK de Cast con CCL a CAF. Todas las funciones de CCL implementada en CAF, por lo que, una vez que realices la migración, ya no necesitarás usar CCL.

El SDK de Cast CAF Sender usa CastContext para administrar GoogleAPIClient en tu nombre. CastContext administra ciclos de vida, errores y devoluciones de llamada por ti, lo que en gran medida simplifica el desarrollo de una app de Cast.

Introducción

  • Como la Biblioteca complementaria de Cast influyó en el diseño del remitente de CAF, la migración de CCL a CAF Sender implica principalmente asignaciones uno a uno de clases y sus métodos.
  • CAF Sender se sigue distribuyendo como parte de Google Play Services. con SDK Manager de Android.
  • Paquetes nuevos (com.google.android.gms.cast.framework.*) que se agregado a CAF Sender, con una funcionalidad similar a CCL, la responsabilidad de cumplir con las Lista de tareas de diseño de Google Cast
  • El remitente de CAF proporciona widgets que cumplen con los requisitos de UX de Cast. estos widgets son similares a los que proporciona CCL.
  • CAF Sender proporciona devoluciones de llamada asíncronas que son similares a CCL, para rastrear estados y obtener datos. A diferencia de CCL, CAF Sender no proporciona ningún de los diversos métodos de interfaz.

En las siguientes secciones, nos enfocaremos principalmente en basadas en VideoCastManager de CCL, pero en muchos casos, la misma se aplican a DataCastManager también.

Dependencias

CCL y CAF tienen las mismas dependencias en la biblioteca de compatibilidad de AppCompat, Biblioteca de compatibilidad de MediaRouter v7 y Servicios de Google Play. Sin embargo, la diferencia es que CAF depende del nuevo framework de Cast disponible en Google Play. services 9.2.0 o versiones posteriores.

En tu archivo build.gradle, quita las dependencias en com.google.android.gms:play-services-cast y com.google.android.libraries.cast.companionlibrary:ccl, Luego, agrega el nuevo framework de Cast:

dependencies {
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.android.support:mediarouter-v7:23.4.0'
    compile 'com.google.android.gms:play-services-cast-framework:9.4.0'
}

También puedes quitar los metadatos de los Servicios de Google Play de la siguiente manera:

<meta‐data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>

Todos los servicios, actividades y recursos que formen parte de CAF se se combinarán con el manifiesto y los recursos de tu app.

La versión mínima del SDK de Android compatible con CAF es la 9 (Gingerbread); La versión mínima del SDK de Android para CCL es la 10.

CCL proporciona un método conveniente, BaseCastManager.checkGooglePlayServices(activity) para verificar que se haya versión de los Servicios de Google Play esté disponible en el dispositivo. El CAF no proporcionarla como parte del SDK de Cast. Sigue el procedimiento Asegúrate de que los dispositivos tengan el APK de Servicios de Google Play para asegurarte de que el APK correcto de los Servicios de Google Play esté instalado en el dispositivo, ya que es posible que las actualizaciones no lleguen a todos los usuarios de inmediato.

Aún debes usar una variante de Theme.AppCompat para la configuración el tema.

Inicialización

Para CCL, se requería llamar a VideoCastManager.initialize() en el El método onCreate() de la instancia de Aplicaciones Esta lógica debería ser del código de la clase Application.

En CAF, también se requiere un paso de inicialización explícito para la transmisión en un framework de aplicaciones. Esto implica inicializar el singleton CastContext con un el OptionsProvider apropiado para especificar el ID de aplicación del receptor y cualquier otras opciones globales. CastContext cumple una función similar a la de CCL. VideoCastManager proporcionando un singleton con el que los clientes pueden interactuar OptionsProvider es similar a CastConfiguration de CCL para permitirte para configurar las funciones del framework de Cast.

Si tu CastConfiguration.Builder de CCL actual se ve de la siguiente manera:

VideoCastManager.initialize(
   getApplicationContext(),
   new CastConfiguration.Builder(context.getString(R.string.app_id))
       .enableWifiReconnection()
       .enableAutoReconnect()
       .build());

Luego, en CAF, el siguiente CastOptionsProvider con CastOptions.Builder sería similar:

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;
    }
}

Consulta nuestra app de ejemplo. para obtener una implementación completa de OptionsProvider.

Declara el OptionsProvider dentro de la “aplicación” elemento de la Archivo 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>

Inicializa de forma diferida el CastContext en cada método onCreate de Activity. (y no la instancia Application):

private CastContext mCastContext;

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

    mCastContext = CastContext.getSharedInstance(this);
}

Para acceder al singleton CastContext, usa lo siguiente:

mCastContext = CastContext.getSharedInstance(this);

Cómo detectar dispositivos

Los VideoCastManager incrementUiCounter y decrementUiCounter de CCL deben Se quitarán de los métodos onResume y onPause de tu Activities.

En CAF, el proceso de detección se inicia y se detiene automáticamente cuando la app pasa a primer plano y a segundo plano, respectivamente.

Botón para transmitir y diálogo de transmisión

Al igual que con CCL, la asistencia de MediaRouter v7 proporciona estos componentes. biblioteca.

MediaRouteButton aún implementa el botón para transmitir, y puedes agregarlo a tu actividad (mediante un ActionBar o un Toolbar), como un elemento de menú del menú.

La declaración de MediaRouteActionProvider en el XML del menú es la misma que con CCL:

<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"/>

Similar a CCL, anula el método onCreateOptionMenu() de cada Activity, pero en lugar de usar CastManager.addMediaRouterButton, usa CastButtonFactory de CAF Para conectar el MediaRouteButton al framework de Cast, haz lo siguiente:

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

Control de dispositivos

Al igual que en CCL, en CAF, el control de dispositivos lo maneja en gran medida el framework. La aplicación emisora no necesita controlarla (ni debe intentar hacerlo). conectarse al dispositivo e iniciar la aplicación receptora mediante GoogleApiClient

La interacción entre el remitente y el receptor ahora se representa como una "sesión". El La clase SessionManager controla el ciclo de vida de la sesión y se inicia automáticamente y detiene las sesiones en respuesta a los gestos del usuario: se inicia una sesión cuando El usuario selecciona un dispositivo de transmisión en el diálogo de transmisión y finaliza cuando lo presiona. el botón "Detener la transmisión" en el diálogo Transmitir o cuando la propia app emisora y finaliza el proceso.

En CCL, debes extender la clase VideoCastConsumerImpl para hacer un seguimiento de la transmisión estado de la sesión:

private final VideoCastConsumer mCastConsumer = new VideoCastConsumerImpl() {
  public void onApplicationConnected(ApplicationMetadata appMetadata, 
                                     String sessionId,
                                     boolean wasLaunched) {}
  public void onDisconnectionReason(int reason) {}
  public void onDisconnected() {}
}

En CAF, la aplicación emisora puede recibir notificaciones de los eventos del ciclo de vida de la sesión registrando un SessionManagerListener con SessionManager. El Las devoluciones de llamada de SessionManagerListener definen métodos de devolución de llamada para todas las sesiones de ciclo de vida de los objetos.

Los siguientes métodos SessionManagerListener se asignan a partir de CCL Interfaz de VideoCastConsumer:

  • VideoCastConsumer.onApplicationConnected -> SessionManagerListener.onSessionStarted
  • VideoCastConsumer.onDisconnected -> SessionManagerListener.onSessionEnded

Declara una clase que implemente la interfaz SessionManagerListener y mueve la lógica VideoCastConsumerImpl con los métodos coincidentes:

private class CastSessionManagerListener implements SessionManagerListener<CastSession> {
  public void onSessionEnded(CastSession session, int error) {}
  public void onSessionStarted(CastSession session, String sessionId) {}
  public void onSessionEnding(CastSession session) {}
  ...
}

La clase CastSession representa una sesión con un dispositivo de transmisión. La clase tiene métodos para controlar los estados de volumen y silencio del dispositivo, lo que hace CCL en el BaseCastManager

En lugar de usar la CCL VideoCastManager para agregar un consumidor, haz lo siguiente:

VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);

Ahora registra tu SessionManagerListener:

mCastSessionManager = 
    CastContext.getSharedInstance(this).getSessionManager();
mCastSessionManagerListener = new CastSessionManagerListener();
mCastSessionManager.addSessionManagerListener(mCastSessionManagerListener,
                  CastSession.class);

Para dejar de escuchar eventos en CCL, haz lo siguiente:

VideoCastManager.getInstance().removeVideoCastConsumer(mCastConsumer);

Ahora, usa SessionManager para dejar de escuchar los eventos de sesión:

mCastSessionManager.removeSessionManagerListener(mCastSessionManagerListener,
                    CastSession.class);

Para desconectarse explícitamente del dispositivo de transmisión, CCL usó lo siguiente:

VideoCastManager.disconnectDevice(boolean stopAppOnExit, 
            boolean clearPersistedConnectionData,
            boolean setDefaultRoute)

Para CAF, usa SessionManager:

CastContext.getSharedInstance(this).getSessionManager()
                                   .endCurrentSession(true);

Para determinar si el remitente está conectado con el receptor, CCL proporciona VideoCastManager.getInstance().isConnected(), pero, en CAF, usa el SessionManager

public boolean isConnected() {
    CastSession castSession = CastContext.getSharedInstance(mAppContext)
                                  .getSessionManager()
                                  .getCurrentCastSession();
    return (castSession != null && castSession.isConnected());
}

En CAF, las notificaciones sobre cambios de volumen o silencio se siguen entregando mediante devolución de llamada métodos en Cast.Listener; estos objetos de escucha están registrados con CastSession Todas las notificaciones restantes sobre el estado del dispositivo se envían a través de CastStateListener devoluciones de llamada; estos objetos de escucha se registran con el CastSession Asegúrate de cancelar el registro de los objetos de escucha cuando Los fragmentos, las actividades o las apps pasan a segundo plano.

Lógica de reconexión

El CAF intenta restablecer las conexiones de red que se pierden debido a una pérdida temporal de la señal de Wi-Fi u otros errores de red. Ahora esto se hace en la nivel de sesión; una sesión puede entrar en estado "suspendido" el estado cuando la conexión está se pierde y vuelve a cambiar a una cuenta “conectada” cuando la conectividad está restaurado. El framework se encarga de volver a conectarse a la aplicación receptora y volver a conectar cualquier canal de transmisión como parte del proceso.

CAF proporciona su propio servicio de reconexión, por lo que puedes quitar la CCL ReconnectionService de tu manifiesto:

<service android:name="com.google.android.libraries.cast.companionlibrary.cast.reconnection.ReconnectionService"/>

Tampoco necesitas los siguientes permisos en tu manifiesto para el lógica de reconexión:

<uses‐permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses‐permission android:name="android.permission.ACCESS_WIFI_STATE"/>

El servicio de reconexión de CAF se habilita de forma predeterminada, pero se puede inhabilitar usando el CastOptions

Además, el CAF también agrega la reanudación automática de la sesión, que se habilita mediante de forma predeterminada (y se puede desactivar mediante CastOptions). Si la aplicación remitente está se envía a segundo plano o se finaliza (cuando se desliza o debido a una falla) mientras una sesión de transmisión está en curso, el framework intentará reanudar esa cuando la aplicación emisora vuelve al primer plano o se reinicia; SessionManager se encarga automáticamente de esto, que emitirá el las devoluciones de llamada correspondientes en cualquier instancia SessionManagerListener registrada.

Registro de canales personalizados

CCL proporciona dos formas de crear un canal de mensajes personalizado para el receptor:

  • CastConfiguration te permite especificar varios espacios de nombres, y CCL y, luego, crear el canal por ti.
  • DataCastManager es similar a VideoCastManager, pero se enfoca en contenido que no es multimedia. casos de uso.

CAF no admite ninguna de estas formas de crear canales personalizados: en su lugar, deberás seguir el procedimiento Agrega un canal personalizado para tu app emisora.

Al igual que con CCL, para las aplicaciones de medios, no es necesario registrar el canal de control de contenido multimedia.

Control multimedia

En CAF, la clase RemoteMediaClient es equivalente a VideoCastManager. métodos multimedia. RemoteMediaClient.Listener es equivalente a VideoCastConsumer. En particular, el onRemoteMediaPlayerMetadataUpdated y onRemoteMediaPlayerStatusUpdated métodos de VideoCastConsumer se mapean a onMetadataUpdated y onStatusUpdated de RemoteMediaClient.Listener, respectivamente:

private class CastMediaClientListener implements RemoteMediaClient.Listener {

    @Override
    public void onMetadataUpdated() {
        setMetadataFromRemote();
    }

    @Override
    public void onStatusUpdated() {
        updatePlaybackState();
    }

    @Override
    public void onSendingRemoteMediaRequest() {
    }

    @Override
    public void onQueueStatusUpdated() {
    }

    @Override
    public void onPreloadStatusUpdated() {
    }
}

No es necesario inicializar ni registrar de forma explícita el RemoteMediaClient. object; el framework creará automáticamente una instancia del objeto y registrará canal de medios subyacente al momento de inicio de la sesión si la aplicación receptora conectado admite el espacio de nombres de contenido multimedia.

Se puede acceder a RemoteMediaClient como el método getRemoteMediaClient de el objeto CastSession.

CastSession castSession = CastContext.getSharedInstance(mAppContext)
                                     .getSessionManager()
                                     .getCurrentCastSession();
mRemoteMediaClient = castSession.getRemoteMediaClient();
mRemoteMediaClientListener = new CastMediaClientListener();

En lugar de las CCL:

VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);

Ahora, usa CAF:

mRemoteMediaClient.addListener(mRemoteMediaClientListener);

Se puede registrar cualquier cantidad de objetos de escucha con el RemoteMediaClient, que permite que múltiples componentes de remitente compartan una sola instancia de RemoteMediaClient asociada con la sesión.

VideoCastManager de CCL proporciona métodos para controlar la reproducción de contenido multimedia:

VideoCastManager manager = VideoCastManager.getInstance();
if (manager.isRemoteMediaLoaded()) {
    manager.pause();
    mCurrentPosition = (int) manager.getCurrentMediaPosition();
}

RemoteMediaClient ahora las implementa en CAF:

if (mRemoteMediaClient.hasMediaSession()) {
    mRemoteMediaClient.pause();
    mCurrentPosition = 
        (int)mRemoteMediaClient.getApproximateStreamPosition();
}

En CAF, todas las solicitudes de contenido multimedia emitidas en RemoteMediaClient muestran un RemoteMediaClient.MediaChannelResult mediante una devolución de llamada de PendingResult que puede usarse para hacer un seguimiento del progreso y el resultado final de la solicitud.

Tanto CCL como CAF usan las clases MediaInfo y MediaMetadata para representar elementos multimedia y cargar contenido multimedia.

Para cargar contenido multimedia en CCL, se usa VideoCastManager:

VideoCastManager.getInstance().loadMedia(media, autoPlay, mCurrentPosition, customData);

En CAF, se usa RemoteMediaClient para cargar los medios:

mRemoteMediaClient.load(media, autoPlay, mCurrentPosition, customData);

Para obtener la información y el estado de Media de una sesión multimedia actual en la CCL usa VideoCastManager:

MediaInfo mediaInfo = VideoCastManager.getInstance()
                                      .getRemoteMediaInformation();
int status = VideoCastManager.getInstance().getPlaybackStatus();
int idleReason = VideoCastManager.getInstance().getIdleReason();

En CAF, usa RemoteMediaClient para obtener la misma información:

MediaInfo mediaInfo = mRemoteMediaClient.getMediaInfo();
int status = mRemoteMediaClient.getPlayerState();
int idleReason = mRemoteMediaClient.getIdleReason();

Superposición introductoria

Al igual que CCL, CAF proporciona una vista personalizada IntroductoryOverlay para destacar. el botón para transmitir cuando se muestre por primera vez a los usuarios.

En lugar de usar el método VideoCastConsumer onCastAvailabilityChanged de CCL Para saber cuándo mostrar la superposición, declara un CastStateListener para determinar cuando el botón para transmitir se vuelva visible una vez que se detecten dispositivos de transmisión en la red local por el MediaRouter:

private IntroductoryOverlay mIntroductoryOverlay;
private MenuItem mMediaRouteMenuItem;

protected void onCreate(Bundle savedInstanceState) {
    ...
    mCastStateListener = new CastStateListener() {
        @Override
        public void onCastStateChanged(int newState) {
            if (newState != CastState.NO_DEVICES_AVAILABLE) {
                showIntroductoryOverlay();
            }
        }
    };
    mCastContext = CastContext.getSharedInstance(this);
    mCastContext.registerLifecycleCallbacksBeforeIceCreamSandwich(this, 
        savedInstanceState);
}

protected void onResume() {
    mCastContext.addCastStateListener(mCastStateListener);
    ...
}

protected void onPause() {
    mCastContext.removeCastStateListener(mCastStateListener);
    ...
}

Realiza un seguimiento de la instancia MediaRouteMenuItem:

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

Verifica si el elemento MediaRouteButton es visible para que la superposición introductoria se pueden mostrar:

private void showIntroductoryOverlay() {
    if (mIntroductoryOverlay != null) {
        mIntroductoryOverlay.remove();
    }
    if ((mMediaRouteMenuItem != null) && mMediaRouteMenuItem.isVisible()) {
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                mIntroductoryOverlay = new IntroductoryOverlay.Builder(
                        VideoBrowserActivity.this, mMediaRouteMenuItem)
                        .setTitleText(getString(R.string.introducing_cast))
                        .setOverlayColor(R.color.primary)
                        .setSingleTime()
                        .setOnOverlayDismissedListener(
                                new IntroductoryOverlay
                                    .OnOverlayDismissedListener() {
                                        @Override
                                        public void onOverlayDismissed() {
                                            mIntroductoryOverlay = null;
                                        }
                                })
                        .build();
                mIntroductoryOverlay.show();
            }
        });
    }
}

Consulta nuestra app de ejemplo para ver el código funcional completo para mostrar la superposición introductoria.

Para personalizar el estilo de la superposición introductoria, sigue el procedimiento Cómo personalizar la superposición introductoria

Minicontrolador

En lugar de MiniController de CCL, usa MiniControllerFragment de CAF en tu archivo de diseño de app de las actividades en las que quieres mostrar la mini responsable del tratamiento de datos:

<fragment
        android:id="@+id/cast_mini_controller"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        app:castShowImageThumbnail="true"
        android:visibility="gone"
        class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment" />

CAF no admite la configuración manual compatible con MiniController de CCL Tampoco es compatible con la función Autoplay.

Para personalizar el estilo y los botones del minicontrol, sigue las procedimiento Personalizar el minicontrol.

Notificaciones y pantalla de bloqueo

Al igual que VideoCastNotificationService de CCL, CAF proporciona un MediaNotificationService para administrar la visualización de las notificaciones multimedia durante la transmisión.

Debes quitar lo siguiente de tu manifiesto:

  • VideoIntentReceiver
  • VideoCastNotificationService

CCL admite proporcionar un servicio de notificación personalizado con el CastConfiguration.Builder; que no es compatible con CAF.

Considera la siguiente inicialización de CastManager mediante CCL:

VideoCastManager.initialize(
   getApplicationContext(),
   new CastConfiguration.Builder(
           context.getString(R.string.app_id))
       .addNotificationAction(
           CastConfiguration.NOTIFICATION_ACTION_PLAY_PAUSE,true)
       .addNotificationAction(
           CastConfiguration.NOTIFICATION_ACTION_DISCONNECT,true)
       .build());

Para la configuración equivalente en CAF, el SDK proporciona una NotificationsOptions.Builder para ayudarte a crear controles multimedia para la y la pantalla de bloqueo para acceder a la app emisora. La notificación y el bloqueo los controles de pantalla pueden habilitarse con CastOptions al inicializar la CastContext

public CastOptions getCastOptions(Context context) {
    NotificationOptions notificationOptions = 
        new NotificationOptions.Builder()
            .setActions(Arrays.asList(
                MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK,
                MediaIntentReceiver.ACTION_STOP_CASTING), new int[]{0, 1})
            .build();
    CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
             .setNotificationOptions(notificationOptions)
             .build();
    return new CastOptions.Builder()
             .setReceiverApplicationId(context.getString(R.string.app_id))
             .setCastMediaOptions(mediaOptions)
             .build();
}

Las notificaciones y los controles de la pantalla de bloqueo siempre están habilitados en CAF. Además, ten en cuenta que los botones para reproducir/pausar y detener la transmisión se incluyen de forma predeterminada. CAF hará un seguimiento automático de la visibilidad de las actividades para decidir cuándo mostrar la notificación multimedia, excepto Gingerbread. (Para Gingerbread, consulta la nota anterior sobre usando registerLifecycleCallbacksBeforeIceCreamSandwich(); CCL VideoCastManager llamadas a incrementUiCounter y decrementUiCounter se debe quitar).

Para personalizar los botones que se muestran en las notificaciones, sigue las procedimiento Agrega controles multimedia a las notificaciones y a la pantalla de bloqueo.

Control expandido

CCL proporciona VideoCastControllerActivity y VideoCastControllerFragment para mostrar un control expandido cuando se transmite contenido multimedia.

Puedes quitar la declaración VideoCastControllerActivity en el manifiesto.

En CAF, debes Extiende ExpandedControllerActivity y agrega el botón para transmitir.

Para personalizar los estilos y botones que se muestran en el responsable del tratamiento de datos, sigue el procedimiento Personaliza el control expandido.

Enfoque de audio

Al igual que con CCL, el foco de audio se administra automáticamente.

Control de volumen

Para Gingerbread, se requiere dispatchKeyEvent como para CCL. En ICS y versiones posteriores para el control de volumen de CCL y CAF.

CAF permite controlar el volumen de la transmisión con el botón de volumen forzado en la teléfono dentro de las actividades de la aplicación y muestra una barra de volumen visual cuando transmitir en versiones compatibles. CAF también se encarga de los cambios de volumen volumen intenso, incluso si la app no está al frente, está bloqueada o incluso si la pantalla está desactivado.

Subtítulos

En Android KitKat y versiones posteriores, puedes usar subtítulos para personalizar los subtítulos. Configuración, en Configuración > Accesibilidad. Las versiones anteriores de Android, pero no tienen esta capacidad. CCL se encarga de esto proporcionando configuración de versiones anteriores y delegación de la configuración del sistema en KitKat y superiores.

CAF no ofrece una configuración personalizada para cambiar las preferencias de subtítulos. Tú Debes quitar las referencias a CaptionsPreferenceActivity en tu manifiesto y tus preferencias XML.

Ya no se necesita TracksChooserDialog de CCL porque se cambió la opción de cierre las pistas de subtítulos se controlan mediante la IU del controlador expandido.

La API de subtítulos opcionales en CAF es similar a v2.

Registro de depuración

CAF no proporciona la configuración de registro de depuración.

Varios

Las siguientes funciones de CCL no son compatibles con CAF:

  • Obtención de autorización antes de la reproducción proporcionando un MediaAuthService
  • Mensajes configurables de la IU

Apps de ejemplo

Consulta las diferencias para migrar nuestra app de ejemplo Universal Music Player para Android (uamp) de CCL a CAF.

También tenemos instructivos de codelabs y apps de ejemplo que usan CAF.