نقل تطبيق مُرسِل CCL إلى إطار عمل تطبيق البث (CAF)

يتيح لك الإجراء التالي تحويل تطبيق مرسل على Android من الإصدار 2 من حزمة تطوير البرامج (SDK) للإرسال مع CCL إلى CAF تم استخدام جميع وظائف CCL التنفيذ في CAF، لذا بعد نقل البيانات، لن تحتاج إلى استخدام CCL.

إنّ حزمة تطوير البرامج (SDK) الخاصة بإرسال CAF Sender تستخدم CastContext لإدارة GoogleAPIClient نيابةً عنك. يدير CastContext مراحل النشاط والأخطاء وعمليات معاودة الاتصال نيابةً عنك، مما يجعله تبسيط تطوير تطبيق البث.

مقدمة

  • ونظرًا لأن تصميم مرسل CAF قد تأثر بمكتبة Cast Companion Library، تتضمن عملية الانتقال من CCL إلى CAF Sender عمليات تعيين فردية الفئات وأساليبها.
  • لا يزال تطبيق CAF Sender موزَّعًا كجزء من "خدمات Google Play" باستخدام مدير حزمة تطوير البرامج (SDK) لنظام التشغيل Android.
  • الحِزم الجديدة (com.google.android.gms.cast.framework.*) التي تم استخدامها مضافة إلى CAF Sender، بوظائف مشابهة لـ CCL، في تنفيذ مسئولية الالتزام قائمة التحقق الخاصة بتصميم Google Cast.
  • يوفّر تطبيق CAF Sender التطبيقات المصغّرة التي تتوافق مع متطلبات تجربة المستخدم لجهاز Cast؛ وتكون هذه التطبيقات المصغّرة مشابهة لتلك التي يوفّرها CCL.
  • يوفّر مرسِل CAF استدعاءات غير متزامنة مماثلة لـ CCL، لتتبع الحالات والحصول على البيانات. على عكس CCL، لا يوفر مرسِل CAF أي حالة إيقاف وتنفيذ أساليب الواجهة المختلفة.

سنركّز بشكل أساسي على الفيديوهات التي تتناول استنادًا إلى VideoCastManager من CCL، ولكن في كثير من الحالات على DataCastManager أيضًا.

التبعيات

لكل من CCL وCAF نفس الاعتماديات على مكتبة دعم AppCompat، مكتبة دعم الإصدار 7 من MediaRouter وخدمات Google Play ومع ذلك، فإن الفرق هو أنّ CAF يعتمد على إطار عمل Google Cast الجديد المتاح في Google Play 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 تم دمجها مع بيان تطبيقك وموارده.

الحد الأدنى لإصدار حزمة تطوير البرامج (SDK) لنظام التشغيل Android الذي يتوافق مع CAF هو 9 (Gingerbread); الحد الأدنى لإصدار حزمة تطوير البرامج (SDK) لنظام التشغيل Android في CCL هو 10.

توفر CCL طريقة ملائمة، BaseCastManager.checkGooglePlayServices(activity)، للتأكّد من توافق توفُّر إصدار من خدمات Google Play على الجهاز. CAF لا لتوفيرها كجزء من حزمة تطوير البرامج (SDK) الخاصة بتكنولوجيا Google Cast. اتّباع الإجراء التأكّد من أنّ الأجهزة تتضمّن حزمة APK لخدمات Google Play لضمان تثبيت حِزمة APK الصحيحة "خدمات Google Play" على حساب المستخدم الجهاز نظرًا لأن التحديثات قد لا تصل إلى جميع المستخدمين على الفور.

لا يزال مطلوبًا منك استخدام صيغة Theme.AppCompat الخاصة بالتطبيق. الموضوع.

الإعداد

بالنسبة إلى CCL، كان مطلوبًا استدعاء VideoCastManager.initialize() في onCreate() لمثيل التطبيقات. يجب أن يكون هذا المنطق من رمز فئة التطبيق.

في CAF، يلزم أيضًا خطوة إعداد واضحة للبث إطار العمل. ويشمل ذلك إعداد المفردة المنفردة CastContext باستخدام OptionsProvider المناسبة لتحديد معرّف طلب المُستلِم وخيارات عامة أخرى. تلعب CastContext دورًا مشابهًا لـ CCL VideoCastManager من خلال توفير صورة مفردة يتفاعل معها العملاء. إنّ OptionsProvider مشابه لـ CastConfiguration في CCL للسماح لك لضبط ميزات إطار عمل Google 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;
    }
}

ألقِ نظرة على نموذج التطبيق لتنفيذ OptionProvider بشكلٍ كامل.

تعريف OptionProvider ضمن "التطبيق" العنصر الأساسي في ملف 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، استخدم:

mCastContext = CastContext.getSharedInstance(this);

رصد الأجهزة

يجب أن يتضمّن كل من VideoCastManager incrementUiCounter وdecrementUiCounter في CCL ستتم إزالته من الطريقتين onResume وonPause في جهاز Activities.

في CAF، تبدأ عملية الاكتشاف وتتوقف تلقائيًا عن طريق إطار العمل عندما يظهر التطبيق في المقدّمة وينتقل إلى الخلفية على التوالي.

زر البث ومربّع حوار البث

كما هو الحال مع CCL، يتم توفير هذه المكونات من خلال دعم الإصدار 7 من MediaRouter المكتبة.

لا يزال زر البث مفعَّل من قِبل "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، قم بإلغاء طريقة onCreateOption Menu() لكل نشاط، لكن بدلاً من استخدام CastManager.addMediaRouterButton، استخدم CastButtonProduct في 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) مراحل الجلسة ويبدأ تلقائيًا. وتوقف الجلسات استجابةً لإيماءات المستخدم: تبدأ الجلسة عند يختار المستخدم جهاز بث في مربّع حوار البث، وينتهي عندما ينقر المستخدم و"إيقاف البث" الزر في مربّع حوار البث أو عند استخدام تطبيق المُرسِل نفسه ينتهي.

في 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 التالية من طرق 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 جلسة مع جهاز بث. تضم الفئة للتحكم في مستوى صوت الجهاز وحالات كتم الصوت، وهو ما تفعله 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);

لقطع الاتصال صراحةً بجهاز البث، استخدمت 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 إعادة إنشاء اتصالات الشبكة المفقودة بسبب إلى فقدان إشارة واي فاي المؤقتة أو أخطاء أخرى في الشبكة. يتم ذلك الآن في صفحة مستوى الجلسة يمكن أن تدخل الجلسة "معلقة" عندما يكون الاتصال وستنتقل مرة أخرى إلى الحالة "متصل" عندما يكون الاتصال تمت استعادتها. يعتني إطار العمل بإعادة الاتصال بتطبيق جهاز الاستقبال. وإعادة ربط أي قنوات بث كجزء من هذه العملية.

يوفر 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). إذا كان تطبيق المرسل يتم إرساله إلى الخلفية أو تم إنهاؤه (عن طريق التمرير سريعًا للخارج أو بسبب حادث سير) عندما تكون جلسة البث قيد التقدم، سيحاول إطار العمل استئناف الجلسة عند عودة تطبيق المرسِل إلى المقدّمة أو إعادة تشغيله يتم معالجة هذا الأمر تلقائيًا من خلال 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 لإبرازها. الزر "إرسال" عند عرضه لأول مرة للمستخدمين.

بدلاً من استخدام طريقة VideoCastConsumer onCastAvailabilityChanged الخاصة بـ CCL لمعرفة وقت عرض التراكب، تعريف CastStateListener لتحديد عندما يصبح زر البث مرئيًا بعد اكتشاف أجهزة البث على الشبكة المحلية من 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's 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 لمساعدتك في إنشاء عناصر التحكّم في الوسائط وشاشة القفل في تطبيق المرسل. الإشعار والقفل يمكن تفعيل عناصر التحكم في الشاشة باستخدام 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. لاحظ أيضًا أن يتم توفير أزرار التشغيل/الإيقاف المؤقت وإيقاف البث تلقائيًا. CAF تتبع مستوى رؤية الأنشطة تلقائيًا لاتخاذ قرار وقت عرض إشعار الوسائط، باستثناء Gingerbread. (بالنسبة إلى Gingerbread، يُرجى الاطّلاع على الملاحظة السابقة على استخدام registerLifecycleCallbacksBeforeIceCreamSandwich()؛ CCL مكالمتا VideoCastManager incrementUiCounter وdecrementUiCounter ).

لتخصيص الأزرار التي تظهر في الإشعارات، اتبع الإجراء إضافة عناصر التحكّم في الوسائط إلى الإشعارات وشاشة القفل

تم توسيع وحدة التحكُّم

توفّر CCL السمة VideoCastControllerActivity وVideoCastControllerFragment لعرض وحدة تحكم موسّعة عند بث الوسائط.

يمكنك إزالة تعريف VideoCastControllerActivity في ملف البيان.

في CAF، يتعين عليك توسيع ExtendedControllerActivity وإضافة زر Cast.

لتخصيص الأنماط والأزرار المعروضة في القسم الموسَّع تحكم، اتبع الإجراء تخصيص وحدة التحكّم الموسّعة

التركيز على الصوت

كما هي الحال مع CCL، تتم إدارة التركيز على الصوت تلقائيًا.

التحكم في مستوى الصوت

بالنسبة إلى Gingerbread، يجب توفير dispatchKeyEvent كما هو الحال مع CCL. في ICS والإصدارات الأحدث يتم التعامل مع التحكُّم في مستوى الصوت لكل من CCL وCAF تلقائيًا.

يتيح CAF التحكم في مستوى صوت البث من خلال زر التحكّم بمستوى الصوت الثابت في هاتفك داخل أنشطة التطبيقات، ويعرض أيضًا شريطًا مرئيًا لمستوى الصوت عند البث على الإصدارات المتوافقة. يتعامل CAF أيضًا مع تغيير مستوى الصوت من خلال مستوى الصوت الثابت حتى لو لم يكن التطبيق مفتوحًا أو تم قفله أو حتى إذا كانت الشاشة

الترجمة والشرح

في Android KitKat والإصدارات الأحدث، يمكن تخصيص الشرح من خلال الشرح الإعدادات، يمكنك العثور عليها ضمن الإعدادات > إمكانية الوصول: في الإصدارات السابقة من Android، لا يتمتعون بهذه الإمكانية. تتعامل CCL مع ذلك من خلال تقديم الإعدادات للإصدارات السابقة والتفويض إلى إعدادات النظام على KitKat وأعلى.

لا يوفر CAF إعدادات مخصصة لتغيير الإعدادات المفضّلة للشرح. إِنْتَ يجب إزالة مراجع CaptionsPreferenceActivity في البيان. وXML لتفضيلاتك.

لم تعُد هناك حاجة إلى TracksChooserDialog الخاص بـ CCL منذ تغيير المكان المغلق. تتم معالجة مسارات الترجمة والشرح من خلال واجهة المستخدم الموسّعة لوحدة التحكُّم.

واجهة برمجة التطبيقات للترجمة والشرح في CAF يشبه الإصدار 2.

تسجيل تصحيح الأخطاء

لا يوفّر CAF إعدادات تسجيل تصحيح الأخطاء.

ميزات متنوّعة

لا تتوفّر ميزات CCL التالية في CAF:

  • الحصول على إذن قبل التشغيل من خلال توفير MediaAuthService
  • رسائل واجهة المستخدم القابلة للضبط

نماذج التطبيقات

يمكنك الاطّلاع على الفرق في عملية نقل نموذج تطبيق Universal Music Player لنظام التشغيل Android (uamp) من CCL إلى CAF.

ولدينا أيضًا برامج تعليمية حول الترميز ونماذج تطبيقات تستخدم CAF.