1. بررسی اجمالی
این کد لبه به شما می آموزد که چگونه یک برنامه ویدیویی موجود در اندروید را برای ارسال محتوا در یک دستگاه دارای 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 کلیک کنید.
روی فایل > کلیک کنید همگام سازی پروژه با فایل های Gradle .
اشکال زدایی USB را در دستگاه Android خود فعال کنید - در اندروید 4.2 و بالاتر، صفحه گزینه های برنامه نویس به طور پیش فرض پنهان است. برای اینکه آن را قابل مشاهده کنید، به Settings > About phone بروید و هفت بار روی Build number ضربه بزنید. به صفحه قبلی بازگردید، به System > Advanced بروید و روی Developer options نزدیک پایین ضربه بزنید، سپس روی USB debugging ضربه بزنید تا روشن شود.
دستگاه اندروید خود را وصل کنید و روی آن کلیک کنید دکمه اجرا در اندروید استودیو. پس از چند ثانیه باید ببینید که برنامه ویدیویی با نام Cast Videos ظاهر می شود.
روی دکمه Cast در برنامه ویدیو کلیک کنید و دستگاه Google Cast خود را انتخاب کنید.
یک ویدیو را انتخاب کنید و روی دکمه پخش کلیک کنید.
پخش ویدیو در دستگاه Google Cast شما شروع می شود.
کنترل کننده گسترش یافته نمایش داده می شود. می توانید از دکمه پخش/مکث برای کنترل پخش استفاده کنید.
به لیست ویدیوها برگردید.
اکنون یک مینی کنترلر در پایین صفحه قابل مشاهده است.
روی دکمه مکث در کنترلر کوچک کلیک کنید تا ویدیو روی گیرنده متوقف شود. برای ادامه پخش مجدد ویدیو، روی دکمه پخش در مینی کنترلر کلیک کنید.
روی دکمه هوم دستگاه موبایل کلیک کنید. اعلانها را پایین بکشید و اکنون باید یک اعلان برای جلسه Cast ببینید.
تلفن خود را قفل کنید و وقتی قفل آن را باز می کنید، باید اعلانی را روی صفحه قفل مشاهده کنید تا پخش رسانه را کنترل کنید یا ارسال را متوقف کنید.
به برنامه ویدیو برگردید و روی دکمه Cast کلیک کنید تا ارسال محتوا در دستگاه Google Cast متوقف شود.
سوالات متداول
4. پروژه شروع را آماده کنید
باید پشتیبانی از Google Cast را به برنامه شروعی که دانلود کردید اضافه کنیم. در اینجا برخی از اصطلاحات Google Cast وجود دارد که در این لبه کد استفاده خواهیم کرد:
- یک برنامه فرستنده روی دستگاه تلفن همراه یا لپ تاپ اجرا می شود،
- یک برنامه گیرنده در دستگاه Google Cast اجرا می شود.
اکنون شما آماده هستید تا با استفاده از Android Studio روی پروژه شروع کننده ایجاد کنید:
- را انتخاب کنید دایرکتوری
app-start
از دانلود کد نمونه خود ( وارد کردن پروژه را در صفحه خوش آمدگویی یا گزینه منو File > New > Import Project... را انتخاب کنید). - را کلیک کنید همگام سازی پروژه با دکمه Gradle Files .
- را کلیک کنید دکمه اجرا برای اجرای برنامه و کاوش در رابط کاربری.
طراحی اپلیکیشن
این برنامه لیستی از ویدیوها را از یک وب سرور راه دور دریافت می کند و فهرستی را برای مرورگر در اختیار کاربر قرار می دهد. کاربران می توانند یک ویدیو را برای دیدن جزئیات انتخاب کنند یا ویدیو را به صورت محلی در دستگاه تلفن همراه پخش کنند.
این برنامه از دو فعالیت اصلی تشکیل شده است: 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
یک برنامه با قابلیت 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. پخش محتوای ویدیویی
ما برنامه نمونه را گسترش میدهیم تا ویدیوها را از راه دور در دستگاه Cast پخش کند. برای انجام این کار، باید به رویدادهای مختلف تولید شده توسط چارچوب Cast گوش دهیم.
پخش رسانه
در سطح بالا، اگر میخواهید رسانهای را در دستگاه Cast پخش کنید، باید این کارها را انجام دهید:
- یک شی
MediaInfo
ایجاد کنید که یک آیتم رسانه را مدل می کند. - به دستگاه Cast متصل شوید و برنامه گیرنده خود را راه اندازی کنید.
- شی
MediaInfo
را در گیرنده خود بارگذاری کنید و محتوا را پخش کنید. - وضعیت رسانه را پیگیری کنید.
- دستورات پخش را بر اساس تعاملات کاربر به گیرنده ارسال کنید.
ما قبلاً مرحله 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))
...
}
اکنون، روی دکمه اجرا برای اجرای برنامه در دستگاه تلفن همراه شما. به دستگاه Cast خود متصل شوید و شروع به پخش ویدیو کنید. شما باید ویدیو را در حال پخش روی گیرنده ببینید.
7. مینی کنترلر
چک لیست طراحی Cast مستلزم آن است که همه برنامههای Cast یک کنترلکننده کوچک ارائه دهند که وقتی کاربر از صفحه محتوای فعلی دور میشود ظاهر شود. مینی کنترلر دسترسی فوری و یک یادآوری قابل مشاهده را برای جلسه Cast فعلی فراهم می کند.
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 به یک برنامه فرستنده نیاز دارد تا کنترلهای رسانه را از یک اعلان و صفحه قفل اجرا کند.
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()
}
را کلیک کنید دکمه اجرا برای اجرای برنامه در دستگاه تلفن همراه شما. یک ویدیو ارسال کنید و از برنامه نمونه دور شوید. برای ویدیویی که در حال حاضر روی گیرنده پخش می شود باید یک اعلان وجود داشته باشد. دستگاه همراه خود را قفل کنید و صفحه قفل اکنون باید کنترلهایی را برای پخش رسانه در دستگاه Cast نشان دهد.
9. پوشش مقدماتی
چک لیست طراحی Google Cast به یک برنامه فرستنده نیاز دارد تا دکمه Cast را به کاربران فعلی معرفی کند تا به آنها اطلاع دهد که برنامه فرستنده اکنون از ارسال محتوا پشتیبانی می کند و همچنین به کاربران تازه وارد Google Cast کمک می کند.
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!!)
}
داده های برنامه را پاک کنید یا برنامه را از دستگاه خود حذف کنید. سپس، روی دکمه اجرا برای اجرای برنامه در دستگاه تلفن همراه خود و باید پوشش مقدماتی را مشاهده کنید (اگر همپوشانی نمایش داده نشد، داده های برنامه را پاک کنید).
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
- آدرس IP دستگاه Android TV خود را پیدا کنید. معمولاً در تنظیمات > شبکه و اینترنت > (نام شبکه ای که دستگاه شما به آن متصل است) در دسترس است. در سمت راست، جزئیات و IP دستگاه شما را در شبکه نشان می دهد.
- از آدرس IP دستگاه خود برای اتصال از طریق ADB با استفاده از ترمینال به آن استفاده کنید:
$ adb connect <device_ip_address>:5555
- از پنجره ترمینال خود، به پوشه سطح بالا برای نمونههای Codelab که در ابتدای این کد لبه دانلود کردهاید، بروید. به عنوان مثال:
$ cd Desktop/android_codelab_src
- فایل apk. را در این پوشه در Android TV خود با اجرای زیر نصب کنید:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
- اکنون باید بتوانید برنامه ای به نام Cast Videos را در منوی برنامه های شما در دستگاه Android TV خود مشاهده کنید.
- به پروژه 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 را ببینید.