CCL-Absender-App zum Cast Application Framework (CAF) migrieren

Mit dem folgenden Verfahren kannst du deine Android-Sender-App von Cast SDK v2 mit CCL in CAF umwandeln. Alle Funktionen von CCL wurden in CAF implementiert. Nach der Migration müssen Sie CCL nicht mehr verwenden.

Das Cast CAF Sender SDK verwendet CastContext, um den GoogleAPIClient in Ihrem Namen zu verwalten. CastContext verwaltet Lebenszyklus, Fehler und Callbacks für Sie, was die Entwicklung einer Cast-Anwendung stark vereinfacht.

Einführung

  • Da das CAF-Senderdesign von der Cast Companion Library beeinflusst wurde, umfasst die Migration von CCL zum CAF-Sender hauptsächlich 1:1-Zuordnungen von Klassen und ihren Methoden.
  • Der CAF-Sender wird weiterhin über den Android SDK Manager als Teil der Google Play-Dienste vertrieben.
  • Neue Pakete (com.google.android.gms.cast.framework.*), die dem CAF-Sender hinzugefügt wurden und ähnliche Funktionen wie CCL haben, sind für die Einhaltung der Checkliste für das Google Cast-Design verantwortlich.
  • Der CAF-Sender stellt Widgets bereit, die den UX-Anforderungen von Cast entsprechen. Diese Widgets ähneln den von CCL bereitgestellten Widgets.
  • Der CAF-Absender bietet asynchrone Callbacks, die CCL ähneln, um Statuswerte zu verfolgen und Daten abzurufen. Im Gegensatz zu CCL bietet CAF Sender keine managementfreien Implementierungen der verschiedenen Schnittstellenmethoden.

In den folgenden Abschnitten konzentrieren wir uns hauptsächlich auf die videozentrierten Anwendungen, die auf dem VideoCastManager von CCL basieren. In vielen Fällen gelten die gleichen Konzepte aber auch für DataCastManager.

Abhängigkeiten

CCL und CAF haben dieselben Abhängigkeiten von der AppCompat-Supportbibliothek, der MediaRouter v7-Supportbibliothek und den Google Play-Diensten. Der Unterschied besteht jedoch darin, dass CAF vom neuen Cast-Framework abhängt, das in den Google Play-Diensten 9.2.0 oder höher verfügbar ist.

Entfernen Sie in der build.gradle-Datei die Abhängigkeiten für com.google.android.gms:play-services-cast und com.google.android.libraries.cast.companionlibrary:ccl und fügen Sie dann das neue Cast-Framework hinzu:

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

Sie können auch die Metadaten des Google Play-Dienstes entfernen:

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

Alle Dienste, Aktivitäten und Ressourcen, die Teil von CAF sind, werden automatisch mit dem Manifest und den Ressourcen Ihrer App zusammengeführt.

Die mindestens von SDKF unterstützte Android SDK-Version ist 9 (Gingerbread). Die mindestens erforderliche SDK-Version von CCL ist 10.

CCL bietet die praktische Methode BaseCastManager.checkGooglePlayServices(activity), um zu prüfen, ob eine kompatible Version der Google Play-Dienste auf dem Gerät verfügbar ist. CAF stellt dies nicht als Teil des Cast SDK zur Verfügung. Folgen Sie der Anleitung Sicherstellen, dass Geräte das APK für die Google Play-Dienste haben, damit das richtige APK für Google Play-Dienste auf dem Gerät eines Nutzers installiert wird, da Updates möglicherweise nicht sofort alle Nutzer erreichen.

Sie müssen trotzdem eine Variante von „Theme.AppCompat“ für das Anwendungsdesign verwenden.

Initialisierung

Für CCL musste VideoCastManager.initialize() in der Methode onCreate() der Anwendungsinstanz aufgerufen werden. Diese Logik sollte aus Ihrem Anwendungsklassencode entfernt werden.

In CAF ist auch für das Cast-Framework ein expliziter Initialisierungsschritt erforderlich. Dazu muss das Singleton CastContext initialisiert werden. Dazu wird eine Empfänger-ID und weitere globale Optionen mit einem geeigneten OptionsProvider angegeben. Die CastContext spielt eine ähnliche Rolle wie die VideoCastManager des CCL, indem er einen Singleton bereitstellt, mit dem Clients interagieren. Die OptionsProvider ähnelt der CastConfiguration von CCL, damit Sie die Funktionen des Cast-Frameworks konfigurieren können.

Wenn Ihr aktueller CCL CastConfiguration.Builder so aussieht:

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

In CAF würde dann CastOptionsProvider mit CastOptions.Builder ähnlich aussehen:

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

Eine vollständige Implementierung von OptionsProvider finden Sie in unserer Beispiel-App.

Deklarieren Sie OptionsOptions im Element „application“ der AndroidManifest.xml-Datei:

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

Initialisieren Sie CastContext in der onCreate-Methode jeder Activity (und nicht in der Instanz Application):

private CastContext mCastContext;

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

    mCastContext = CastContext.getSharedInstance(this);
}

Verwenden Sie Folgendes, um auf den Singleton CastContext zuzugreifen:

mCastContext = CastContext.getSharedInstance(this);

Geräteerkennung

VideoCastManager incrementUiCounter und decrementUiCounter der CCL sollten aus den Methoden onResume und onPause von Activities entfernt werden.

In CAF wird der Erkennungsprozess automatisch vom Framework gestartet und beendet, wenn die Anwendung in den Vordergrund gelangt bzw. in den Hintergrund wechselt.

Cast-Symbol und Streaming-Dialogfeld

Wie bei CCL werden diese Komponenten von der Supportbibliothek von MediaRouter Version 7 bereitgestellt.

Das Cast-Symbol wird weiterhin von MediaRouteButton implementiert und kann über das ActionBar oder Toolbar als Menüelement in deine Aktivität aufgenommen werden.

Die Deklaration von MediaRouteActionProvider in der Menü-XML ist mit CCL identisch:

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

Ähnlich wie bei CCL können Sie für jede Aktivität die Methode onCreateOptionMenu() überschreiben, statt CastCast.addMediaRouterButton von CAF zu verwenden, sondern die CastButtonFactory von CAF zu verwenden, um MediaRouteButton mit dem Cast-Framework zu verbinden:

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

Gerätesteuerung

Ähnlich wie in CCL wird die Gerätesteuerung in CAF weitgehend vom Framework übernommen. Die Absenderanwendung muss die Verbindung zum Gerät nicht selbst verarbeiten und sollte auch nicht versuchen, die Empfängeranwendung über GoogleApiClient zu starten.

Die Interaktion zwischen Absender und Empfänger wird nun als „Sitzung“ dargestellt. Die Klasse SessionManager verarbeitet den Sitzungslebenszyklus und startet und beendet Sitzungen automatisch als Reaktion auf Nutzergesten: Eine Sitzung wird gestartet, wenn der Nutzer ein Cast-Gerät im Cast-Dialogfeld auswählt und beendet wird, wenn der Nutzer im Streaming-Dialogfeld auf die Schaltfläche „Streaming beenden“ tippt oder wenn die Absender-App selbst beendet wird.

In der CCL müssen Sie die Klasse VideoCastConsumerImpl erweitern, um den Status der Streamingsitzung zu verfolgen:

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 kann die Absenderanwendung über Sitzungslebenszyklusereignisse benachrichtigt werden, indem eine SessionManagerListener bei SessionManager registriert wird. Die SessionManagerListener-Callbacks definieren Callback-Methoden für alle Sitzungslebenszyklusereignisse.

Die folgenden SessionManagerListener-Methoden werden über die CCL-Schnittstelle VideoCastConsumer zugeordnet:

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

Deklarieren Sie eine Klasse, in der die SessionManagerListener-Schnittstelle implementiert wird, und verschieben Sie die VideoCastConsumerImpl-Logik in die Abgleichmethoden:

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

Die Klasse CastSession stellt eine Sitzung mit einem Übertragungsgerät dar. Die Klasse hat Methoden zum Steuern der Lautstärke des Geräts und der Stummschaltungen, was CCL in BaseCastManager tut.

Anstatt den CCL VideoCastManager zum Hinzufügen eines Nutzers zu verwenden:

VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);

Registrieren Sie jetzt Ihr SessionManagerListener:

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

So beenden Sie die Überwachung von Ereignissen in CCL:

VideoCastManager.getInstance().removeVideoCastConsumer(mCastConsumer);

Beenden Sie jetzt mit SessionManager das Überwachen von Sitzungsereignissen:

mCastSessionManager.removeSessionManagerListener(mCastSessionManagerListener,
                    CastSession.class);

Wenn die Verbindung zum Übertragungsgerät explizit getrennt werden soll, hat CCL Folgendes verwendet:

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

Für CAF verwenden Sie SessionManager:

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

Um festzustellen, ob der Absender mit dem Empfänger verbunden ist, stellt CCL VideoCastManager.getInstance().isConnected() bereit, aber in CAF verwenden Sie SessionManager:

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

In CAF werden Benachrichtigungen über Statusänderungen/Lautschaltungen weiterhin über Callback-Methoden in Cast.Listener gesendet. Diese Listener sind bei CastSession registriert. Alle verbleibenden Gerätestatusbenachrichtigungen werden über CastStateListener-Callbacks gesendet. Diese Listener sind bei CastSession registriert. Achten Sie darauf, dass Sie die Registrierung von Listenern aufheben, wenn die zugehörigen Fragmente, Aktivitäten oder Apps im Hintergrund ausgeführt werden.

Logik für die erneute Verbindung

CAF versucht, Netzwerkverbindungen wiederherzustellen, die aufgrund eines vorübergehenden WLAN-Signalverlustes oder anderer Netzwerkfehler unterbrochen wurden. Dies erfolgt jetzt auf Sitzungsebene. Eine Sitzung kann in den unterbrochenen Zustand versetzt werden, wenn die Verbindung wiederhergestellt ist. Das Framework sorgt dafür, dass die Verbindung zur Empfängeranwendung und dann wieder zu allen Cast-Kanälen wiederhergestellt wird.

CAF bietet einen eigenen Verbindungsdienst, mit dem Sie die CCL ReconnectionService aus Ihrem Manifest entfernen können:

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

Außerdem benötigen Sie die folgenden Berechtigungen in Ihrem Manifest für die Verbindungslogik:

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

Der CAF-Neuverbindungsdienst ist standardmäßig aktiviert, kann aber mithilfe von CastOptions deaktiviert werden.

Darüber hinaus fügt CAF die automatische Sitzungswiederaufnahme hinzu. Diese ist standardmäßig aktiviert und kann über CastOptions deaktiviert werden. Wenn die Absenderanwendung im Hintergrund gesendet oder beendet wird (durch Wischen oder aufgrund eines Absturzes), versucht das Framework, diese Sitzung fortzusetzen, wenn die Absenderanwendung in den Vordergrund zurückkehrt oder neu gestartet wird. Dies wird automatisch von der SessionManager ausgeführt, die den registrierten Callback ausgibt.

Benutzerdefinierte Kanalregistrierung

CCL bietet zwei Möglichkeiten zum Erstellen eines benutzerdefinierten Nachrichtenkanals für den Empfänger:

  • Mit CastConfiguration können Sie mehrere Namespaces angeben. Der CCL erstellt dann den Kanal für Sie.
  • DataCastManager ähnelt VideoCastManager, ist jedoch auf Anwendungsfälle außerhalb der Medienbranche ausgerichtet.

Keine dieser Möglichkeiten zum Erstellen eines benutzerdefinierten Kanals wird von CAF unterstützt. Folgen Sie stattdessen der Anleitung Benutzerdefinierten Kanal hinzufügen für Ihre Absenderanwendung.

Ähnlich wie bei CCL ist es bei Medienanwendungen nicht erforderlich, den Medienkontrollkanal explizit zu registrieren.

Mediensteuerung

In CAF entspricht die Klasse RemoteMediaClient den Medienmethoden VideoCastManager. RemoteMediaClient.Listener entspricht VideoCastConsumer-Methoden. Insbesondere entsprechen die Methoden onRemoteMediaPlayerMetadataUpdated und onRemoteMediaPlayerStatusUpdated von VideoCastConsumer den Methoden onMetadataUpdated und onStatusUpdated von 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() {
    }
}

Das Objekt RemoteMediaClient muss nicht explizit initialisiert oder registriert werden. Das Framework instanziiert das Objekt automatisch und registriert den zugrunde liegenden Medienkanal zum Zeitpunkt des Sitzungsbeginns, wenn die Empfängeranwendung, mit der eine Verbindung besteht, den Medien-Namespace unterstützt.

Auf RemoteMediaClient kann als getRemoteMediaClient-Methode des CastSession-Objekts zugegriffen werden.

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

Anstelle von CCLs:

VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);

Verwenden Sie jetzt CAF:

mRemoteMediaClient.addListener(mRemoteMediaClientListener);

Bei RemoteMediaClient kann eine beliebige Anzahl von Listenern registriert werden. Dadurch können mehrere Absenderkomponenten die einzelne Instanz von RemoteMediaClient teilen, die mit der Sitzung verknüpft ist.

VideoCastManager von CCL bietet Methoden zur Verarbeitung der Medienwiedergabe:

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

Diese werden jetzt von RemoteMediaClient in CAF implementiert:

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

In CAF geben alle am RemoteMediaClient ausgegebenen Medienanfragen einen RemoteMediaClient.MediaChannelResult über einen PendingResult-Callback zurück, mit dem der Fortschritt und das endgültige Ergebnis der Anfrage verfolgt werden können.

Sowohl CCL als auch CAF verwenden die Klassen MediaInfo und MediaMetadata, um Medienelemente darzustellen und Medien zu laden.

Zum Laden von Medien in CCL wird VideoCastManager verwendet:

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

In CAF wird RemoteMediaClient zum Laden der Medien verwendet:

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

Um die Media-Informationen und den Status einer aktuellen Mediensitzung auf dem Empfänger abzurufen, verwendet CCL die VideoCastManager:

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

Verwenden Sie in CAF RemoteMediaClient, um dieselben Informationen abzurufen:

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

Einführungs-Overlay

Ähnlich wie CCL bietet CAF eine benutzerdefinierte Ansicht IntroductoryOverlay, um das Cast-Symbol hervorzuheben, wenn es Nutzern zum ersten Mal angezeigt wird.

Anstatt die Methode VideoCastConsumer onCastAvailabilityChanged von CCL zu verwenden, um zu wissen, wann das Overlay angezeigt werden soll, musst du ein CastStateListener deklarieren, um zu bestimmen, wann das Cast-Symbol sichtbar wird, sobald Cast-Geräte im lokalen Netzwerk von MediaRouter erkannt werden:

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

Beobachten Sie die Instanz 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;
}

Prüfen Sie, ob MediaRouteButton sichtbar ist, damit das Einführungs-Overlay angezeigt werden kann:

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

In unserer Beispiel-App finden Sie den vollständigen Arbeitscode zum Anzeigen des Einführungs-Overlays.

Wenn Sie das Design des Einführungs-Overlays anpassen möchten, folgen Sie der Anleitung unter Einführungs-Overlay anpassen.

Mini-Controller

Verwenden Sie anstelle von MiniController des CCL in der App-Layoutdatei der Aktivitäten, in denen der Mini-Controller angezeigt werden soll, MiniControllerFragment von CAF:

<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 unterstützt nicht die manuelle Konfiguration, die von MiniController des CCL unterstützt wird, und auch nicht die Funktion Autoplay.

Folgen Sie der Anleitung unter Mini-Controller anpassen, um den Stil und die Tasten des Mini-Controllers anzupassen.

Benachrichtigung und Sperrbildschirm

Ähnlich wie VideoCastNotificationService von CCL bietet CAF eine MediaNotificationService, um die Anzeige von Medienbenachrichtigungen beim Streamen zu verwalten.

Du musst Folgendes aus deinem Manifest entfernen:

  • VideoIntentReceiver
  • VideoCastNotificationService

CCL unterstützt die Bereitstellung eines benutzerdefinierten Benachrichtigungsdienstes für CastConfiguration.Builder. Dies wird von CAF nicht unterstützt.

Sehen Sie sich die folgende CastManager-Initialisierung mit CCL an:

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

Für die entsprechende Konfiguration in CAF bietet das SDK ein NotificationsOptions.Builder, mit dem Sie Mediensteuerelemente für den Benachrichtigungs- und Sperrbildschirm in der Absender-App erstellen können. Die Benachrichtigungs- und Sperrbildschirmsteuerelemente können mit dem CastOptions beim Initialisieren von CastContext aktiviert werden.

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

Benachrichtigungen und Steuerelemente für den Sperrbildschirm sind in CAF immer aktiviert. Die Schaltflächen für Wiedergabe/Pause und das Streamen sind standardmäßig verfügbar. CAF zeichnet automatisch die Sichtbarkeit von Aktivitäten auf, um zu entscheiden, wann die Medienbenachrichtigung angezeigt werden soll, außer für Gingerbread. Für Gingerbread lesen Sie die früheren Hinweise zur Verwendung von registerLifecycleCallbacksBeforeIceCreamSandwich(). Die Aufrufe VideoCastManager incrementUiCounter und decrementUiCounter von CCL sollten entfernt werden.

Folgen Sie der Anleitung unter Mediensteuerelemente zum Benachrichtigungs- und Sperrbildschirm hinzufügen, um die in Benachrichtigungen angezeigten Schaltflächen anzupassen.

Maximierter Controller

CCL stellt die VideoCastControllerActivity und VideoCastControllerFragment bereit, um beim Streamen von Medien einen erweiterten Controller anzuzeigen.

Du kannst die VideoCastControllerActivity-Deklaration im Manifest entfernen.

In CAF müssen Sie die ExpandedControllerActivity erweitern und das Cast-Symbol hinzufügen.

Folgen Sie der Anleitung unter Erweiterten Controller anpassen, um die Stile und Schaltflächen anzupassen, die im maximierten Controller angezeigt werden.

Audiofokus

Wie bei der CCL wird der Audiofokus automatisch verwaltet.

Lautstärkeregelung

Für Gingerbread ist dispatchKeyEvent wie bei CCL erforderlich. In ICS und höher wird für die CCL- und CAF-Lautstärkeregelung automatisch übernommen.

CAF ermöglicht die Steuerung der Streaming-Lautstärke über die entsprechende Taste auf dem Smartphone innerhalb deiner App-Aktivitäten. Außerdem wird bei der Übertragung von unterstützten Versionen eine visuelle Lautstärkeleiste angezeigt. CAF verarbeitet auch die Lautstärke über die feste Lautstärke, auch wenn Ihre App nicht im Vordergrund, gesperrt oder ausgeschaltet ist.

Untertitel

In Android KitKat und höher können Untertitel über die Einstellungen für Untertitel unter „Einstellungen“ > „Bedienungshilfen“ angepasst werden. Frühere Versionen von Android haben diese Funktion jedoch nicht. CCL übernimmt dies durch die Bereitstellung benutzerdefinierter Einstellungen für frühere Versionen und das Delegieren an die Systemeinstellungen auf KitKat und höher.

CAF bietet keine benutzerdefinierten Einstellungen zum Ändern der Untertiteleinstellungen. Du solltest die CaptionsPreferenceActivity-Referenzen in deinem Manifest und deine XML-Einstellungen entfernen.

Die TracksChooserDialog des CCL wird nicht mehr benötigt, da das Ändern der Untertitel-Tracks über die erweiterte Controller-UI abgewickelt wird.

Die Untertitelung API in CAF ähnelt v2.

Fehlerprotokollierung

CAF bietet keine Einstellungen für das Debug-Logging.

Verschiedenes

Die folgenden CCL-Features werden in CAF nicht unterstützt:

  • Einholen der Autorisierung vor der Wiedergabe durch Angeben eines MediaAuthService
  • Konfigurierbare UI-Nachrichten

Beispiel-Apps

Sehen Sie sich den diff zum Migrieren unserer Beispiel-App Universal Music Player for Android (uamp) von CCL zu CAF an.

Wir bieten auch Codelab-Anleitungen und Beispiel-Apps an, die CAF verwenden.