یک برنامه اندرویدی را Cast فعال کنید

1. بررسی اجمالی

نشان‌واره Google Cast

این کد لبه به شما می آموزد که چگونه یک برنامه ویدیویی موجود در اندروید را برای ارسال محتوا در یک دستگاه دارای Google Cast تغییر دهید.

Google Cast چیست؟

Google Cast به کاربران امکان می دهد محتوا را از دستگاه تلفن همراه به تلویزیون ارسال کنند. سپس کاربران می توانند از دستگاه تلفن همراه خود به عنوان یک کنترل از راه دور برای پخش رسانه در تلویزیون استفاده کنند.

Google Cast SDK به شما امکان می دهد برنامه خود را برای کنترل تلویزیون یا سیستم صوتی گسترش دهید. Cast SDK به شما امکان می دهد اجزای رابط کاربری لازم را بر اساس چک لیست طراحی Google Cast اضافه کنید.

چک لیست طراحی Google Cast برای ساده و قابل پیش بینی کردن تجربه کاربر Cast در همه پلتفرم های پشتیبانی شده ارائه شده است.

قرار است چه چیزی بسازیم؟

پس از تکمیل این کد لبه، یک برنامه ویدیویی Android خواهید داشت که می‌تواند ویدیوها را به دستگاهی با قابلیت Google Cast ارسال کند.

چیزی که یاد خواهید گرفت

  • چگونه Google Cast SDK را به یک برنامه ویدیویی نمونه اضافه کنیم.
  • نحوه اضافه کردن دکمه Cast برای انتخاب دستگاه Google Cast.
  • نحوه اتصال به دستگاه Cast و راه اندازی گیرنده رسانه.
  • نحوه پخش ویدیو
  • چگونه مینی کنترلر Cast را به برنامه خود اضافه کنید.
  • نحوه پشتیبانی از اعلان‌های رسانه و کنترل‌های صفحه قفل
  • نحوه اضافه کردن یک کنترلر توسعه یافته
  • نحوه ارائه یک پوشش مقدماتی
  • چگونه ویجت‌های Cast را سفارشی کنیم.
  • نحوه ادغام با Cast Connect

آنچه شما نیاز دارید

  • جدیدترین Android SDK .
  • اندروید استودیو نسخه 3.2+
  • یک دستگاه تلفن همراه با Android 4.1+ Jelly Bean (سطح API 16).
  • یک کابل داده USB برای اتصال دستگاه تلفن همراه به رایانه توسعه.
  • یک دستگاه Google Cast مانند Chromecast یا Android TV که با دسترسی به اینترنت پیکربندی شده است.
  • تلویزیون یا مانیتور با ورودی HDMI.
  • برای آزمایش ادغام Cast Connect به Chromecast با Google TV نیاز است، اما برای بقیه Codelab اختیاری است. اگر یکی ندارید، در پایان این آموزش از مرحله Add Cast Connect Support رد شوید.

تجربه کنید

  • شما باید دانش قبلی کاتلین و توسعه اندروید را داشته باشید.
  • شما همچنین به دانش قبلی در مورد تماشای تلویزیون نیاز دارید :)

چگونه از این آموزش استفاده خواهید کرد؟

فقط از طریق آن را بخوانید آن را بخوانید و تمرینات را کامل کنید

به تجربه خود از ساخت اپلیکیشن های اندرویدی چه امتیازی می دهید؟

تازه کار متوسط مسلط

تجربه خود را از تماشای تلویزیون چگونه ارزیابی می کنید؟

تازه کار متوسط مسلط

2. کد نمونه را دریافت کنید

می توانید تمام کدهای نمونه را در رایانه خود دانلود کنید ...

و فایل فشرده دانلود شده را باز کنید.

3. برنامه نمونه را اجرا کنید

نماد یک جفت قطب نما

ابتدا، بیایید ببینیم که برنامه نمونه تکمیل شده چگونه به نظر می رسد. این برنامه یک پخش کننده ویدیوی اساسی است. کاربر می تواند یک ویدیو را از یک لیست انتخاب کند و سپس می تواند ویدیو را به صورت محلی در دستگاه پخش کند یا آن را به دستگاه Google Cast ارسال کند.

با دانلود کد، دستورالعمل های زیر نحوه باز کردن و اجرای برنامه نمونه تکمیل شده در Android Studio را شرح می دهد:

Import Project را در صفحه خوش آمدگویی یا گزینه های منو File > New > Import Project... را انتخاب کنید.

را انتخاب کنید نماد پوشه دایرکتوری app-done از پوشه کد نمونه و روی OK کلیک کنید.

روی فایل > کلیک کنید دکمه «Sync Project with Gradle» اندروید استودیو همگام سازی پروژه با فایل های Gradle .

اشکال زدایی USB را در دستگاه Android خود فعال کنید - در اندروید 4.2 و بالاتر، صفحه گزینه های برنامه نویس به طور پیش فرض پنهان است. برای اینکه آن را قابل مشاهده کنید، به Settings > About phone بروید و هفت بار روی Build number ضربه بزنید. به صفحه قبلی بازگردید، به System > Advanced بروید و روی Developer options نزدیک پایین ضربه بزنید، سپس روی USB debugging ضربه بزنید تا روشن شود.

دستگاه اندروید خود را وصل کنید و روی آن کلیک کنید دکمه اجرای اندروید استودیو، یک مثلث سبز رنگ که به سمت راست اشاره می کند دکمه اجرا در اندروید استودیو. پس از چند ثانیه باید ببینید که برنامه ویدیویی با نام Cast Videos ظاهر می شود.

روی دکمه Cast در برنامه ویدیو کلیک کنید و دستگاه Google Cast خود را انتخاب کنید.

یک ویدیو را انتخاب کنید و روی دکمه پخش کلیک کنید.

پخش ویدیو در دستگاه Google Cast شما شروع می شود.

کنترل کننده گسترش یافته نمایش داده می شود. می توانید از دکمه پخش/مکث برای کنترل پخش استفاده کنید.

به لیست ویدیوها برگردید.

اکنون یک مینی کنترلر در پایین صفحه قابل مشاهده است. تصویری از یک تلفن اندرویدی که برنامه «Cast Videos» را اجرا می‌کند و مینی کنترلر در پایین صفحه ظاهر می‌شود.

روی دکمه مکث در کنترلر کوچک کلیک کنید تا ویدیو روی گیرنده متوقف شود. برای ادامه پخش مجدد ویدیو، روی دکمه پخش در مینی کنترلر کلیک کنید.

روی دکمه هوم دستگاه موبایل کلیک کنید. اعلان‌ها را پایین بکشید و اکنون باید یک اعلان برای جلسه Cast ببینید.

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

به برنامه ویدیو برگردید و روی دکمه Cast کلیک کنید تا ارسال محتوا در دستگاه Google Cast متوقف شود.

سوالات متداول

4. پروژه شروع را آماده کنید

تصویری از یک تلفن Android که برنامه «Cast Videos» را اجرا می‌کند

باید پشتیبانی از Google Cast را به برنامه شروعی که دانلود کردید اضافه کنیم. در اینجا برخی از اصطلاحات Google Cast وجود دارد که در این لبه کد استفاده خواهیم کرد:

  • یک برنامه فرستنده روی دستگاه تلفن همراه یا لپ تاپ اجرا می شود،
  • یک برنامه گیرنده در دستگاه Google Cast اجرا می شود.

اکنون شما آماده هستید تا با استفاده از Android Studio روی پروژه شروع کننده ایجاد کنید:

  1. را انتخاب کنید نماد پوشه دایرکتوری app-start از دانلود کد نمونه خود ( وارد کردن پروژه را در صفحه خوش آمدگویی یا گزینه منو File > New > Import Project... را انتخاب کنید).
  2. را کلیک کنید دکمه «Sync Project with Gradle» اندروید استودیو همگام سازی پروژه با دکمه Gradle Files .
  3. را کلیک کنید دکمه اجرای اندروید استودیو، یک مثلث سبز رنگ که به سمت راست اشاره می کند دکمه اجرا برای اجرای برنامه و کاوش در رابط کاربری.

طراحی اپلیکیشن

این برنامه لیستی از ویدیوها را از یک وب سرور راه دور دریافت می کند و فهرستی را برای مرورگر در اختیار کاربر قرار می دهد. کاربران می توانند یک ویدیو را برای دیدن جزئیات انتخاب کنند یا ویدیو را به صورت محلی در دستگاه تلفن همراه پخش کنند.

این برنامه از دو فعالیت اصلی تشکیل شده است: VideoBrowserActivity و LocalPlayerActivity . برای ادغام عملکرد Google Cast، Activities باید از AppCompatActivity یا از والد آن FragmentActivity به ارث برده شود. این محدودیت وجود دارد زیرا ما باید MediaRouteButton (ارائه شده در کتابخانه پشتیبانی MediaRouter ) را به عنوان MediaRouteActionProvider اضافه کنیم و این فقط در صورتی کار می کند که فعالیت از کلاس های ذکر شده در بالا به ارث برده شود. کتابخانه پشتیبانی MediaRouter به کتابخانه پشتیبانی AppCompat بستگی دارد که کلاس های مورد نیاز را ارائه می دهد.

VideoBrowserActivity

این فعالیت حاوی یک Fragment ( VideoBrowserFragment ) است. این لیست توسط یک ArrayAdapter ( VideoListAdapter ) پشتیبانی می شود. لیست ویدیوها و ابرداده مرتبط با آنها در یک سرور راه دور به عنوان یک فایل JSON میزبانی می شود. یک AsyncTaskLoader ( VideoItemLoader ) این JSON را واکشی می کند و آن را پردازش می کند تا لیستی از اشیاء MediaItem بسازد.

یک شی MediaItem یک ویدیو و ابرداده مرتبط با آن، مانند عنوان، توضیحات، URL برای جریان، URL برای تصاویر پشتیبان، و تراک‌های متن مرتبط (برای زیرنویس‌ها) در صورت وجود، مدل می‌کند. شی MediaItem بین اکتیویتی ها ارسال می شود، بنابراین MediaItem روش های کاربردی برای تبدیل آن به Bundle و بالعکس دارد.

هنگامی که لودر لیست MediaItems را می سازد، آن لیست را به VideoListAdapter ارسال می کند که سپس لیست MediaItems را در VideoBrowserFragment ارائه می کند. به کاربر لیستی از تصاویر کوچک ویدیو با توضیحات کوتاه برای هر ویدیو ارائه می شود. هنگامی که یک مورد انتخاب می شود، MediaItem مربوطه به یک Bundle تبدیل می شود و به LocalPlayerActivity ارسال می شود.

LocalPlayerActivity

این فعالیت فراداده مربوط به یک ویدیوی خاص را نمایش می دهد و به کاربر اجازه می دهد ویدیو را به صورت محلی در دستگاه تلفن همراه پخش کند.

این فعالیت میزبان یک VideoView ، برخی از کنترل‌های رسانه، و یک ناحیه متنی برای نمایش توضیحات ویدیوی انتخابی است. پخش کننده قسمت بالای صفحه را پوشش می دهد و فضایی را برای توضیحات دقیق ویدیو در زیر باز می کند. کاربر می تواند پخش/مکث کند یا به دنبال پخش محلی ویدیوها باشد.

وابستگی ها

از آنجایی که ما از AppCompatActivity استفاده می کنیم، به کتابخانه پشتیبانی AppCompat نیاز داریم. برای مدیریت لیست ویدیوها و دریافت ناهمزمان تصاویر لیست، از کتابخانه Volley استفاده می کنیم.

سوالات متداول

5. افزودن دکمه Cast

تصویر قسمت بالای یک تلفن Android با اجرای برنامه Cast Video. دکمه Cast که در گوشه سمت راست بالای صفحه ظاهر می شود

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

وابستگی ها

فایل app build.gradle را به‌روزرسانی کنید تا وابستگی‌های کتابخانه لازم را شامل شود:

dependencies {
    implementation 'androidx.appcompat:appcompat:1.5.0'
    implementation 'androidx.mediarouter:mediarouter:1.3.1'
    implementation 'androidx.recyclerview:recyclerview:1.2.1'
    implementation 'com.google.android.gms:play-services-cast-framework:21.1.0'
    implementation 'com.android.volley:volley:1.2.1'
    implementation "androidx.core:core-ktx:1.8.0"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}

پروژه را همگام‌سازی کنید تا ساخت‌های پروژه بدون خطا تأیید شود.

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

چارچوب Cast دارای یک شی تک‌تنی جهانی به CastContext است که همه تعاملات Cast را هماهنگ می‌کند.

شما باید رابط OptionsProvider را برای تامین CastOptions مورد نیاز برای مقداردهی اولیه CastContext singleton پیاده سازی کنید. مهمترین گزینه شناسه برنامه گیرنده است که برای فیلتر کردن نتایج کشف دستگاه Cast و راه اندازی برنامه گیرنده هنگام شروع جلسه Cast استفاده می شود.

هنگامی که برنامه خود را با قابلیت Cast خود توسعه می دهید، باید به عنوان توسعه دهنده Cast ثبت نام کنید و سپس یک شناسه برنامه برای برنامه خود دریافت کنید. برای این کد لبه، از یک شناسه برنامه نمونه استفاده خواهیم کرد.

فایل جدید CastOptionsProvider.kt زیر را به بسته com.google.sample.cast.refplayer پروژه اضافه کنید:

package com.google.sample.cast.refplayer

import android.content.Context
import com.google.android.gms.cast.framework.OptionsProvider
import com.google.android.gms.cast.framework.CastOptions
import com.google.android.gms.cast.framework.SessionProvider

class CastOptionsProvider : OptionsProvider {
    override fun getCastOptions(context: Context): CastOptions {
        return CastOptions.Builder()
                .setReceiverApplicationId(context.getString(R.string.app_id))
                .build()
    }

    override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? {
        return null
    }
}

اکنون OptionsProvider در تگ " application " برنامه AndroidManifest.xml اعلام کنید:

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

با تنبلی CastContext را در متد VideoBrowserActivity onCreate مقداردهی کنید:

import com.google.android.gms.cast.framework.CastContext

private var mCastContext: CastContext? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.video_browser)
    setupActionBar()

    mCastContext = CastContext.getSharedInstance(this)
}

همان منطق اولیه سازی را به LocalPlayerActivity اضافه کنید.

دکمه Cast

اکنون که CastContext مقداردهی اولیه شده است، باید دکمه Cast را اضافه کنیم تا کاربر بتواند یک دستگاه Cast را انتخاب کند. دکمه Cast توسط MediaRouteButton از کتابخانه پشتیبانی MediaRouter پیاده سازی شده است. مانند هر نماد عملی که می توانید به فعالیت خود اضافه کنید (با استفاده از ActionBar یا Toolbar )، ابتدا باید آیتم منوی مربوطه را به منوی خود اضافه کنید.

فایل res/menu/browse.xml را ویرایش کنید و آیتم MediaRouteActionProvider را در منو قبل از آیتم تنظیمات اضافه کنید:

<item
    android:id="@+id/media_route_menu_item"
    android:title="@string/media_route_menu_title"
    app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
    app:showAsAction="always"/>

با استفاده از CastButtonFactory برای اتصال MediaRouteButton به چارچوب Cast، روش onCreateOptionsMenu() از VideoBrowserActivity نادیده بگیرید:

import com.google.android.gms.cast.framework.CastButtonFactory

private var mediaRouteMenuItem: MenuItem? = null

override fun onCreateOptionsMenu(menu: Menu): Boolean {
     super.onCreateOptionsMenu(menu)
     menuInflater.inflate(R.menu.browse, menu)
     mediaRouteMenuItem = CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), menu,
                R.id.media_route_menu_item)
     return true
}

به روشی مشابه، onCreateOptionsMenu در LocalPlayerActivity لغو کنید.

را کلیک کنید دکمه اجرای اندروید استودیو، یک مثلث سبز رنگ که به سمت راست اشاره می کند دکمه اجرا برای اجرای برنامه در دستگاه تلفن همراه شما. باید یک دکمه Cast را در نوار عملکرد برنامه ببینید و وقتی روی آن کلیک می‌کنید، دستگاه‌های Cast را در شبکه محلی شما فهرست می‌کند. کشف دستگاه به طور خودکار توسط CastContext مدیریت می شود. دستگاه Cast خود را انتخاب کنید و برنامه گیرنده نمونه در دستگاه Cast بارگیری می‌شود. می توانید بین فعالیت مرور و فعالیت پخش کننده محلی حرکت کنید و وضعیت دکمه Cast همگام نگه داشته می شود.

ما هیچ پشتیبانی برای پخش رسانه وصل نکرده‌ایم، بنابراین هنوز نمی‌توانید ویدیوها را در دستگاه Cast پخش کنید. برای قطع ارتباط روی دکمه Cast کلیک کنید.

6. پخش محتوای ویدیویی

تصویری از یک تلفن Android که برنامه «Cast Videos» را اجرا می‌کند

ما برنامه نمونه را گسترش می‌دهیم تا ویدیوها را از راه دور در دستگاه Cast پخش کند. برای انجام این کار، باید به رویدادهای مختلف تولید شده توسط چارچوب Cast گوش دهیم.

پخش رسانه

در سطح بالا، اگر می‌خواهید رسانه‌ای را در دستگاه Cast پخش کنید، باید این کارها را انجام دهید:

  1. یک شی MediaInfo ایجاد کنید که یک آیتم رسانه را مدل می کند.
  2. به دستگاه Cast متصل شوید و برنامه گیرنده خود را راه اندازی کنید.
  3. شی MediaInfo را در گیرنده خود بارگذاری کنید و محتوا را پخش کنید.
  4. وضعیت رسانه را پیگیری کنید.
  5. دستورات پخش را بر اساس تعاملات کاربر به گیرنده ارسال کنید.

ما قبلاً مرحله 2 را در بخش قبل انجام داده ایم. انجام مرحله 3 با چارچوب Cast آسان است. مرحله 1 معادل نگاشت یک شی به شی دیگر است. MediaInfo چیزی است که چارچوب Cast آن را درک می کند و MediaItem محفظه برنامه ما برای یک آیتم رسانه است. ما به راحتی می توانیم یک MediaItem را به MediaInfo نگاشت کنیم.

برنامه نمونه LocalPlayerActivity از قبل با استفاده از این فهرست، بین پخش محلی و از راه دور تمایز قائل می شود:

private var mLocation: PlaybackLocation? = null

enum class PlaybackLocation {
    LOCAL, REMOTE
}

enum class PlaybackState {
    PLAYING, PAUSED, BUFFERING, IDLE
}

در این کد لبه برای شما مهم نیست که بدانید دقیقاً چگونه منطق پخش کننده نمونه کار می کند. درک این نکته مهم است که پخش کننده رسانه برنامه شما باید اصلاح شود تا از دو مکان پخش به روشی مشابه آگاه باشد.

در حال حاضر پخش کننده محلی همیشه در حالت پخش محلی است زیرا هنوز چیزی در مورد وضعیت های Casting نمی داند. ما باید رابط کاربری را بر اساس انتقال وضعیتی که در چارچوب Cast اتفاق می‌افتد، به‌روزرسانی کنیم. به عنوان مثال، اگر شروع به ارسال محتوا کنیم، باید پخش محلی را متوقف کنیم و برخی از کنترل ها را غیرفعال کنیم. به طور مشابه، اگر زمانی که در این فعالیت هستیم، بازیگران را متوقف کنیم، باید به پخش محلی منتقل شویم. برای رسیدگی به آن باید به رویدادهای مختلف تولید شده توسط چارچوب Cast گوش دهیم.

مدیریت جلسه بازیگران

برای چارچوب Cast، یک جلسه Cast مراحل اتصال به یک دستگاه، راه‌اندازی (یا پیوستن)، اتصال به یک برنامه گیرنده، و راه‌اندازی یک کانال کنترل رسانه را در صورت لزوم ترکیب می‌کند. کانال کنترل رسانه نحوه ارسال و دریافت پیام‌ها از پخش‌کننده رسانه گیرنده توسط چارچوب Cast است.

وقتی کاربر دستگاهی را از روی دکمه Cast انتخاب می‌کند، جلسه Cast به‌طور خودکار شروع می‌شود و وقتی کاربر ارتباط خود را قطع می‌کند، به‌طور خودکار متوقف می‌شود. اتصال مجدد به جلسه گیرنده به دلیل مشکلات شبکه نیز به طور خودکار توسط Cast SDK انجام می شود.

بیایید یک SessionManagerListener به LocalPlayerActivity اضافه کنیم:

import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.cast.framework.SessionManagerListener
...

private var mSessionManagerListener: SessionManagerListener<CastSession>? = null
private var mCastSession: CastSession? = null
...

private fun setupCastListener() {
    mSessionManagerListener = object : SessionManagerListener<CastSession> {
        override fun onSessionEnded(session: CastSession, error: Int) {
            onApplicationDisconnected()
        }

        override fun onSessionResumed(session: CastSession, wasSuspended: Boolean) {
            onApplicationConnected(session)
        }

        override fun onSessionResumeFailed(session: CastSession, error: Int) {
            onApplicationDisconnected()
        }

        override fun onSessionStarted(session: CastSession, sessionId: String) {
            onApplicationConnected(session)
        }

        override fun onSessionStartFailed(session: CastSession, error: Int) {
            onApplicationDisconnected()
        }

        override fun onSessionStarting(session: CastSession) {}
        override fun onSessionEnding(session: CastSession) {}
        override fun onSessionResuming(session: CastSession, sessionId: String) {}
        override fun onSessionSuspended(session: CastSession, reason: Int) {}
        private fun onApplicationConnected(castSession: CastSession) {
            mCastSession = castSession
            if (null != mSelectedMedia) {
                if (mPlaybackState == PlaybackState.PLAYING) {
                    mVideoView!!.pause()
                    loadRemoteMedia(mSeekbar!!.progress, true)
                    return
                } else {
                    mPlaybackState = PlaybackState.IDLE
                    updatePlaybackLocation(PlaybackLocation.REMOTE)
                }
            }
            updatePlayButton(mPlaybackState)
            invalidateOptionsMenu()
        }

        private fun onApplicationDisconnected() {
            updatePlaybackLocation(PlaybackLocation.LOCAL)
            mPlaybackState = PlaybackState.IDLE
            mLocation = PlaybackLocation.LOCAL
            updatePlayButton(mPlaybackState)
            invalidateOptionsMenu()
       }
   }
}

در فعالیت LocalPlayerActivity ، ما علاقه مندیم که از اتصال یا قطع ارتباط ما با دستگاه Cast مطلع شویم تا بتوانیم به پخش کننده محلی یا از آن جابجا شویم. توجه داشته باشید که اتصال می‌تواند نه تنها با نمونه‌ای از برنامه‌ای که در دستگاه تلفن همراه شما اجرا می‌شود، بلکه می‌تواند توسط نمونه دیگری از برنامه شما (یا دیگری) که در دستگاه تلفن همراه دیگری اجرا می‌شود، مختل شود.

جلسه فعال فعلی با نام SessionManager.getCurrentSession() قابل دسترسی است. در پاسخ به تعامل کاربر با گفتگوهای Cast، جلسات به طور خودکار ایجاد و حذف می شوند.

ما باید شنود جلسه خود را ثبت کنیم و برخی از متغیرهایی را که در اکتیویتی استفاده خواهیم کرد مقداردهی اولیه کنیم. متد LocalPlayerActivity onCreate را به:

import com.google.android.gms.cast.framework.CastContext
...

private var mCastContext: CastContext? = null
...

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    mCastContext = CastContext.getSharedInstance(this)
    mCastSession = mCastContext!!.sessionManager.currentCastSession
    setupCastListener()
    ...
    loadViews()
    ...
    val bundle = intent.extras
    if (bundle != null) {
        ....
        if (shouldStartPlayback) {
              ....

        } else {
            if (mCastSession != null && mCastSession!!.isConnected()) {
                updatePlaybackLocation(PlaybackLocation.REMOTE)
            } else {
                updatePlaybackLocation(PlaybackLocation.LOCAL)
            }
            mPlaybackState = PlaybackState.IDLE
            updatePlayButton(mPlaybackState)
        }
    }
    ...
}

در حال بارگیری رسانه

در Cast SDK، RemoteMediaClient مجموعه‌ای از APIهای راحت را برای مدیریت پخش رسانه از راه دور در گیرنده فراهم می‌کند. برای CastSession که از پخش رسانه پشتیبانی می کند، یک نمونه از RemoteMediaClient به طور خودکار توسط SDK ایجاد می شود. با فراخوانی متد getRemoteMediaClient() در نمونه CastSession قابل دسترسی است. روش های زیر را به LocalPlayerActivity اضافه کنید تا ویدیوی انتخابی فعلی را روی گیرنده بارگیری کنید:

import com.google.android.gms.cast.framework.media.RemoteMediaClient
import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaLoadOptions
import com.google.android.gms.cast.MediaMetadata
import com.google.android.gms.common.images.WebImage
import com.google.android.gms.cast.MediaLoadRequestData

private fun loadRemoteMedia(position: Int, autoPlay: Boolean) {
    if (mCastSession == null) {
        return
    }
    val remoteMediaClient = mCastSession!!.remoteMediaClient ?: return
    remoteMediaClient.load( MediaLoadRequestData.Builder()
                .setMediaInfo(buildMediaInfo())
                .setAutoplay(autoPlay)
                .setCurrentTime(position.toLong()).build())
}

private fun buildMediaInfo(): MediaInfo? {
    val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE)
    mSelectedMedia?.studio?.let { movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, it) }
    mSelectedMedia?.title?.let { movieMetadata.putString(MediaMetadata.KEY_TITLE, it) }
    movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia!!.getImage(0))))
    movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia!!.getImage(1))))
    return mSelectedMedia!!.url?.let {
        MediaInfo.Builder(it)
            .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
            .setContentType("videos/mp4")
            .setMetadata(movieMetadata)
            .setStreamDuration((mSelectedMedia!!.duration * 1000).toLong())
            .build()
    }
}

اکنون روش های مختلف موجود را برای استفاده از منطق جلسه Cast برای پشتیبانی از پخش از راه دور به روز کنید:

private fun play(position: Int) {
    startControllersTimer()
    when (mLocation) {
        PlaybackLocation.LOCAL -> {
            mVideoView!!.seekTo(position)
            mVideoView!!.start()
        }
        PlaybackLocation.REMOTE -> {
            mPlaybackState = PlaybackState.BUFFERING
            updatePlayButton(mPlaybackState)
            //seek to a new position within the current media item's new position 
            //which is in milliseconds from the beginning of the stream
            mCastSession!!.remoteMediaClient?.seek(position.toLong())
        }
        else -> {}
    }
    restartTrickplayTimer()
}
private fun togglePlayback() {
    ...
    PlaybackState.IDLE -> when (mLocation) {
        ...
        PlaybackLocation.REMOTE -> {
            if (mCastSession != null && mCastSession!!.isConnected) {
                loadRemoteMedia(mSeekbar!!.progress, true)
            }
        }
        else -> {}
    }
    ...
}
override fun onPause() {
    ...
    mCastContext!!.sessionManager.removeSessionManagerListener(
                mSessionManagerListener!!, CastSession::class.java)
}
override fun onResume() {
    Log.d(TAG, "onResume() was called")
    mCastContext!!.sessionManager.addSessionManagerListener(
            mSessionManagerListener!!, CastSession::class.java)
    if (mCastSession != null && mCastSession!!.isConnected) {
        updatePlaybackLocation(PlaybackLocation.REMOTE)
    } else {
        updatePlaybackLocation(PlaybackLocation.LOCAL)
    }
    super.onResume()
}

برای متد updatePlayButton ، مقدار متغیر isConnected را تغییر دهید:

private fun updatePlayButton(state: PlaybackState?) {
    ...
    val isConnected = (mCastSession != null
                && (mCastSession!!.isConnected || mCastSession!!.isConnecting))
    ...
}

اکنون، روی دکمه Run اندروید استودیو، یک مثلث سبز رنگ که به سمت راست اشاره می کند دکمه اجرا برای اجرای برنامه در دستگاه تلفن همراه شما. به دستگاه Cast خود متصل شوید و شروع به پخش ویدیو کنید. شما باید ویدیو را در حال پخش روی گیرنده ببینید.

7. مینی کنترلر

چک لیست طراحی Cast مستلزم آن است که همه برنامه‌های Cast یک کنترل‌کننده کوچک ارائه دهند که وقتی کاربر از صفحه محتوای فعلی دور می‌شود ظاهر شود. مینی کنترلر دسترسی فوری و یک یادآوری قابل مشاهده را برای جلسه Cast فعلی فراهم می کند.

تصویر قسمت پایینی تلفن Android که پخش کننده کوچک را در برنامه Cast Videos نشان می دهد

Cast SDK یک نمای سفارشی، MiniControllerFragment ارائه می‌کند، که می‌تواند به فایل طرح‌بندی برنامه فعالیت‌هایی که می‌خواهید کنترل‌کننده کوچک را در آنها نشان دهید اضافه شود.

تعریف قطعه زیر را به پایین هر دو res/layout/player_activity.xml و res/layout/video_browser.xml اضافه کنید:

<fragment
    android:id="@+id/castMiniController"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:visibility="gone"
    class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment"/>

را کلیک کنید دکمه اجرای اندروید استودیو، یک مثلث سبز رنگ که به سمت راست اشاره می کند دکمه اجرا برای اجرای برنامه و پخش ویدیو. هنگامی که پخش در گیرنده شروع می شود، باید مینی کنترلر را در پایین هر فعالیت مشاهده کنید. با استفاده از مینی کنترلر می توانید پخش از راه دور را کنترل کنید. اگر بین فعالیت مرور و فعالیت پخش کننده محلی حرکت کنید، وضعیت مینی کنترلر باید با وضعیت پخش رسانه گیرنده همگام باشد.

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

چک لیست طراحی Google Cast به یک برنامه فرستنده نیاز دارد تا کنترل‌های رسانه را از یک اعلان و صفحه قفل اجرا کند.

تصویر یک تلفن Android که کنترل‌های رسانه را در قسمت اعلان‌ها نشان می‌دهد

Cast SDK یک MediaNotificationService برای کمک به برنامه فرستنده در ساخت کنترل‌های رسانه برای اعلان و صفحه قفل ارائه می‌کند. این سرویس به صورت خودکار در مانیفست برنامه شما ادغام می شود.

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

هنگام تنظیم اولیه CastContext کنترل‌های اعلان و صفحه قفل را می‌توان با CastOptions فعال کرد. کنترل های رسانه برای اعلان و صفحه قفل به طور پیش فرض روشن هستند. تا زمانی که اعلان روشن باشد، ویژگی صفحه قفل روشن است.

CastOptionsProvider را ویرایش کنید و پیاده سازی getCastOptions را برای مطابقت با این کد تغییر دهید:

import com.google.android.gms.cast.framework.media.CastMediaOptions
import com.google.android.gms.cast.framework.media.NotificationOptions

override fun getCastOptions(context: Context): CastOptions {
   val notificationOptions = NotificationOptions.Builder()
            .setTargetActivityClassName(VideoBrowserActivity::class.java.name)
            .build()
    val mediaOptions = CastMediaOptions.Builder()
            .setNotificationOptions(notificationOptions)
            .build()
   return CastOptions.Builder()
                .setReceiverApplicationId(context.getString(R.string.app_id))
                .setCastMediaOptions(mediaOptions)
                .build()
}

را کلیک کنید دکمه Run اندروید استودیو، یک مثلث سبز رنگ که به سمت راست اشاره می کند دکمه اجرا برای اجرای برنامه در دستگاه تلفن همراه شما. یک ویدیو ارسال کنید و از برنامه نمونه دور شوید. برای ویدیویی که در حال حاضر روی گیرنده پخش می شود باید یک اعلان وجود داشته باشد. دستگاه همراه خود را قفل کنید و صفحه قفل اکنون باید کنترل‌هایی را برای پخش رسانه در دستگاه Cast نشان دهد.

تصویر یک تلفن Android که کنترل‌های رسانه را روی صفحه قفل نشان می‌دهد

9. پوشش مقدماتی

چک لیست طراحی Google Cast به یک برنامه فرستنده نیاز دارد تا دکمه Cast را به کاربران فعلی معرفی کند تا به آنها اطلاع دهد که برنامه فرستنده اکنون از ارسال محتوا پشتیبانی می کند و همچنین به کاربران تازه وارد Google Cast کمک می کند.

تصویری که پوشش مقدماتی Cast را در اطراف دکمه Cast در برنامه Cast Videos Android نشان می‌دهد

Cast SDK یک نمای سفارشی به IntroductoryOverlay را ارائه می دهد که می تواند برای برجسته کردن دکمه Cast در اولین نمایش داده شدن به کاربران استفاده شود. کد زیر را به VideoBrowserActivity اضافه کنید:

import com.google.android.gms.cast.framework.IntroductoryOverlay
import android.os.Looper

private var mIntroductoryOverlay: IntroductoryOverlay? = null

private fun showIntroductoryOverlay() {
    mIntroductoryOverlay?.remove()
    if (mediaRouteMenuItem?.isVisible == true) {
       Looper.myLooper().run {
           mIntroductoryOverlay = com.google.android.gms.cast.framework.IntroductoryOverlay.Builder(
                    this@VideoBrowserActivity, mediaRouteMenuItem!!)
                   .setTitleText("Introducing Cast")
                   .setSingleTime()
                   .setOnOverlayDismissedListener(
                           object : IntroductoryOverlay.OnOverlayDismissedListener {
                               override fun onOverlayDismissed() {
                                   mIntroductoryOverlay = null
                               }
                          })
                   .build()
          mIntroductoryOverlay!!.show()
        }
    }
}

اکنون، یک CastStateListener اضافه کنید و onPause که یک دستگاه Cast در دسترس است onCreate onResume showIntroductoryOverlay را فراخوانی کنید.

import com.google.android.gms.cast.framework.CastState
import com.google.android.gms.cast.framework.CastStateListener

private var mCastStateListener: CastStateListener? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.video_browser)
    setupActionBar()
    mCastStateListener = object : CastStateListener {
            override fun onCastStateChanged(newState: Int) {
                if (newState != CastState.NO_DEVICES_AVAILABLE) {
                    showIntroductoryOverlay()
                }
            }
        }
    mCastContext = CastContext.getSharedInstance(this)
}

override fun onResume() {
    super.onResume()
    mCastContext?.addCastStateListener(mCastStateListener!!)
}

override fun onPause() {
    super.onPause()
    mCastContext?.removeCastStateListener(mCastStateListener!!)
}

داده های برنامه را پاک کنید یا برنامه را از دستگاه خود حذف کنید. سپس، روی دکمه Run اندروید استودیو، یک مثلث سبز رنگ که به سمت راست اشاره می کند دکمه اجرا برای اجرای برنامه در دستگاه تلفن همراه خود و باید پوشش مقدماتی را مشاهده کنید (اگر همپوشانی نمایش داده نشد، داده های برنامه را پاک کنید).

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

چک‌لیست طراحی Google Cast به یک برنامه فرستنده نیاز دارد تا کنترل‌کننده گسترده‌ای را برای رسانه در حال پخش فراهم کند. کنترلر توسعه یافته یک نسخه تمام صفحه از مینی کنترلر است.

تصویری از یک ویدیو در حال پخش در تلفن اندرویدی که کنترلر گسترش یافته روی آن قرار گرفته است

Cast SDK ویجتی را برای کنترلر توسعه یافته به نام ExpandedControllerActivity فراهم می کند. این یک کلاس انتزاعی است که برای اضافه کردن دکمه Cast باید آن را زیر کلاس قرار دهید.

ابتدا یک فایل منبع منوی جدید به نام expanded_controller.xml ایجاد کنید تا کنترلر توسعه یافته دکمه Cast را ارائه دهد:

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
            android:id="@+id/media_route_menu_item"
            android:title="@string/media_route_menu_title"
            app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
            app:showAsAction="always"/>

</menu>

یک بسته جدید expandedcontrols در بسته com.google.sample.cast.refplayer ایجاد کنید. سپس یک فایل جدید به نام ExpandedControlsActivity.kt در بسته com.google.sample.cast.refplayer.expandedcontrols ایجاد کنید.

package com.google.sample.cast.refplayer.expandedcontrols

import android.view.Menu
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity
import com.google.sample.cast.refplayer.R
import com.google.android.gms.cast.framework.CastButtonFactory

class ExpandedControlsActivity : ExpandedControllerActivity() {
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        super.onCreateOptionsMenu(menu)
        menuInflater.inflate(R.menu.expanded_controller, menu)
        CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item)
        return true
    }
}

اکنون ExpandedControlsActivity را در AndroidManifest.xml در تگ application بالای OPTIONS_PROVIDER_CLASS_NAME اعلام کنید:

<application>
    ...
    <activity
        android:name="com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity"
        android:label="@string/app_name"
        android:launchMode="singleTask"
        android:theme="@style/Theme.CastVideosDark"
        android:screenOrientation="portrait"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
        </intent-filter>
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.google.sample.cast.refplayer.VideoBrowserActivity"/>
    </activity>
    ...
</application>

CastOptionsProvider را ویرایش کنید و NotificationOptions و CastMediaOptions تغییر دهید تا فعالیت هدف را روی ExpandedControlsActivity تنظیم کنید:

import com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity

override fun getCastOptions(context: Context): CastOptions {
    val notificationOptions = NotificationOptions.Builder()
            .setTargetActivityClassName(ExpandedControlsActivity::class.java.name)
            .build()
    val mediaOptions = CastMediaOptions.Builder()
            .setNotificationOptions(notificationOptions)
            .setExpandedControllerActivityClassName(ExpandedControlsActivity::class.java.name)
            .build()
    return CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .setCastMediaOptions(mediaOptions)
            .build()
}

روش LocalPlayerActivity loadRemoteMedia را برای نمایش ExpandedControlsActivity هنگام بارگیری رسانه راه دور به روز کنید:

import com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity

private fun loadRemoteMedia(position: Int, autoPlay: Boolean) {
    if (mCastSession == null) {
        return
    }
    val remoteMediaClient = mCastSession!!.remoteMediaClient ?: return
    remoteMediaClient.registerCallback(object : RemoteMediaClient.Callback() {
        override fun onStatusUpdated() {
            val intent = Intent(this@LocalPlayerActivity, ExpandedControlsActivity::class.java)
            startActivity(intent)
            remoteMediaClient.unregisterCallback(this)
        }
    })
    remoteMediaClient.load(MediaLoadRequestData.Builder()
                .setMediaInfo(buildMediaInfo())
                .setAutoplay(autoPlay)
                .setCurrentTime(position.toLong()).build())
}

را کلیک کنید دکمه اجرای اندروید استودیو، یک مثلث سبز رنگ که به سمت راست اشاره می کند دکمه اجرا برای اجرای برنامه در دستگاه تلفن همراه و پخش ویدیو. باید کنترلر گسترش یافته را ببینید. به لیست ویدیوها برگردید و با کلیک بر روی مینی کنترلر، کنترلر باز شده دوباره بارگذاری می شود. برای دیدن اعلان از برنامه دور شوید. روی تصویر اعلان کلیک کنید تا کنترلر توسعه یافته بارگیری شود.

11. پشتیبانی Cast Connect را اضافه کنید

کتابخانه Cast Connect به برنامه‌های فرستنده موجود اجازه می‌دهد با برنامه‌های Android TV از طریق پروتکل Cast ارتباط برقرار کنند. Cast Connect در بالای زیرساخت Cast ساخته می شود و برنامه Android TV شما به عنوان گیرنده عمل می کند.

وابستگی ها

توجه: برای اجرای Cast Connect، play-services-cast-framework باید 19.0.0 یا بالاتر باشد.

گزینه های راه اندازی

برای راه‌اندازی برنامه Android TV که به آن گیرنده Android نیز گفته می‌شود، باید پرچم setAndroidReceiverCompatible را در شی LaunchOptions روی true تنظیم کنیم. این شی LaunchOptions نحوه راه اندازی گیرنده را دیکته می کند و به CastOptions ارسال شده توسط کلاس CastOptionsProvider ارسال می شود. با تنظیم پرچم ذکر شده در بالا روی false ، گیرنده وب برای شناسه برنامه تعریف شده در کنسول توسعه دهنده Cast راه اندازی می شود.

در فایل CastOptionsProvider.kt موارد زیر را به متد getCastOptions اضافه کنید:

import com.google.android.gms.cast.LaunchOptions
...
val launchOptions = LaunchOptions.Builder()
            .setAndroidReceiverCompatible(true)
            .build()
return new CastOptions.Builder()
        .setLaunchOptions(launchOptions)
        ...
        .build()

اعتبار راه اندازی را تنظیم کنید

در سمت فرستنده، می‌توانید CredentialsData برای نشان دادن افرادی که به جلسه می‌پیوندند، مشخص کنید. credentials رشته ای است که می تواند توسط کاربر تعریف شود، تا زمانی که برنامه ATV شما بتواند آن را درک کند. CredentialsData فقط در زمان راه‌اندازی یا زمان پیوستن به برنامه Android TV شما منتقل می‌شود. اگر در حین اتصال دوباره آن را تنظیم کنید، به برنامه Android TV شما منتقل نخواهد شد.

برای تنظیم Launch Credentials CredentialsData باید تعریف شده و به شی LaunchOptions ارسال شود. کد زیر را به متد getCastOptions در فایل CastOptionsProvider.kt خود اضافه کنید:

import com.google.android.gms.cast.CredentialsData
...

val credentialsData = CredentialsData.Builder()
        .setCredentials("{\"userId\": \"abc\"}")
        .build()
val launchOptions = LaunchOptions.Builder()
       ...
       .setCredentialsData(credentialsData)
       .build()

اعتبارنامه ها را در LoadRequest تنظیم کنید

در صورتی که برنامه گیرنده وب و برنامه Android TV شما credentials به طور متفاوتی مدیریت می کنند، ممکن است لازم باشد برای هر کدام credentials جداگانه تعریف کنید. به منظور مراقبت از آن، کد زیر را در فایل LocalPlayerActivity.kt خود در تابع loadRemoteMedia اضافه کنید:

remoteMediaClient.load(MediaLoadRequestData.Builder()
       ...
       .setCredentials("user-credentials")
       .setAtvCredentials("atv-user-credentials")
       .build())

بسته به برنامه گیرنده‌ای که فرستنده شما به آن ارسال می‌کند، SDK اکنون به‌طور خودکار بررسی می‌کند که از کدام اعتبارنامه‌ها برای جلسه جاری استفاده کند.

آزمایش Cast Connect

مراحل نصب Android TV APK در Chromecast با Google TV

  1. آدرس IP دستگاه Android TV خود را پیدا کنید. معمولاً در تنظیمات > شبکه و اینترنت > (نام شبکه ای که دستگاه شما به آن متصل است) در دسترس است. در سمت راست، جزئیات و IP دستگاه شما را در شبکه نشان می دهد.
  2. از آدرس IP دستگاه خود برای اتصال از طریق ADB با استفاده از ترمینال به آن استفاده کنید:
$ adb connect <device_ip_address>:5555
  1. از پنجره ترمینال خود، به پوشه سطح بالا برای نمونه‌های Codelab که در ابتدای این کد لبه دانلود کرده‌اید، بروید. به عنوان مثال:
$ cd Desktop/android_codelab_src
  1. فایل apk. را در این پوشه در Android TV خود با اجرای زیر نصب کنید:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
  1. اکنون باید بتوانید برنامه ای به نام Cast Videos را در منوی برنامه های شما در دستگاه Android TV خود مشاهده کنید.
  2. به پروژه Android Studio خود بازگردید و روی دکمه Run کلیک کنید تا برنامه فرستنده را در دستگاه تلفن همراه فیزیکی خود نصب و اجرا کنید. در گوشه سمت راست بالا، روی نماد Cast کلیک کنید و دستگاه Android TV خود را از گزینه‌های موجود انتخاب کنید. اکنون باید برنامه Android TV را مشاهده کنید که در دستگاه Android TV شما راه اندازی شده است و پخش یک ویدیو به شما امکان می دهد تا با استفاده از کنترل از راه دور Android TV خود، پخش ویدیو را کنترل کنید.

12. ویجت های Cast را سفارشی کنید

می‌توانید ویجت‌های Cast را با تنظیم رنگ‌ها، شکل دادن به دکمه‌ها، متن و ظاهر تصاویر کوچک، و با انتخاب انواع دکمه‌ها برای نمایش، سفارشی کنید.

res/values/styles_castvideo.xml را به روز کنید

<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item>
    <item name="castIntroOverlayStyle">@style/CustomCastIntroOverlay</item>
    <item name="castMiniControllerStyle">@style/CustomCastMiniController</item>
    <item name="castExpandedControllerStyle">@style/CustomCastExpandedController</item>
    <item name="castExpandedControllerToolbarStyle">
        @style/ThemeOverlay.AppCompat.ActionBar
    </item>
    ...
</style>

تم های سفارشی زیر را اعلام کنید:

<!-- Customize Cast Button -->
<style name="CustomMediaRouterTheme" parent="Theme.MediaRouter">
    <item name="mediaRouteButtonStyle">@style/CustomMediaRouteButtonStyle</item>
</style>
<style name="CustomMediaRouteButtonStyle" parent="Widget.MediaRouter.Light.MediaRouteButton">
    <item name="mediaRouteButtonTint">#EEFF41</item>
</style>

<!-- Customize Introductory Overlay -->
<style name="CustomCastIntroOverlay" parent="CastIntroOverlay">
    <item name="castButtonTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Button</item>
    <item name="castTitleTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Title</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Button" parent="android:style/TextAppearance">
    <item name="android:textColor">#FFFFFF</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Title" parent="android:style/TextAppearance.Large">
    <item name="android:textColor">#FFFFFF</item>
</style>

<!-- Customize Mini Controller -->
<style name="CustomCastMiniController" parent="CastMiniController">
    <item name="castShowImageThumbnail">true</item>
    <item name="castTitleTextAppearance">@style/TextAppearance.AppCompat.Subhead</item>
    <item name="castSubtitleTextAppearance">@style/TextAppearance.AppCompat.Caption</item>
    <item name="castBackground">@color/accent</item>
    <item name="castProgressBarColor">@color/orange</item>
</style>

<!-- Customize Expanded Controller -->
<style name="CustomCastExpandedController" parent="CastExpandedController">
    <item name="castButtonColor">#FFFFFF</item>
    <item name="castPlayButtonDrawable">@drawable/cast_ic_expanded_controller_play</item>
    <item name="castPauseButtonDrawable">@drawable/cast_ic_expanded_controller_pause</item>
    <item name="castStopButtonDrawable">@drawable/cast_ic_expanded_controller_stop</item>
</style>

13. تبریک می گویم

اکنون می‌دانید که چگونه می‌توانید یک برنامه ویدیویی را با استفاده از ابزارک‌های Cast SDK در Android فعال کنید.

برای جزئیات بیشتر، راهنمای برنامه‌نویس Android Sender را ببینید.