העברת אפליקציית שולח CCL אל Cast Application Framework (CAF)

ההליך הבא מאפשר לך להמיר את אפליקציית השולח ב-Android מ- Cast SDK v2 עם CCL אל CAF. כל הפונקציונליות של CCL כבר ב-CAF, כך שאחרי ההעברה לא צריך יותר להשתמש ב-CCL.

ערכת ה-SDK של Cast CAF Sender משתמשת ב-CastContext כדי לנהל את GoogleAPIClient בשמכם. CastContext מנהל עבורכם מחזורי חיים, שגיאות וקריאות חוזרות (callback), מפשט את הפיתוח של אפליקציית Cast.

מבוא

  • מכיוון שהעיצוב של שולח CAF הושפע מהספרייה הנלווית של Cast, המיגרציה מ-CCL ל-CAF Sender כוללת בעיקר מיפויים אחד-לאחד והשיטות שלהם.
  • CAF Sender עדיין מופץ כחלק מ-Google Play Services באמצעות מנהל ה-SDK של Android.
  • חבילות חדשות (com.google.android.gms.cast.framework.*) שנוספו נוסף ל-CAF Sender, עם פונקציונליות שדומה ל-CCL, באחריות לציית רשימת משימות לעיצוב של Google Cast.
  • CAF Sender מספק ווידג'טים שעומדים בדרישות של Cast UX. הווידג'טים האלה דומים לווידג'טים שמסופקים על ידי CCL.
  • CAF Sender מספק קריאות חוזרות אסינכרוניות שדומות ל-CCL כדי לעקוב ומשיגים נתונים. בשונה מ-CCL, CAF Sender לא מספק שום פעולה ללא תפעול הטמעות של שיטות הממשק השונות.

בחלקים הבאים נתמקד בעיקר בתוכן וידאו שמבוססות על VideoCastManager של CCL, אבל במקרים רבים גם רלוונטיים גם ל-DataCastManager.

יחסי תלות

ל-CCL ול-CAF יש אותם יחסי תלות בספריית התמיכה של AppCompat, ספריית התמיכה של MediaRouter v7 ושירותי Google Play. אבל ההבדל CAF תלוי במסגרת Cast החדשה שזמינה ב-Google Play שירותים 9.2.0 ואילך.

בקובץ build.gradle, מסירים את יחסי התלות ב com.google.android.gms:play-services-cast והקבוצה com.google.android.libraries.cast.companionlibrary:ccl, לאחר מכן מוסיפים את מסגרת ההעברה החדשה:

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

אפשר גם להסיר את המטא-נתונים של שירות Google Play:

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

כל השירותים, הפעילויות והמשאבים שכלולים ב-CAF הופכים אוטומטית מוזגו עם המניפסט של האפליקציה ועם המשאבים שלה.

הגרסה המינימלית של Android SDK שנתמכת ב-CAF היא 9 (Gingerbread); גרסת Android SDK המינימלית ב-CCL היא 10.

CCL מציע שיטה נוחה, BaseCastManager.checkGooglePlayServices(activity), כדי לאמת שמתקיים הגרסה של Google Play Services זמינה במכשיר. CAF לא מספקים את זה כחלק מ-Cast SDK. מבצעים את התהליך מוודאים שלמכשירים יש את ה-APK של Google Play Services כדי לוודא שה-APK הנכון של Google Play Services מותקנת של המכשיר, כי ייתכן שהעדכונים לא יגיעו לכל המשתמשים באופן מיידי.

עדיין צריך להשתמש בווריאנט של Theme.AppCompat עיצוב.

אתחול

עבור CCL, היה צורך לשלוח קריאה אל VideoCastManager.initialize() onCreate() של מכונת האפליקציות. הלוגיקה הזו צריכה להיות הוסר מקוד הכיתה של האפליקציה.

ב-CAF, נדרש גם שלב אתחול מפורש עבור הפעלת Cast . התהליך הזה כולל אתחול הסינגלטון של CastContext, באמצעות OptionsProvider המתאים כדי לציין את מזהה האפליקציה של המקבל אפשרויות גלובליות אחרות. התפקיד של CastContext דומה לזה של CCL VideoCastManager באמצעות אספקת סינגלטון שהלקוחות מקיימים איתו אינטראקציה. המדד OptionsProvider דומה לCastConfiguration של CCL כדי לאפשר כדי להגדיר את התכונות של מסגרת Cast.

אם ה-CCL הנוכחי CastConfiguration.Builder נראה כך:

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

אחר כך, ב-CAF, מבצעים CastOptionsProvider באמצעות CastOptions.Builder יהיה דומה:

public class CastOptionsProvider implements OptionsProvider {

    @Override
    public CastOptions getCastOptions(Context context) {
        return new CastOptions.Builder()
                .setReceiverApplicationId(context.getString(R.string.app_id))
                .build();
    }

    @Override
    public List<SessionProvider> getAdditionalSessionProviders(
            Context context) {
        return null;
    }
}

כדאי להציץ באפליקציה לדוגמה שלנו כדי לבצע הטמעה מלאה של OptionsProvider.

יש להצהיר על OptionsProvider בתוך ה-application של הרכיב קובץ AndroidManifest.xml:

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

מפעילים אתחול מדורג של CastContext בכל method onCreate של Activity (ולא במופע Application):

private CastContext mCastContext;

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

    mCastContext = CastContext.getSharedInstance(this);
}

כדי לגשת ל-Singleton, צריך להשתמש ב-CastContext:

mCastContext = CastContext.getSharedInstance(this);

גילוי מכשירים

VideoCastManager incrementUiCounter ו-decrementUiCounter של CCL צריכים תוסר מה-method onResume ו-onPause של Activities.

ב-CAF, תהליך הגילוי מתחיל ומופסק באופן אוטומטי על ידי framework, כשהאפליקציה מגיעה לחזית ועוברת לרקע, בהתאמה.

הלחצן להפעלת Cast ותיבת הדו-שיח של הפעלת Cast

בדומה ל-CCL, הרכיבים האלה מסופקים על ידי התמיכה של MediaRouter בגרסה 7 לספרייה.

הלחצן להפעלת Cast עדיין מוטמע ב-MediaRouteButton ואפשר להוסיף אותו לפעילות שלך (באמצעות ActionBar או Toolbar), כאפשרות בתפריט בתפריט.

ההצהרה MediaRouteActionProvider ב-XML של התפריט זהה להצהרה עם 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"/>

בדומה ל-CCL, יש לבטל את השיטה onCreateOptionOptions() של כל פעילות, אבל במקום להשתמש ב-CastManager.addMediaRouterButton, צריך להשתמש ב-castButton לרשות שמנפיקים את הלחצן של CAF כדי לחבר את MediaRouteButton ל-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;
}

שליטה במכשירים

בדומה ל-CCL, ב-CAF, ה-framework מטפל ברוב המקרים. האפליקציה של השולח לא צריכה לטפל (ולא לנסות לטפל בה) להתחבר למכשיר ולהפעיל את אפליקציית המקבל באמצעות GoogleApiClient

אינטראקציה בין השולח למקבל מיוצגת עכשיו כ'סשן'. המחלקה SessionManager מטפלת במחזור החיים של הסשן ומתחילה באופן אוטומטי ומפסיק סשנים בתגובה לתנועות משתמש: סשן מתחיל כש- משתמש בוחר מכשיר Cast בתיבת הדו-שיח של הפעלת Cast ומסתיים כשהמשתמש מקיש הלחצן 'הפסקת ההעברה' לחצן בתיבת הדו-שיח 'העברה' או כאשר האפליקציה של השולח עצמה יסתיים.

ב-CCL צריך להרחיב את המחלקה VideoCastConsumerImpl כדי לעקוב אחרי ההעברה סטטוס הסשן:

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

ב-CAF, האפליקציה השולח יכולה לקבל התראות על אירועים במחזור החיים של הסשן באמצעות רישום SessionManagerListener דרך SessionManager. קריאות חוזרות (callback) של SessionManagerListener מגדירות שיטות קריאה חוזרת (callback) לכל הסשנים אירועים במחזור החיים.

שיטות SessionManagerListener הבאות ממופות מ-CCL ממשק VideoCastConsumer:

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

צריך להצהיר על מחלקה שמטמיעה את הממשק של SessionManagerListener וההעברה הלוגיקה VideoCastConsumerImpl לשיטות ההתאמה:

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

המחלקה CastSession מייצגת סשן עם מכשיר Cast. בכיתה יש שיטות לשליטה בעוצמת הקול ובמצבי ההשתקה של המכשיר, BaseCastManager

במקום להוסיף צרכן באמצעות CCL VideoCastManager:

VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);

עכשיו צריך לרשום את SessionManagerListener:

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

כדי להפסיק להאזין לאירועים ב-CCL:

VideoCastManager.getInstance().removeVideoCastConsumer(mCastConsumer);

עכשיו יש להשתמש ב-SessionManager כדי להפסיק להאזין לאירועי סשן:

mCastSessionManager.removeSessionManagerListener(mCastSessionManagerListener,
                    CastSession.class);

כדי להתנתק ממכשיר Cast באופן מפורש, נעשה שימוש ב-CCL:

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

בשביל CAF, משתמשים ב-SessionManager:

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

כדי לקבוע אם השולח מחובר לצד המקבל, CCL מספק VideoCastManager.getInstance().isConnected(), אבל ב-CAF משתמשים ב- SessionManager:

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

ב-CAF, התראות על שינוי מצב עוצמת הקול או השתקה עדיין נשלחות באמצעות קריאה חוזרת (callback) methods ב-Cast.Listener; המאזינים האלה רשומים ב CastSession. כל ההתראות על מצב המכשיר הנותרות נשלחות דרך CastStateListener התקשרות חזרה; המאזינים האלה רשומים CastSession. חשוב עדיין לבטל את רישום המאזינים כאשר מקטעים, פעילויות או אפליקציות יועברו לרקע.

לוגיקת החיבור מחדש

CAF מנסה ליצור מחדש חיבורי רשת שאבדו בגלל אובדן זמני של אות Wi-Fi או שגיאות רשת אחרות. הפעולה הזו מתבצעת עכשיו רמת סשן; סשן יכול להיכנס ל"השעיה" כשהחיבור הוא ילך לאיבוד, ויחזור למצב "מחובר" כשהקישוריות היא שוחזרה. ה-framework מטפל בחיבור מחדש לאפליקציית המקבל ולחבר מחדש את כל ערוצי ההעברה (cast) במסגרת התהליך הזה.

CAF מספק שירות משלו לחיבור מחדש, כך שאתם יכולים להסיר CCL ReconnectionService מהמניפסט:

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

כמו כן, אין צורך בהרשאות הבאות במניפסט של לוגיקת החיבור מחדש:

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

שירות החיבור מחדש של CAF מופעל כברירת מחדל, אבל ניתן להשבית אותו באמצעות CastOptions

בנוסף, CAF מוסיפה גם המשך אוטומטי של סשן, שמופעל על ידי ברירת המחדל (וניתן להשבית אותה דרך CastOptions). אם האפליקציה של השולח נשלח לרקע או נסגר (על ידי החלקה החוצה או בגלל תאונה) בזמן שמתבצעת הפעלת Cast, ה-framework ינסה להמשיך סשן כשאפליקציית השולח חוזרת לחזית או מופעלת מחדש. מטופל באופן אוטומטי על ידי SessionManager, שינפיק קריאות חוזרות (callback) מתאימות במכונות SessionManagerListener רשומות.

רישום ערוץ מותאם אישית

ב-CCL יש שתי דרכים ליצור ערוץ הודעות בהתאמה אישית למקבל:

  • באמצעות CastConfiguration אפשר לציין כמה מרחבי שמות ו-CCL ניצור את הערוץ בשבילכם.
  • DataCastManager דומה ל-VideocastManager אבל מתמקד בנושא לא מדיה במקרים שונים.

אף אחת מהשיטות האלה ליצירת ערוץ מותאם אישית לא נתמכת על ידי CAF – תצטרכו לבצע את התהליך הוספת ערוץ מותאם אישית לאפליקציית השולח שלך.

בדומה ל-CCL, ביישומי מדיה אין צורך באופן מפורש רושמים את ערוץ בקרת המדיה.

פקד מדיה

ב-CAF, המחלקה RemoteMediaClient מקבילה ל-VideoCastManager שיטות מדיה. הערך RemoteMediaClient.Listener זהה ל- VideoCastConsumer אמצעי תשלום. באופן ספציפי, onRemoteMediaPlayerMetadataUpdated ו-onRemoteMediaPlayerStatusUpdated של VideoCastConsumer ממפה אל onMetadataUpdated onStatusUpdated שיטות של 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() {
    }
}

לא צריך לאתחל או לרשום באופן מפורש את RemoteMediaClient אובייקט; ה-framework ייצור את האובייקט באופן אוטומטי ותרשום את ערוץ המדיה הבסיסי בזמן ההתחלה של הסשן, אם אפליקציית המקבל תומך במרחב השמות של המדיה.

אפשר לגשת ל-RemoteMediaClient כ-method getRemoteMediaClient של את האובייקט CastSession.

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

במקום CCL:

VideoCastManager.getInstance().addVideoCastConsumer(mCastConsumer);

עכשיו אפשר להשתמש ב-CAF:

mRemoteMediaClient.addListener(mRemoteMediaClientListener);

ניתן לרשום כל מספר של מאזינים ב-RemoteMediaClient, שמאפשר לרכיבים של שולחים מרובים לשתף את המופע היחיד של RemoteMediaClient שמשויך לסשן.

VideoCastManager של CCL מספק שיטות לטיפול בהפעלת מדיה:

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

ההיבטים האלה מוטמעים עכשיו על ידי RemoteMediaClient ב-CAF:

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

ב-CAF, כל בקשות המדיה שהונפקו ב-RemoteMediaClient מחזירות RemoteMediaClient.MediaChannelResult באמצעות התקשרות חזרה ב-PendingResult שבו ניתן להשתמש כדי לעקוב אחר ההתקדמות והתוצאה הסופית של הבקשה.

גם CCL וגם CAF משתמשים במחלקות MediaInfo ו-MediaMetadata כדי לייצג קובצי מדיה וכדי לטעון מדיה.

כדי לטעון מדיה ב-CCL, נעשה שימוש בVideoCastManager:

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

ב-CAF, נעשה שימוש בRemoteMediaClient לטעינת המדיה:

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

כדי לקבל את המידע Media והסטטוס של סשן מדיה נוכחי ב המקבל, CCL משתמש בVideoCastManager:

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

ב-CAF, משתמשים ב-RemoteMediaClient כדי לקבל את אותו המידע:

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

שכבת-על של סרטון היכרות

בדומה ל-CCL, ל-CAF יש תצוגה מותאמת אישית IntroductoryOverlay שאפשר להדגיש לחצן הפעלת Cast כשהוא מוצג לראשונה למשתמשים.

במקום להשתמש בשיטת ה-onCastAvailabilityChanged VideoCastConsumer של CCL. כדי לדעת מתי להציג את שכבת-העל, צריך להצהיר על CastStateListener כדי כשהלחצן להפעלת Cast מוצג שוב אחרי שמכשירי Cast מתגלים רשת מקומית על ידי 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);
    ...
}

מעקב אחרי המכונה של 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;
}

צריך לבדוק אם ה-MediaRouteButton גלוי כדי ששכבת-העל של המבוא ניתן להציג:

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

כדאי לעיין אפליקציה לדוגמה לקוד העבודה המלא להצגת שכבת-העל של המבוא.

כדי להתאים אישית את העיצוב של שכבת-העל של המבוא, פועלים לפי התהליך התאמה אישית של שכבת-על ראשונית.

מיני-בקר

במקום MiniController של CCL, אפשר להשתמש ב-MiniControllerFragment של 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 לא תומכת בהגדרה הידנית שנתמכת ב-MiniController של CCL וגם לא תומך בתכונה Autoplay.

כדי להתאים אישית את העיצוב והלחצנים של המיני-בקר, פועלים לפי תהליך התאמה אישית של מיני-בקר.

התראה ומסך הנעילה

בדומה ל-VideoCastNotificationService של CCL, CAF מספק MediaNotificationService כדי לנהל את התצוגה של התראות מדיה בזמן ההעברה (cast).

יש להסיר את הפרטים הבאים מהמניפסט:

  • VideoIntentReceiver
  • VideoCastNotificationService

CCL תומך ביצירת שירות התראות בהתאמה אישית CastConfiguration.Builder; שלא נתמך על ידי CAF.

כדאי לשקול את אתחול CastManager הבא באמצעות 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());

בשביל ההגדרות המקבילות ב-CAF, ה-SDK מספק NotificationsOptions.Builder כדי לעזור לך לפתח פקדי מדיה התראה ומסך הנעילה באפליקציית השולח. ההתראה והנעילה ניתן להפעיל את פקדי המסך עם CastOptions כאשר מאתחלים 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();
}

ההתראות והפקדים של מסך הנעילה תמיד מופעלים ב-CAF. כמו כן, שימו לב לחצני ההפעלה/השהיה ועצירה של הפעלת ה-Cast מסופקים כברירת מחדל. CAF יעקוב באופן אוטומטי אחר החשיפה של הפעילויות כדי להחליט מתי להציג את ההתראה לגבי המדיה, חוץ מ-Gingerbread. (עבור Gingerbread, ראו הערה מוקדמת בנושא באמצעות registerLifecycleCallbacksBeforeIceCreamSandwich(); CCL VideoCastManager incrementUiCounter ו-decrementUiCounter שיחות יש להסיר).

כדי להתאים אישית את הלחצנים שמוצגים בהתראות, פועלים לפי תהליך הוספת פקדי מדיה להתראות ולמסך הנעילה.

בקר מורחב

CCL מספק את VideoCastControllerActivity ו-VideoCastControllerFragment כדי להציג בקר מורחב בזמן הפעלת Cast של מדיה.

אפשר להסיר את ההצהרה VideoCastControllerActivity במניפסט.

ב-CAF צריך מרחיבים אתExpandedControllerActivity ומוסיפים את לחצן הפעלת Cast.

כדי להתאים אישית את הסגנונות והלחצנים שמוצגים בתצוגה מורחבת לנאמני מידע, בצעו את התהליך התאמה אישית של בקר מורחב.

מיקוד אודיו

בדומה ל-CCL, מיקוד האודיו מנוהל באופן אוטומטי.

בקרת עוצמת הקול

ב-Gingerbread, נדרש dispatchKeyEvent כמו ב-CCL. ב-ICS ואילך גם ב-CCL וגם בבקרת עוצמת הקול ב-CAF מטופלות באופן אוטומטי.

CAF מאפשר לשלוט בעוצמת הקול של הפעלת Cast באמצעות לחצן עוצמת הקול הקשיחה הטלפון בתוך הפעילויות שלך באפליקציות, וגם מציג סרגל עוצמת קול ויזואלי מתבצעת העברה (cast) בגרסאות נתמכות. CAF מטפל גם בשינוי עוצמת הקול באמצעות עוצמת קול קשיחה גם אם האפליקציה לא קדמית, נעולה או גם אם המסך מושבתת.

כתוביות

ב-Android KitKat ואילך, אפשר להתאים אישית את הכתוביות באמצעות כתוביות 'הגדרות', אפשר למצוא בקטע 'הגדרות' > נגישות. בגרסאות קודמות של Android, עם זאת, אין לנו את היכולת הזו. CCL מטפל בזה על ידי אספקת הגדרות לגרסאות קודמות והענקת גישה להגדרות המערכת ב-KitKat ומעלה.

מערכת CAF לא מספקת הגדרות מותאמות אישית לשינוי ההעדפות לגבי כתוביות. שלך צריך להסיר את CaptionsPreferenceActivity ההפניות במניפסט ו-XML של ההעדפות שלכם.

אין יותר צורך בTracksChooserDialog של CCL מאז ששינית את הסגירה טראקים של כתוביות מנוהלים על ידי ממשק המשתמש המורחב של הבקר.

closed captioning API ב-CAF דומה ל-v2.

רישום ביומן של ניפוי באגים

הכלי CAF לא מספק הגדרות לרישום ניפוי באגים ביומן.

שונות

תכונות ה-CCL הבאות לא נתמכות ב-CAF:

  • קבלת הרשאה לפני הפעלה על ידי מתן MediaAuthService
  • הודעות בממשק המשתמש שניתן להגדיר

אפליקציות לדוגמה

כדאי לראות את ההבדל בנושא העברת האפליקציה לדוגמה של Universal Music Player for Android (uamp) מ-CCL ל-CAF.

יש לנו גם מדריכים של Codelab ואפליקציות לדוגמה שמשתמשות ב-CAF.