Esegui la migrazione dell'app mittente CCL al Cast Application Framework (CAF)

La seguente procedura consente di convertire l'app del mittente Android da Cast SDK v2 con CCL a CAF. Tutte le funzionalità di CCL sono state implementate in CAF, quindi non dovrai più utilizzare CCL.

L'SDK Cast CAF Cast utilizza CastContext per gestire il client GoogleAPI per tuo conto. CastContext gestisce cicli di vita, errori e callback per te, semplificando notevolmente lo sviluppo di un'app Cast.

Introduzione

  • Poiché la progettazione del mittente CAF è stata influenzata dalla libreria companion Cast, la migrazione da CCL a Mittente CAF prevede principalmente mappature one-to-one delle classi e dei relativi metodi.
  • Mittente CAF viene comunque distribuito come parte di Google Play Services tramite il gestore SDK Android.
  • I nuovi pacchetti (com.google.android.gms.cast.framework.*) che sono stati aggiunti a Mittente CAF con funzionalità simili a CCL si assumono la responsabilità di rispettare l'elenco di controllo di Google Cast Design.
  • Mittente CAF fornisce widget conformi ai requisiti di trasmissione dell'esperienza utente; questi widget sono simili a quelli forniti da CCL.
  • Mittente CAF fornisce callback asincroni simili a CCL per monitorare gli stati e ottenere dati. A differenza di CCL, il mittente CAF non fornisce alcuna implementazione dei vari metodi dell'interfaccia.

Nelle sezioni seguenti ci concentreremo principalmente sulle applicazioni videocentriche basate su VideoCastManager, ma in molti casi gli stessi concetti si applicano anche a DataCastManager.

Dipendenze

CCL e CAF presentano le stesse dipendenze dalla libreria di supporto AppCompat, dalla libreria di supporto MediaRouter v7 e da Google Play Services. Tuttavia, la differenza è che CAF dipende dal nuovo framework Cast disponibile in Google Play Services 9.2.0 o versioni successive.

Nel file build.gradle, rimuovi le dipendenze da com.google.android.gms:play-services-cast e com.google.android.libraries.cast.companionlibrary:ccl, quindi aggiungi il nuovo framework 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'
}

Puoi anche rimuovere i metadati di Google Play Services:

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

Le attività, i servizi e le risorse che fanno parte del CAF vengono automaticamente uniti al manifest e alle risorse della tua app.

La versione minima dell'SDK Android supportata dal CAF è 9 (Gingerbread); la versione minima dell'SDK CCL è 10.

CCL fornisce un metodo pratico BaseCastManager.checkGooglePlayServices(activity) per verificare che sul dispositivo sia disponibile una versione compatibile di Google Play Services. CAF non lo fornisce come parte dell'SDK Cast. Segui la procedura Assicurati che l'APK di Google Play Services disponga dei dispositivi per assicurarti che sul dispositivo di un utente sia installato l'APK di Google Play Services corretto, perché gli aggiornamenti potrebbero non raggiungere tutti gli utenti immediatamente.

È comunque necessario utilizzare una variante di Theme.AppCompat per il tema dell'applicazione.

Inizializzazione

Per la CCL, VideoCastManager.initialize() doveva essere chiamato nel metodo onCreate() dell'istanza Applications. Questa logica deve essere rimossa dal codice della classe della tua applicazione.

In CAF è necessario anche un passaggio di inizializzazione esplicito per il framework di trasmissione. Questo prevede l'inizializzazione del singleton CastContext, utilizzando un OptionsProvider appropriato per specificare l'ID applicazione del destinatario ed eventuali altre opzioni globali. CastContext svolge un ruolo simile a quello di CCL VideoCastManager fornendo un singleton con cui i clienti interagiscono. OptionsProvider è simile al CastConfiguration di CCL per consentirti di configurare le funzionalità del framework Cast.

Se l'attuale CCL CastConfiguration.Builder ha il seguente aspetto:

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

Quindi in CAF il seguente CastOptionsProvider utilizzando CastOptions.Builder sarebbe simile:

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

Dai un'occhiata alla nostra app di esempio per un'implementazione completa di OptionsProvider.

Dichiara l'elemento OptionsProvider all'interno dell'elemento "application" del file 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>

Inizializza lentamente CastContext nel metodo onCreate di ogni Activity (e non l'istanza Application):

private CastContext mCastContext;

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

    mCastContext = CastContext.getSharedInstance(this);
}

Per accedere al singleton di CastContext, utilizza:

mCastContext = CastContext.getSharedInstance(this);

Rilevamento dispositivi

Le VideoCastManager incrementUiCounter e decrementUiCounter di CCL devono essere rimosse dai metodi onResume e onPause di Activities.

In CAF, il processo di rilevamento viene avviato e interrotto automaticamente dal framework quando l'app viene in primo piano e passa in background, rispettivamente.

Pulsante Trasmetti e finestra di dialogo Trasmetti

Analogamente a CCL, questi componenti sono forniti dalla libreria di supporto MediaRouter v7.

Il pulsante Trasmetti viene comunque implementato da MediaRouteButton e può essere aggiunto alla tua attività (utilizzando ActionBar o Toolbar) come voce del menu.

La dichiarazione di MediaRouteActionProvider nel file XML del menu è la stessa di 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"/>

In modo simile a CCL, sostituisci il metodo onCreateOptionMenu() di ogni attività, ma anziché utilizzare CastManager.addMediaRouterButton, utilizza CastCastFactory di CAF per collegare MediaRouteButton al framework Cast:

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

Controllo dei dispositivi

Analogamente a CCL, in CAF, il controllo dei dispositivi viene gestito in gran parte dal framework. L'applicazione del mittente non ha bisogno di gestire (e non dovrebbe provare a gestire) la connessione al dispositivo e l'avvio dell'applicazione del destinatario utilizzando GoogleApiClient.

L'interazione tra mittente e destinatario è ora rappresentata come una "sessione". La classe SessionManager gestisce il ciclo di vita della sessione e avvia e interrompe automaticamente le sessioni in risposta ai gesti dell'utente: una sessione viene avviata quando l'utente seleziona un dispositivo di trasmissione nella finestra di dialogo Trasmetti e termina quando l'utente tocca il pulsante "Interrompi trasmissione" nella finestra di dialogo Trasmetti o quando l'app mittente stessa termina.

In CCL, devi estendere la classe VideoCastConsumerImpl per monitorare lo stato della sessione di trasmissione:

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

In CAF, l'applicazione del mittente può ricevere una notifica degli eventi del ciclo di vita della sessione registrando un SessionManagerListener con SessionManager. I callback SessionManager listener definiscono i metodi di callback per tutti gli eventi del ciclo di vita della sessione.

I seguenti metodi SessionManagerListener sono mappati dall'interfaccia VideoCastConsumer di CCL:

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

Dichiara una classe che implementa l'interfaccia SessionManagerListener e sposta la logica VideoCastConsumerImpl nei metodi di corrispondenza:

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 classe CastSession rappresenta una sessione con un dispositivo di trasmissione. La classe dispone di metodi per controllare il volume del dispositivo e gli stati di disattivazione, che vengono utilizzati dalla CCL in BaseCastManager.

Anziché utilizzare l'VideoCastManager di CCL per aggiungere un consumatore:

VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);

Ora registra il tuo SessionManagerListener:

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

Per interrompere l'ascolto degli eventi in:

VideoCastManager.getInstance().removeVideoCastConsumer(mCastConsumer);

Ora utilizza SessionManager per interrompere l'ascolto degli eventi di sessione:

mCastSessionManager.removeSessionManagerListener(mCastSessionManagerListener,
                    CastSession.class);

Per disconnetterti esplicitamente dal dispositivo di trasmissione, CCL ha utilizzato:

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

Per il CAF, utilizza SessionManager:

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

Per determinare se il mittente è connesso al ricevitore, CCL fornisce VideoCastManager.getInstance().isConnected(), ma in CAF utilizza il comando SessionManager:

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

In CAF, le notifiche di modifica del volume/disattivazione dello stato vengono comunque inviate tramite metodi di callback in Cast.Listener; questi ascoltatori vengono registrati con CastSession. Tutte le rimanenti notifiche di stato del dispositivo vengono inviate tramite CastStateListener callback; questi ascoltatori vengono registrati con CastSession. Assicurati di annullare la registrazione degli ascoltatori anche quando i frammenti, le attività o le app associate passano in background.

Logica di riconnessione

Il CAF tenta di ristabilire le connessioni di rete perse a causa della temporanea perdita di segnale Wi-Fi o di altri errori di rete. Questa operazione viene eseguita a livello di sessione; una sessione può entrare in uno stato "sospeso" quando la connessione viene persa e viene ripristinata la modalità "connessa" quando viene ripristinata la connettività. Il framework si occupa di riconnettersi all'applicazione del ricevitore e di riconnettere i canali di trasmissione nell'ambito di questo processo.

CAF fornisce il proprio servizio di riconnessione, quindi puoi rimuovere la CCL ReconnectionService dal tuo manifest:

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

Inoltre, non sono necessarie le seguenti autorizzazioni nel manifest per la logica di riconnessione:

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

Il servizio di riconnessione CAF è abilitato per impostazione predefinita, ma può essere disattivato utilizzando CastOptions.

Inoltre, CAF aggiunge anche la ripresa automatica della sessione che è abilitata per impostazione predefinita (e può essere disattivata tramite CastOptions). Se l'applicazione del mittente viene inviata in background o viene terminata (scorrindo verso l'esterno o a causa di un arresto anomalo) mentre è in corso una sessione di trasmissione, il framework tenterà di riprendere la sessione quando l'applicazione del mittente torna in primo piano o viene riavviata; questo viene gestito automaticamente dal SessionManager, che emette il callback appropriato

Registrazione personalizzata del canale

CCL offre due modi per creare un canale di messaggi personalizzato per il destinatario:

  • CastConfiguration ti consente di specificare più spazi dei nomi e CCL creerà quindi il canale per te.
  • DataCastManager è simile a VideoCastManager, ma è incentrato sui casi d'uso non multimediali.

Poiché nessuno dei due metodi per creare un canale personalizzato è supportato dal CAF, devi seguire la procedura Aggiungi un canale personalizzato per l'app del mittente.

Analogamente a CCL, per le applicazioni multimediali non è necessario registrare esplicitamente il canale di controllo.

Controllo dei contenuti multimediali

In CAF, la classe RemoteMediaClient equivale ai metodi multimediali di VideoCastManager. RemoteMediaClient.Listener equivale a metodi VideoCastConsumer. In particolare, i metodi onRemoteMediaPlayerMetadataUpdated e onRemoteMediaPlayerStatusUpdated di VideoCastConsumer vengono mappati rispettivamente ai metodi onMetadataUpdated e onStatusUpdated di RemoteMediaClient.Listener:

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() {
    }
}

Non è necessario inizializzare o registrare esplicitamente l'oggetto RemoteMediaClient; il framework creerà automaticamente l'istanza dell'oggetto e registrerà il canale multimediale sottostante all'inizio della sessione se l'applicazione del destinatario che si connette supporta lo spazio dei nomi dei contenuti multimediali.

RemoteMediaClient è accessibile come metodo getRemoteMediaClient dell'oggetto CastSession.

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

Invece di CCL:

VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);

Ora utilizza CAF:

mRemoteMediaClient.addListener(mRemoteMediaClientListener);

È possibile registrare un numero qualsiasi di ascoltatori con RemoteMediaClient, consentendo a più componenti del mittente di condividere la singola istanza di RemoteMediaClient associata alla sessione.

Il VideoCastManager di CCL fornisce metodi per gestire la riproduzione dei contenuti multimediali:

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

Ora sono implementate da RemoteMediaClient in CAF:

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

In CAF, tutte le richieste multimediali inviate in RemoteMediaClient restituiscono un RemoteMediaClient.MediaChannelResult tramite un callback PendingResult, che può essere utilizzato per monitorare l'avanzamento e l'esito finale della richiesta.

Sia CCL che CAF utilizzano le classi MediaInfo e MediaMetadata per rappresentare gli elementi multimediali e per caricarli.

Per caricare contenuti multimediali in CCL, viene utilizzato l'VideoCastManager:

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

Nel CAF, RemoteMediaClient viene utilizzato per caricare il contenuto multimediale:

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

Per recuperare le informazioni Media e lo stato di una sessione multimediale corrente sul destinatario, CCL utilizza VideoCastManager:

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

Nel CAF, utilizza l'RemoteMediaClient per ottenere le stesse informazioni:

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

Overlay introduttivo

Analogamente a CCL, il CAF fornisce una visualizzazione personalizzata IntroductoryOverlay per evidenziare il pulsante Trasmetti quando viene mostrato per la prima volta agli utenti.

Invece di utilizzare il metodo VideoCastConsumer onCastAvailabilityChanged di CCL per sapere quando visualizzare l'overlay, dichiara CastStateListener per determinare quando il pulsante Trasmetti diventa visibile una volta che i dispositivi di trasmissione vengono rilevati sulla rete locale da 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);
    ...
}

Monitora l'istanza 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;
}

Controlla se è visibile l'elemento MediaRouteButton in modo da poter mostrare l'overlay introduttivo:

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

Dai un'occhiata alla nostra app di esempio per il codice completo per la visualizzazione dell'overlay introduttivo.

Per personalizzare lo stile dell'overlay introduttivo, segui la procedura Personalizza overlay introduttivo.

Mini controller

Invece di MiniController per il CCL, utilizza il MiniControllerFragment del CAF nel file di layout dell'app delle attività in cui vuoi mostrare il mini controller:

<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 non supporta la configurazione manuale supportata da MiniController di CCL e non supporta la funzionalità Autoplay.

Per personalizzare lo stile e i pulsanti del mini controller, segui la procedura Personalizza il controller mini.

Notifica e schermata di blocco

Analogamente al VideoCastNotificationService di CCL, il CAF fornisce un MediaNotificationService per gestire la visualizzazione delle notifiche multimediali durante la trasmissione.

devi rimuovere quanto segue dal manifest:

  • VideoIntentReceiver
  • VideoCastNotificationService

CCL supporta la fornitura di un servizio di notifica personalizzato con il CastConfiguration.Builder, che non è supportato dal CAF.

Considera l'inizializzazione di CastManager utilizzando 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());

Per la configurazione equivalente in CAF, l'SDK fornisce un NotificationsOptions.Builder per aiutarti a creare i controlli multimediali per la notifica e la schermata di blocco nell'app del mittente. I controlli della notifica e della schermata di blocco possono essere attivati con CastOptions durante l'inizializzazione di 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();
}

Le notifiche e i controlli della schermata di blocco vengono sempre attivati in CAF. Inoltre, tieni presente che i pulsanti per riproduzione, pausa e interruzione della trasmissione sono forniti per impostazione predefinita. Il CAF monitora automaticamente la visibilità delle attività per decidere quando visualizzare la notifica multimediale, ad eccezione di Gingerbread. Per Gingerbread, consulta la nota precedente sull'utilizzo di registerLifecycleCallbacksBeforeIceCreamSandwich(); le chiamate VideoCastManager incrementUiCounter e decrementUiCounter di CCL devono essere rimosse.

Per personalizzare i pulsanti visualizzati nelle notifiche, segui la procedura Aggiungi controlli multimediali a notifica e schermata di blocco.

Controller espanso

CCL fornisce a VideoCastControllerActivity e a VideoCastControllerFragment la visualizzazione di un controller espanso durante la trasmissione di contenuti multimediali.

Puoi rimuovere la dichiarazione VideoCastControllerActivity nel file manifest.

Nel CAF, devi estendere l'attività ExpandedControllerActivity e aggiungere il pulsante Trasmetti.

Per personalizzare gli stili e i pulsanti visualizzati nel controller espanso, segui la procedura Personalizza il controller espanso.

Focus audio

Come nel caso di CCL, la messa a fuoco audio viene gestita automaticamente.

Controllo del volume

Per il pan di zenzero, è richiesto dispatchKeyEvent come con la CCL. In ICS e superiori sia per il controllo del volume CCL che per quello CAF viene gestito automaticamente.

CAF consente di controllare il volume di trasmissione tramite il pulsante del volume fisso sul telefono all'interno delle attività delle app, nonché di mostrare una barra del volume visiva quando trasmetti dalle versioni supportate. Il CAF gestisce inoltre la variazione del volume tramite il volume rigido anche se l'app non è davanti, è bloccata o anche con lo schermo disattivato.

Sottotitoli codificati

In Android KitKat e versioni successive, i sottotitoli possono essere personalizzati tramite le impostazioni di Sottotitoli, che si trovano in Impostazioni > Accessibilità. Tuttavia, le versioni precedenti di Android non dispongono di questa funzionalità. CCL gestisce questa situazione fornendo impostazioni personalizzate per le versioni precedenti e delegando le impostazioni di sistema su KitKat e versioni successive.

Il CAF non fornisce impostazioni personalizzate per la modifica delle preferenze dei sottotitoli. Devi rimuovere i riferimenti CaptionsPreferenceActivity nel manifest e le preferenze XML.

La TracksChooserDialog di CCL non è più necessaria perché la modifica delle tracce dei sottotitoli codificati viene gestita dall'interfaccia utente del controller espanso.

L'API per i sottotitoli in CAF è simile alla v2.

Logging del debug

CAF non fornisce impostazioni di logging di debug.

Varie

Le seguenti funzionalità CCL non sono supportate in CAF:

  • Ottenere l'autorizzazione prima della riproduzione fornendo un MediaAuthService
  • Messaggi UI configurabili

Esempi di app

Dai un'occhiata alle diff per la migrazione della nostra app di esempio Universal Music Player per Android (uamp) da CCL a CAF.

Sono disponibili anche tutorial su codelab e app di esempio che utilizzano CAF.