Przenoszenie aplikacji CCL Sender do aplikacji Cast Cast Framework (CAF)

Wykonując opisane poniżej czynności, możesz przekonwertować aplikację nadawcy na Androida z pakietu SDK SDK w wersji 2 oraz pliku CCL na CAF. Wszystkie funkcje listy kontroli dostępu zostały wdrożone w CAF, więc po migracji nie trzeba już używać tej listy.

Pakiet SDK przesyłającego Cast CAF używa CastContext do zarządzania GoogleAPIClient w Twoim imieniu. CastContext zarządza cyklami życia, błędami i wywołaniami zwrotnymi, co znacznie upraszcza tworzenie aplikacji Cast.

Wprowadzenie

  • Na projekt nadawcy CAF wpływ miał biblioteka towarzysząca Cast, więc migracja z listy CCL do nadawcy CAF obejmuje głównie mapowanie klas jeden do jednego oraz ich metod.
  • Narzędzie do wysyłania wiadomości CAF jest nadal rozpowszechniane w ramach Usług Google Play za pomocą menedżera Android SDK.
  • Nowe pakiety (com.google.android.gms.cast.framework.*), które zostały dodane do nadawcy CAF, z funkcją podobną do CCL, przejmują odpowiedzialność za zgodność z listą kontrolną Google Cast.
  • Nadawca CAF udostępnia widżety zgodne z wymaganiami Cast UX. Widżety te są podobne do tych dostarczanych przez CCL.
  • Funkcja CAF Sender zapewnia asynchroniczne wywołania zwrotne podobne do CCL w celu śledzenia stanów i uzyskiwania danych. W przeciwieństwie do CCL Sender CAF nie udostępnia żadnych implementacji różnego typu różnych metod interfejsu.

W kolejnych sekcjach skupimy się głównie na aplikacjach skoncentrowanych na filmach opartych na narzędziu VideoCastManager, ale w wielu przypadkach te same pojęcia odnoszą się również do DataCastManagera.

Zależności

CCL i CAF mają te same zależności w bibliotece pomocy AppCompat, bibliotece pomocy MediaRouter w wersji 7 i usługach Google Play. Różnica polega na tym, że CAF zależy od nowej platformy przesyłania dostępnej w Usługach Google Play w wersji 9.2.0 lub nowszej.

W pliku build.gradle usuń zależności w elementach com.google.android.gms:play-services-cast i com.google.android.libraries.cast.companionlibrary:ccl, a potem dodaj nową platformę przesyłania:

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

Możesz też usunąć metadane usługi Google Play:

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

Wszystkie usługi, działania i zasoby, które są częścią CAF, są automatycznie scalane z plikiem manifestu aplikacji i zasobami.

Minimalna wersja pakietu Android SDK obsługiwana przez CAF to 9 (Gingerbread). Minimalna wersja pakietu CCL Androida to 10.

Lista CCL pozwala łatwo sprawdzić, czy na urządzeniu jest dostępna zgodna wersja Usług Google Play. BaseCastManager.checkGooglePlayServices(activity) CAF nie udostępnia tego w ramach pakietu Cast. Wykonaj procedurę sprawdź, czy na urządzeniach użytkowników jest zainstalowany pakiet APK usług Google Play, aby upewnić się, że na urządzeniu użytkownika jest zainstalowany prawidłowy plik APK Usług Google Play, ponieważ aktualizacje mogą nie docierać natychmiast do wszystkich użytkowników.

Nadal musisz używać wariantu Theme.AppCompat dla motywu aplikacji.

Zdarzenie inicjujące

W przypadku listy CCL metodę VideoCastManager.initialize() trzeba wywołać w metodzie onCreate() instancji Application. Ta logika powinna zostać usunięta z kodu klasy aplikacji.

W CAF wymagany jest też jawny etap inicjowania platformy przesyłania. Wymaga to zainicjowania singletonu CastContext za pomocą odpowiedniego atrybutu OptionsProvider do określenia identyfikatora aplikacji odbiornika oraz innych opcji globalnych. CastContext pełni funkcję podobną do VideoCastManagerCCL, ponieważ zapewnia pojedynczy węzeł, z którym klienci wchodzą w interakcje. OptionsProvider jest podobny do CastConfiguration w CCL, co umożliwia skonfigurowanie funkcji platformy Cast.

Jeśli Twoja obecna lista kontroli dostępu (CastConfiguration.Builder) wygląda tak:

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

Następnie w CAF następujący ciąg CastOptionsProvider za pomocą CastOptions.Builder będzie podobny:

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

Zapoznaj się z naszą przykładową aplikacją, aby uzyskać pełną implementację opcji OptionProvider.

Zadeklaruj opcje OptionProvider w elemencie „application” w pliku 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>

Leniwie zainicjuj metodę CastContext w metodzie onCreate Activity (a nie w instancji Application):

private CastContext mCastContext;

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

    mCastContext = CastContext.getSharedInstance(this);
}

Aby uzyskać dostęp do tonu pojedynczego typu CastContext:

mCastContext = CastContext.getSharedInstance(this);

Wykrywanie urządzeń

Należy usunąć atrybuty VideoCastManager incrementUiCounter i decrementUiCounter listy CCL z metod onResume i onPause instancji Activities.

W CAF proces wykrywania jest uruchamiany i zatrzymywany automatycznie przez ramkę, gdy aplikacja działa na pierwszym planie i odpowiednio działa w tle.

Przycisk Cast i okno przesyłania

Podobnie jak w przypadku listy CCL, te komponenty są dostarczane przez bibliotekę pomocy MediaRouter w wersji 7.

Przycisk Cast jest wciąż zaimplementowany przez element MediaRouteButton i można go dodać do aktywności (przy użyciu ActionBar lub Toolbar) jako element menu.

Deklaracja MediaRouteActionProvider w menu xml jest taka sama jak w przypadku 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"/>

Podobnie jak w przypadku CCL, zmień metodę metody onCreateOptionMenu() w każdej aktywności, ale zamiast korzystać z CastCast.addMediaRouterButton, za pomocą metody CastFFactor użyj przycisku CAF, by podłączyć klucz MediaRouteButton do platformy przesyłania:

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

Sterowanie urządzeniem

Podobnie jak w przypadku CCL, w CAF sterowanie urządzeniami odbywa się w większości przez platformę. Aplikacja nadawcy nie musi (i nie powinna przeprowadzać) obsługi połączenia z urządzeniem i uruchamiania aplikacji odbiornika za pomocą GoogleApiClient.

Interakcja między nadawcą i odbiorcą jest teraz reprezentowana jako „sesja”. Klasa SessionManager obsługuje cykl życia sesji i automatycznie rozpoczyna i zatrzymuje sesje w odpowiedzi na gesty użytkownika. Sesja zaczyna się, gdy użytkownik wybierze urządzenie przesyłające w oknie Cast, a kończy się, gdy użytkownik kliknie przycisk „Zatrzymaj przesyłanie” w oknie przesyłania lub po zakończeniu działania aplikacji nadawcy.

Aby śledzić stan sesji przesyłania w CLCL, musisz rozszerzyć klasę VideoCastConsumerImpl:

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

W CAF aplikacja wysyłająca może otrzymywać powiadomienia o zdarzeniach cyklu życia sesji, rejestrując SessionManagerListener za pomocą SessionManager. Wywołania zwrotne SessionManagerListener definiują metody wywołania zwrotnego dla wszystkich zdarzeń cyklu życia sesji.

Te metody SessionManagerListener są zmapowane z interfejsu VideoCastConsumer interfejsu CCL:

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

Zadeklaruj klasę, która implementuje interfejs SessionManagerListener, i przenieś logikę VideoCastConsumerImpl do metod dopasowania:

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

Klasa CastSession reprezentuje sesję z urządzeniem przesyłającym. Klasa ma metody do kontrolowania głośności urządzenia i stanów wyciszenia, które CCL wykonuje w BaseCastManager.

Zamiast dodawać klienta za pomocą listy CCL VideoCastManager:

VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);

Teraz zarejestruj urządzenie SessionManagerListener:

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

Aby przestać nasłuchiwać zdarzeń w CLCL:

VideoCastManager.getInstance().removeVideoCastConsumer(mCastConsumer);

Za pomocą SessionManager możesz przestać nasłuchiwać zdarzeń w sesji:

mCastSessionManager.removeSessionManagerListener(mCastSessionManagerListener,
                    CastSession.class);

Aby wyraźnie odłączyć urządzenie przesyłające, użyto listy CCL:

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

W przypadku CAF użyj SessionManager:

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

Aby sprawdzić, czy nadawca jest połączony z odbiornikiem, lista CCL udostępnia VideoCastManager.getInstance().isConnected(), ale w CAF użyj SessionManager:

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

W CAF powiadomienia o zmianie stanu głośności/wyciszenia są nadal dostarczane za pomocą metod wywołania zwrotnego w Cast.Listener. Te detektory są zarejestrowane w CastSession. Wszystkie pozostałe powiadomienia o stanie urządzenia są obsługiwane przez wywołania zwrotne CastStateListener. Te odbiorniki są zarejestrowane w CastSession. Pamiętaj, aby wyrejestrować urządzenie, gdy powiązane z nim fragmenty, aktywności lub aplikacje zaczną działać w tle.

Logika ponownego połączenia

CAF próbuje ponownie nawiązać połączenia sieciowe utracone z powodu tymczasowej utraty sygnału Wi-Fi lub innych błędów sieci. Odbywa się to na poziomie sesji. Po utracie połączenia stan połączenia może zostać „zawieszony”, a po przywróceniu połączenia urządzenie przejdzie z powrotem do stanu „Połączono”. W ramach tego procesu platforma nawiąże ponownie połączenie z aplikacją odbiornika i kanały.

CAF ma własną usługę ponownego łączenia, możesz więc usunąć listę CCL ReconnectionService z pliku manifestu:

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

Nie potrzebujesz tych uprawnień w pliku manifestu dla logiki połączenia:

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

Usługa ponownego połączenia CAF jest domyślnie włączona, ale można ją wyłączyć za pomocą CastOptions.

Ponadto CAF dodaje też automatyczne wznawianie sesji, które jest domyślnie włączone (i można je dezaktywować za pomocą CastOptions). Jeśli aplikacja nadawcy jest wysyłana w tle lub zatrzymana (przesunięta poza ekran lub z powodu awarii) podczas trwania sesji przesyłania, platforma spróbuje wznowić tę sesję, gdy aplikacja nadawcy powróci na pierwszy plan lub zostanie ponownie uruchomiona. Ta operacja jest wywoływana automatycznie przez wywołanie SessionManager, które wywołuje zdarzenie.

Rejestracja kanału niestandardowego

Lista CCL umożliwia utworzenie niestandardowego kanału wiadomości do odbiorcy:

  • Pole CastConfiguration pozwala określić wiele przestrzeni nazw, a lista CCL spowoduje utworzenie kanału za Ciebie.
  • DataCastManager jest podobny do VideoCastManager, ale skupia się na przypadkach użycia innych niż media.

Żaden z tych sposobów tworzenia kanału niestandardowego nie jest obsługiwany przez CAF – musisz zamiast tego wykonać procedurę dodawania kanału niestandardowego dla aplikacji nadawcy.

Podobnie jak w przypadku CCL w przypadku aplikacji do obsługi multimediów, nie trzeba rejestrować kanału kontroli mediów.

Sterowanie multimediami

W CAF klasa RemoteMediaClient jest odpowiednikiem metod multimedialnych VideoCastManager. RemoteMediaClient.Listener jest odpowiednikiem metod VideoCastConsumer. W szczególności metody onRemoteMediaPlayerMetadataUpdated i onRemoteMediaPlayerStatusUpdated VideoCastConsumer są mapowane odpowiednio na metody onMetadataUpdated i onStatusUpdated obiektu 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() {
    }
}

Nie trzeba inicjować ani rejestrować obiektu RemoteMediaClient. Platforma automatycznie utworzy wystąpienie obiektu i zarejestruje bazowy kanał multimediów w momencie rozpoczęcia sesji, jeśli aplikacja odbiornika obsługująca przestrzeń nazw multimediów.

RemoteMediaClient jest dostępny jako metoda getRemoteMediaClient obiektu CastSession.

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

Zamiast listy CCL:

VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);

Teraz użyj CAF:

mRemoteMediaClient.addListener(mRemoteMediaClientListener);

W RemoteMediaClient można zarejestrować dowolną liczbę detektorów, co umożliwia wielu komponentom nadawcy udostępnianie pojedynczego wystąpienia RemoteMediaClient powiązanego z sesją.

VideoCastManager CCL udostępnia metody obsługi odtwarzania multimediów:

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

Te elementy są teraz zaimplementowane przez RemoteMediaClient w CAF:

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

W CAF wszystkie żądania mediów wysyłane w RemoteMediaClient zwracają stan RemoteMediaClient.MediaChannelResult za pomocą wywołania zwrotnego PendingResult, które można wykorzystać do śledzenia postępów i ostatecznych wyników żądania.

Zarówno CCL, jak i CAF używają klasy MediaInfo i MediaMetadata do reprezentowania elementów multimedialnych i wczytywania multimediów.

Do wczytywania multimediów na liście kontroli dostępu używany jest plik VideoCastManager:

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

W pliku CAF plik multimedialny RemoteMediaClient jest używany do wczytywania multimediów:

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

Aby uzyskać informacje Media i stan bieżącej sesji multimediów na odbiorniku, CCL używa VideoCastManager:

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

W pliku CAF użyj RemoteMediaClient, aby uzyskać te same informacje:

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

Nakładka z wprowadzeniem

Podobnie jak w przypadku listy CCL, CAF udostępnia widok niestandardowy IntroductoryOverlay do wyróżniania przycisku Cast przy jego pierwszym wyświetlaniu.

Zamiast używać metody VideoCastConsumer onCastAvailabilityChanged w narzędziu CCL do określania, kiedy ma być wyświetlana nakładka, zadeklaruj CastStateListener, aby określić, kiedy przycisk Cast będzie widoczny po wykryciu urządzeń przesyłających w sieci lokalnej przez 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);
    ...
}

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

Sprawdź, czy pole MediaRouteButton jest widoczne, aby można było wyświetlić nakładkę powitalną:

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

Zajrzyj do naszej przykładowej aplikacji, aby zapoznać się z pełnym kodem działania, który pozwala wyświetlać nakładkę powitalną.

Aby dostosować styl nakładki wprowadzającej, wykonaj procedurę dostosowania nakładki wprowadzającej.

Minikontroler

Zamiast MiniController w pliku CCL używaj w pliku układu aplikacji pliku CAF MiniControllerFragment działań, w których chcesz wyświetlać minikontroler:

<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 nie obsługuje konfiguracji ręcznej obsługiwanej przez MiniController listę kontroli dostępu (CCL) ani nie obsługuje funkcji Autoplay.

Aby dostosować styl i przyciski minikontrolera, wykonaj czynności opisane w artykule Dostosowywanie minikontrolera.

Powiadomienie i ekran blokady

Podobnie jak w przypadku CCL VideoCastNotificationService, CAF udostępnia MediaNotificationService do zarządzania wyświetlaniem powiadomień o multimediach podczas przesyłania.

Usuń z pliku manifestu tych elementów:

  • VideoIntentReceiver
  • VideoCastNotificationService

CCL obsługuje niestandardową usługę powiadomień z CastConfiguration.Builder. Nie jest to obsługiwane przez CAF.

Rozważ następujące inicjowanie CastManager przy użyciu 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());

W przypadku równoważnej konfiguracji w CFD pakiet SDK zawiera element NotificationsOptions.Builder, który ułatwia tworzenie elementów sterujących multimediami dla powiadomień i ekranu blokady w aplikacji nadawcy. Ustawienia powiadomień i ekranu blokady można włączyć za pomocą CastOptions podczas inicjowania 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();
}

Powiadomienia i ustawienia ekranu blokady są zawsze włączone w CAF. Pamiętaj też, że domyślnie są dostępne przyciski odtwarzania/wstrzymywania i zatrzymywania przesyłania. CAF automatycznie śledzi widoczność aktywności, aby wybrać, kiedy ma zostać wyświetlone powiadomienie (z wyjątkiem Gingerbread). (Gingerbread, zobacz wcześniejszą notatkę na temat używania registerLifecycleCallbacksBeforeIceCreamSandwich(); wywołań VideoCastManager incrementUiCounter i decrementUiCounter CCL należy usunąć).

Aby dostosować przyciski wyświetlane w powiadomieniach, wykonaj procedurę dodawania opcji sterowania multimediami do ekranu blokady i powiadomień.

Rozwinięty kontroler

Lista CCL udostępnia VideoCastControllerActivity i VideoCastControllerFragment do wyświetlania rozwiniętego kontrolera podczas przesyłania multimediów.

Możesz usunąć deklarację VideoCastControllerActivity w pliku manifestu.

W CAF musisz rozwinąć ExpandedControllerActivity i dodać przycisk Cast.

Aby dostosować style i przyciski wyświetlane w rozwiniętym kontrolerze, wykonaj procedurę dostosowywania kontrolera rozwiniętego.

Aktywność audio

Tak jak w przypadku CCL, dźwięk jest zarządzany automatycznie.

Regulacja głośności

W przypadku wersji Gingerbread dispatchKeyEvent jest wymagany jak w przypadku listy kontroli dostępu (CCL). W ICS i nowszych wersjach sterowanie głośnością CCL i CAF jest obsługiwane automatycznie.

CAF umożliwia sterowanie głośnością za pomocą przycisku głośności na telefonie wewnątrz aktywności w aplikacjach, a także wyświetlanie paska głośności podczas przesyłania w obsługiwanych wersjach. CAF obsługuje też zmienianie głośności w trakcie głośnego odtwarzania, nawet jeśli aplikacja nie jest widoczna z przodu, zablokowana lub nawet przy wyłączonym ekranie.

Napisy

Na urządzeniu z Androidem KitKat lub nowszym napisy można dostosować w Ustawieniach napisów, klikając Ustawienia > Ułatwienia dostępu. Wcześniejsze wersje Androida nie mają takiej możliwości. CCL obsługuje to ustawienie, udostępniając niestandardowe ustawienia wcześniejszych wersji i przekazując ustawienia systemowe do Androida KitKat lub nowszego.

CAF nie ma niestandardowych ustawień do zmiany preferencji napisów. Musisz usunąć odniesienia do CaptionsPreferenceActivity w pliku manifestu i pliku XML ustawień.

Pole TracksChooserDialog w CLCL nie jest już potrzebne, ponieważ zmiana ścieżek napisów jest obsługiwana przez rozwinięty interfejs użytkownika kontrolera.

Interfejs API napisów w CAF jest podobny do wersji 2.

Logowanie debugowania

CAF nie udostępnia ustawień logowania debugowania.

Inne

Poniższe funkcje CCL nie są obsługiwane w CAF:

  • Uzyskanie autoryzacji przed rozpoczęciem odtwarzania: w MediaAuthService
  • Konfigurowalne komunikaty interfejsu

Przykładowe aplikacje

Zapoznaj się z informacjami o różnicy dotyczącej przeniesienia przykładowej aplikacji Universal Music Player na Androida (uamp) z CCL do CAF.

Udostępniamy też samouczki dotyczące ćwiczeń i przykładowe aplikacje, które korzystają z plików CAF.