انتقال برنامه CCL Sender به Cast Application Framework (CAF)

روش زیر به شما امکان می دهد برنامه فرستنده اندروید خود را از Cast SDK v2 با CCL به CAF تبدیل کنید. تمام عملکردهای CCL در CAF پیاده سازی شده است، بنابراین پس از مهاجرت، دیگر نیازی به استفاده از CCL نخواهید داشت.

Cast CAF Sender SDK از CastContext برای مدیریت GoogleAPIClient از طرف شما استفاده می‌کند. CastContext چرخه‌های عمر، خطاها و پاسخ‌های تماس را برای شما مدیریت می‌کند، که توسعه یک برنامه Cast را بسیار ساده می‌کند.

مقدمه

  • از آنجایی که طراحی CAF Sender تحت تأثیر کتابخانه Cast Companion قرار گرفته است، مهاجرت از CCL به CAF Sender عمدتاً شامل نگاشت یک به یک کلاس ها و روش های آنها است.
  • فرستنده CAF هنوز به عنوان بخشی از خدمات Google Play با استفاده از مدیر Android SDK توزیع می شود.
  • بسته‌های جدید ( com.google.android.gms.cast.framework.* ) که به فرستنده CAF اضافه شده‌اند، با عملکردی مشابه CCL، مسئولیت پیروی از چک لیست Google Cast Design را بر عهده می‌گیرند.
  • CAF Sender ویجت هایی را ارائه می دهد که با الزامات Cast UX مطابقت دارند. این ویجت ها شبیه به ابزارهای ارائه شده توسط CCL هستند.
  • فرستنده CAF برای ردیابی وضعیت ها و به دست آوردن داده ها، تماس های غیرهمزمان مشابه CCL را فراهم می کند. برخلاف CCL، CAF Sender هیچ گونه پیاده سازی بدون عملیاتی از روش های مختلف رابط را ارائه نمی دهد.

در بخش‌های بعدی، ما عمدتاً بر روی برنامه‌های ویدئومرکزی مبتنی بر VideoCastManager CCL تمرکز خواهیم کرد، اما در بسیاری از موارد، همین مفاهیم برای DataCastManager نیز صدق می‌کند.

وابستگی ها

CCL و CAF وابستگی های یکسانی به کتابخانه پشتیبانی AppCompat، کتابخانه پشتیبانی MediaRouter v7 و خدمات Google Play دارند. با این حال، تفاوت این است که CAF به چارچوب جدید Cast که در Google Play Services 9.2.0 یا جدیدتر موجود است بستگی دارد.

در فایل build.gradle خود، وابستگی‌ها به com.google.android.gms:play-services-cast و com.google.android.libraries.cast.companionlibrary:ccl حذف کنید، سپس چارچوب 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'
}

همچنین می‌توانید فراداده سرویس Google Play را حذف کنید:

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

هر سرویس، فعالیت و منبعی که بخشی از CAF است به طور خودکار با مانیفست و منابع برنامه شما ادغام می شود.

حداقل نسخه Android SDK که CAF پشتیبانی می کند 9 (نان زنجبیلی) است. حداقل نسخه Android SDK CCL 10 است.

CCL یک روش راحت به BaseCastManager.checkGooglePlayServices(activity) را برای تأیید اینکه یک نسخه سازگار از خدمات Google Play در دستگاه موجود است ارائه می دهد. CAF این را به عنوان بخشی از Cast SDK ارائه نمی کند. برای اطمینان از نصب صحیح APK سرویس‌های Google Play روی دستگاه کاربر، زیرا ممکن است به‌روزرسانی‌ها فوراً به همه کاربران نرسد، این روش را دنبال کنید. مطمئن شوید دستگاه‌ها APK خدمات Google Play را دارند.

همچنان باید از یک نوع Theme.AppCompat برای موضوع برنامه استفاده کنید.

مقداردهی اولیه

برای CCL، VideoCastManager.initialize() لازم بود در متد onCreate() نمونه Applications فراخوانی شود. این منطق باید از کد کلاس Application شما حذف شود.

در CAF، یک مرحله اولیه سازی صریح نیز برای چارچوب Cast مورد نیاز است. این شامل مقداردهی اولیه CastContext singleton، با استفاده از یک OptionsProvider مناسب برای تعیین شناسه برنامه گیرنده و هر گزینه کلی دیگر است. CastContext نقشی مشابه VideoCastManager CCL با ارائه یک تک‌تن که مشتریان با آن تعامل دارند، ایفا می‌کند. 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 در روش onCreate هر Activity مقداردهی کنید (و نه نمونه Application ):

private CastContext mCastContext;

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

    mCastContext = CastContext.getSharedInstance(this);
}

برای دسترسی به CastContext singleton از:

mCastContext = CastContext.getSharedInstance(this);

کشف دستگاه

CCL's VideoCastManager incrementUiCounter و decrementUiCounter باید از روش‌های onResume و onPause Activities شما حذف شوند.

در CAF، هنگامی که برنامه به پیش‌زمینه می‌آید و به پس‌زمینه می‌رود، فرآیند کشف به‌طور خودکار توسط فریمورک شروع و متوقف می‌شود.

دکمه Cast و گفتگوی Cast

همانند CCL، این مؤلفه ها توسط کتابخانه پشتیبانی MediaRouter v7 ارائه شده است.

دکمه 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، روش onCreateOptionMenu() هر Activity را نادیده بگیرید، اما به جای استفاده از CastManager.addMediaRouterButton، از CastButtonFactory CAF برای اتصال MediaRouteButton به چارچوب 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، کنترل دستگاه تا حد زیادی توسط چارچوب انجام می شود. برنامه فرستنده نیازی به اتصال به دستگاه و راه اندازی برنامه گیرنده با استفاده از GoogleApiClient ندارد (و نباید تلاش کند)

تعامل بین فرستنده و گیرنده اکنون به عنوان یک "جلسه" نشان داده می شود. کلاس SessionManager چرخه عمر جلسه را کنترل می کند و به طور خودکار جلسات را در پاسخ به حرکات کاربر شروع و متوقف می کند: یک جلسه زمانی شروع می شود که کاربر یک دستگاه Cast را در گفتگوی 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 از رویدادهای چرخه زندگی جلسه مطلع شود. تماس‌های SessionManagerListener روش‌های بازگشت به تماس را برای همه رویدادهای چرخه عمر جلسه تعریف می‌کنند.

روش‌های SessionManagerListener زیر از رابط VideoCastConsumer CCL ترسیم شده‌اند:

  • 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 را نشان می دهد. کلاس دارای روش هایی برای کنترل حجم دستگاه و حالت های بی صدا است که CCL در 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، اعلان‌های تغییر وضعیت صدا/بی‌صدا همچنان از طریق روش‌های پاسخ به تماس در Cast.Listener ارائه می‌شوند. این شنوندگان در CastSession ثبت شده اند. همه اعلان‌های وضعیت دستگاه باقی‌مانده از طریق تماس‌های CastStateListener ارائه می‌شوند. این شنوندگان در CastSession ثبت شده اند. وقتی قطعات، فعالیت‌ها یا برنامه‌های مرتبط به پس‌زمینه می‌روند، مطمئن شوید که هنوز ثبت شنوندگان را لغو ثبت کرده‌اید.

منطق اتصال مجدد

CAF تلاش می کند تا اتصالات شبکه ای را که به دلیل قطع موقت سیگنال WiFi یا سایر خطاهای شبکه از بین رفته اند، دوباره برقرار کند. این اکنون در سطح جلسه انجام می شود. یک جلسه می تواند زمانی که اتصال قطع می شود وارد حالت "تعلیق" شود و با بازیابی اتصال به حالت "متصل" برمی گردد. فریم ورک از اتصال مجدد به برنامه گیرنده و اتصال مجدد هر کانال 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 در حال انجام است، برنامه فرستنده به پس‌زمینه فرستاده شود یا خاتمه یابد (با کشیدن انگشت یا به دلیل خرابی)، فریم ورک تلاش می‌کند تا زمانی که برنامه فرستنده به پیش‌زمینه بازگردد یا راه‌اندازی مجدد شود، آن جلسه را از سر بگیرد. این به طور خودکار توسط SessionManager مدیریت می‌شود، که در هر نمونه ثبت‌شده 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 نیست. اگر برنامه گیرنده متصل به فضای نام رسانه از فضای نام رسانه پشتیبانی کند، فریم ورک به طور خودکار شی را نمونه‌برداری می‌کند و کانال رسانه زیرین را در زمان شروع جلسه ثبت می‌کند.

RemoteMediaClient می تواند به عنوان متد 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 هنگامی که برای اولین بار به کاربران نشان داده می شود، ارائه می دهد.

به جای استفاده از روش CCL's VideoCastConsumer onCastAvailabilityChanged برای دانستن زمان نمایش همپوشانی، یک CastStateListener را اعلام کنید تا مشخص شود وقتی دستگاه های Cast در شبکه محلی توسط MediaRouter کشف شدند، چه زمانی دکمه Cast قابل مشاهده می شود:

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 پشتیبانی نمی کند.

برای سفارشی کردن استایل و دکمه‌های مینی کنترلر، رویه Customize Mini Controller را دنبال کنید.

اعلان و صفحه قفل

مشابه با VideoCastNotificationService CCL، CAF یک MediaNotificationService را برای مدیریت نمایش اعلان‌های رسانه هنگام ارسال محتوا ارائه می‌کند.

باید موارد زیر را از مانیفست خود حذف کنید:

  • 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 ارائه می‌کند تا به شما کمک کند کنترل‌های رسانه را برای اعلان و صفحه قفل در برنامه فرستنده بسازید. هنگام تنظیم اولیه CastContext ، کنترل‌های اعلان و صفحه قفل را می‌توان با CastOptions فعال کرد.

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 فعال هستند. همچنین توجه داشته باشید که دکمه‌های پخش/مکث و توقف پخش به‌صورت پیش‌فرض ارائه شده‌اند. CAF به طور خودکار قابلیت مشاهده فعالیت‌ها را برای تصمیم‌گیری در مورد زمان نمایش اعلان رسانه، به جز شیرینی زنجفیلی، ردیابی می‌کند. (برای شیرینی زنجفیلی، به یادداشت قبلی در مورد استفاده از registerLifecycleCallbacksBeforeIceCreamSandwich() مراجعه کنید؛ CCL's VideoCastManager incrementUiCounter و تماس‌های decrementUiCounter باید حذف شوند.)

برای سفارشی کردن دکمه‌هایی که در اعلان‌ها نمایش داده می‌شوند، رویه افزودن کنترل‌های رسانه به اعلان و قفل صفحه را دنبال کنید.

کنترلر گسترش یافته

CCL VideoCastControllerActivity و VideoCastControllerFragment را برای نمایش یک کنترلر توسعه یافته در هنگام ریختن رسانه فراهم می کند.

می‌توانید اعلان VideoCastControllerActivity را در مانیفست حذف کنید.

در CAF، باید ExpandedControllerActivity را گسترش دهید و دکمه Cast را اضافه کنید .

برای سفارشی کردن سبک‌ها و دکمه‌هایی که در کنترل‌کننده توسعه‌یافته نمایش داده می‌شوند، رویه Customize Expanded Controller را دنبال کنید.

فوکوس صوتی

همانند CCL، فوکوس صوتی به صورت خودکار مدیریت می شود.

کنترل صدا

برای Gingerbread، dispatchKeyEvent مانند CCL مورد نیاز است. در ICS و بالاتر برای هر دو CCL و CAF کنترل صدا به طور خودکار انجام می شود.

CAF کنترل صدای پخش‌شده را از طریق دکمه ولوم سخت روی تلفن در داخل فعالیت‌های برنامه‌های شما امکان‌پذیر می‌کند و همچنین نوار صدای بصری را هنگام ارسال محتوا در نسخه‌های پشتیبانی شده نشان می‌دهد. CAF همچنین تغییر صدا را از طریق ولوم سخت کنترل می کند، حتی اگر برنامه شما در جلو نباشد، قفل باشد یا حتی اگر صفحه نمایش خاموش باشد.

زیرنویس‌های بسته

در کیت‌کت اندروید و بالاتر، زیرنویس‌ها را می‌توان از طریق تنظیمات زیرنویس، که در زیر تنظیمات > دسترس‌پذیری یافت می‌شود، سفارشی کرد. نسخه های قبلی اندروید اما این قابلیت را ندارند. CCL با ارائه تنظیمات سفارشی برای نسخه های قبلی و تفویض اختیار به تنظیمات سیستم در کیت کت و بالاتر این کار را انجام می دهد.

CAF تنظیمات سفارشی برای تغییر تنظیمات برگزیده ارائه نمی دهد. باید ارجاعات CaptionsPreferenceActivity را در مانیفست و تنظیمات XML خود حذف کنید.

CCL's TracksChooserDialog دیگر مورد نیاز نیست زیرا تغییر تراک‌های شرح بسته توسط رابط کاربری کنترل‌کننده توسعه‌یافته انجام می‌شود.

API زیرنویس بسته در CAF شبیه نسخه 2 است.

ثبت اشکال زدایی

CAF تنظیمات ثبت اشکال زدایی را ارائه نمی دهد.

متفرقه

ویژگی‌های CCL زیر در CAF پشتیبانی نمی‌شوند:

  • دریافت مجوز قبل از پخش با ارائه MediaAuthService
  • پیام های رابط کاربری قابل تنظیم

نمونه برنامه ها

به تفاوت انتقال برنامه نمونه پخش کننده موسیقی جهانی برای Android (uamp) از CCL به CAF نگاهی بیندازید.

ما همچنین آموزش های Codelab و نمونه برنامه هایی داریم که از CAF استفاده می کنند.