۱. مرور کلی

این آزمایشگاه کد به شما آموزش میدهد که چگونه یک برنامه ویدیویی iOS موجود را برای پخش محتوا روی دستگاهی که از Google Cast پشتیبانی میکند، تغییر دهید.
گوگل کست چیست؟
گوگل کست به کاربران اجازه میدهد محتوا را از دستگاه تلفن همراه خود به تلویزیون منتقل کنند. سپس کاربران میتوانند از دستگاه تلفن همراه خود به عنوان کنترل از راه دور برای پخش رسانه در تلویزیون استفاده کنند.
کیت توسعه نرمافزار گوگل کست (Google Cast SDK) به شما امکان میدهد برنامه خود را برای کنترل دستگاههای دارای قابلیت گوگل کست (مانند تلویزیون یا سیستم صوتی) گسترش دهید. کیت توسعه نرمافزار گوگل کست (Cast SDK) به شما امکان میدهد اجزای رابط کاربری لازم را بر اساس چک لیست طراحی گوگل کست (Google Cast Design Checklist) اضافه کنید.
چک لیست طراحی گوگل کست (Google Cast) ارائه شده است تا تجربه کاربری کست (Cast) را در تمام پلتفرمهای پشتیبانیشده ساده و قابل پیشبینی کند.
قرار است چه چیزی بسازیم؟
وقتی این آزمایشگاه کدنویسی را تکمیل کردید، یک برنامه ویدیویی iOS خواهید داشت که قادر به پخش ویدیوها به دستگاه Google Cast خواهد بود.
آنچه یاد خواهید گرفت
- نحوه اضافه کردن SDK گوگل کست به یک برنامه ویدیویی نمونه.
- نحوه اضافه کردن دکمه Cast برای انتخاب دستگاه Google Cast.
- نحوه اتصال به دستگاه Cast و راهاندازی گیرنده رسانه.
- نحوه ارسال ویدیو.
- نحوه اضافه کردن یک کنترلر Cast mini به برنامه شما.
- نحوه اضافه کردن یک کنترلر توسعهیافته.
- چگونه یک مقدمه مقدماتی ارائه دهیم.
- نحوه سفارشیسازی ویجتهای Cast.
- نحوه ادغام Cast Connect
آنچه نیاز دارید
- جدیدترین Xcode .
- یک دستگاه تلفن همراه با iOS 9 یا بالاتر (یا شبیهساز Xcode).
- یک کابل داده USB برای اتصال دستگاه تلفن همراه به رایانه توسعه (در صورت استفاده از دستگاه).
- یک دستگاه گوگل کست مانند کروم کست یا تلویزیون اندروید که به اینترنت دسترسی داشته باشد.
- تلویزیون یا مانیتوری که ورودی HDMI داشته باشد.
- برای آزمایش ادغام Cast Connect، یک Chromecast با Google TV مورد نیاز است، اما برای بقیه Codelab اختیاری است. اگر Chromecast ندارید، میتوانید از مرحله افزودن پشتیبانی Cast Connect که در انتهای این آموزش آمده است، صرف نظر کنید.
تجربه
- شما باید دانش قبلی در زمینه توسعه iOS داشته باشید.
- همچنین به دانش قبلی در مورد تماشای تلویزیون نیاز خواهید داشت :)
چگونه از این آموزش استفاده خواهید کرد؟
تجربه خود را در ساخت اپلیکیشنهای iOS چگونه ارزیابی میکنید؟
تجربه خود را با تماشای تلویزیون چگونه ارزیابی میکنید؟
۲. کد نمونه را دریافت کنید
شما میتوانید تمام کدهای نمونه را روی کامپیوتر خود دانلود کنید...
و فایل زیپ دانلود شده را از حالت فشرده خارج کنید.
۳. برنامه نمونه را اجرا کنید

ابتدا، بیایید ببینیم برنامه نمونه تکمیلشده چگونه است. این برنامه یک پخشکننده ویدیوی ساده است. کاربر میتواند یک ویدیو را از یک لیست انتخاب کند و سپس آن را بهصورت محلی روی دستگاه پخش کند یا آن را به یک دستگاه Google Cast منتقل کند.
با دانلود کد، دستورالعملهای زیر نحوه باز کردن و اجرای برنامه نمونه تکمیل شده در Xcode را شرح میدهند:
سوالات متداول
تنظیمات CocoaPods
برای راهاندازی CocoaPods، به کنسول خود بروید و با استفاده از Ruby پیشفرض موجود در macOS، آن را نصب کنید:
sudo gem install cocoapods
اگر مشکلی دارید، برای دانلود و نصب مدیر وابستگی به مستندات رسمی مراجعه کنید.
راهاندازی پروژه
- به ترمینال خود بروید و به دایرکتوری codelab بروید.
- وابستگیها را از Podfile نصب کنید.
cd app-done pod update pod install
- Xcode را باز کنید و گزینه Open another project... را انتخاب کنید.
- فایل
CastVideos-ios.xcworkspaceرا از قسمت مربوطه انتخاب کنید.
دایرکتوری app-doneدر پوشه کد نمونه.
برنامه را اجرا کنید
هدف و شبیهساز را انتخاب کنید و سپس برنامه را اجرا کنید:

باید بعد از چند ثانیه برنامهی پخش ویدیو را ببینید.
هنگام نمایش اعلان مربوط به پذیرش اتصالات شبکه ورودی، حتماً روی «مجاز» کلیک کنید. در صورت عدم پذیرش این گزینه، نماد ارسال محتوا ظاهر نمیشود.

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

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

ما باید پشتیبانی از گوگل کست را به برنامهی شروع که دانلود کردهاید اضافه کنیم. در اینجا برخی از اصطلاحات گوگل کست که در این آزمایشگاه کد استفاده خواهیم کرد، آورده شده است:
- یک برنامه فرستنده روی دستگاه تلفن همراه یا لپتاپ اجرا میشود،
- یک برنامه گیرنده روی دستگاه Google Cast اجرا میشود.
راهاندازی پروژه
اکنون آمادهاید تا با استفاده از Xcode، پروژهی اولیه را روی آن بسازید:
- به ترمینال خود بروید و به دایرکتوری codelab بروید.
- وابستگیها را از Podfile نصب کنید.
cd app-start pod update pod install
- Xcode را باز کنید و گزینه Open another project... را انتخاب کنید.
- فایل
CastVideos-ios.xcworkspaceرا از قسمت مربوطه انتخاب کنید.
دایرکتوری app-startدر پوشه کد نمونه.
طراحی اپلیکیشن
این برنامه لیستی از ویدیوها را از یک وب سرور راه دور دریافت میکند و لیستی را برای مرور در اختیار کاربر قرار میدهد. کاربران میتوانند یک ویدیو را برای مشاهده جزئیات انتخاب کنند یا ویدیو را به صورت محلی در دستگاه تلفن همراه پخش کنند.
این برنامه از دو کنترلر نمای اصلی تشکیل شده است: MediaTableViewController و MediaViewController.
کنترلکنندهی MediaTableView
این UITableViewController لیستی از ویدیوها را از یک نمونه MediaListModel نمایش میدهد. لیست ویدیوها و متادیتای مرتبط با آنها به صورت یک فایل JSON در یک سرور راه دور میزبانی میشوند. MediaListModel این JSON را واکشی کرده و آن را برای ساخت لیستی از اشیاء MediaItem پردازش میکند.
یک شیء MediaItem یک ویدیو و ابردادههای مرتبط با آن، مانند عنوان، توضیحات، URL برای یک تصویر و URL برای جریان را مدلسازی میکند.
MediaTableViewController یک نمونه MediaListModel ایجاد میکند و سپس خود را به عنوان یک MediaListModelDelegate ثبت میکند تا از زمان دانلود شدن متادیتای رسانه مطلع شود و بتواند نمای جدولی را بارگذاری کند.
به کاربر لیستی از تصاویر کوچک ویدیو به همراه توضیحی کوتاه برای هر ویدیو ارائه میشود. وقتی یک آیتم انتخاب میشود، MediaItem مربوطه به MediaViewController ارسال میشود.
کنترلکنندهی MediaView
این کنترلر نما، متادیتای مربوط به یک ویدیوی خاص را نمایش میدهد و به کاربر اجازه میدهد ویدیو را به صورت محلی در دستگاه تلفن همراه پخش کند.
کنترلر نما میزبان یک LocalPlayerView ، برخی کنترلهای رسانهای و یک ناحیه متنی برای نمایش توضیحات ویدیوی انتخاب شده است. پخشکننده قسمت بالای صفحه را پوشش میدهد و فضایی برای توضیحات دقیق ویدیو در زیر آن باقی میگذارد. کاربر میتواند پخش/مکث کند یا پخش ویدیوی محلی را جستجو کند.
سوالات متداول
۵. اضافه کردن دکمهی Cast

یک برنامهی دارای قابلیت Cast، دکمهی Cast را در هر یک از کنترلکنندههای نمای خود نمایش میدهد. کلیک بر روی دکمهی Cast، فهرستی از دستگاههای Cast را نمایش میدهد که کاربر میتواند آنها را انتخاب کند. اگر کاربر در حال پخش محتوا به صورت محلی در دستگاه فرستنده بوده باشد، انتخاب یک دستگاه Cast، پخش را در آن دستگاه Cast شروع یا از سر میگیرد. در هر زمانی در طول یک جلسهی Cast، کاربر میتواند بر روی دکمهی Cast کلیک کند و ارسال برنامهی خود به دستگاه Cast را متوقف کند. کاربر باید بتواند در هر صفحهای از برنامهی شما، همانطور که در چک لیست طراحی Google Cast توضیح داده شده است، به دستگاه Cast متصل شود یا از آن جدا شود.
پیکربندی
پروژه شروع به همان وابستگیها و تنظیمات Xcode که برای برنامه نمونه تکمیل شده انجام دادید، نیاز دارد. به آن بخش برگردید و همان مراحل را برای اضافه کردن GoogleCast.framework به پروژه شروع برنامه دنبال کنید.
مقداردهی اولیه
چارچوب Cast یک شیء سینگلتون سراسری به GCKCastContext دارد که تمام فعالیتهای چارچوب را هماهنگ میکند. این شیء باید در اوایل چرخه حیات برنامه، معمولاً در متد application(_:didFinishLaunchingWithOptions:) از نماینده برنامه، مقداردهی اولیه شود تا از سرگیری خودکار جلسه پس از راهاندازی مجدد برنامه فرستنده به درستی انجام شود و اسکن دستگاهها آغاز گردد.
هنگام مقداردهی اولیه GCKCastContext باید یک شیء GCKCastOptions ارائه شود. این کلاس شامل گزینههایی است که بر رفتار چارچوب تأثیر میگذارند. مهمترین آنها شناسه برنامه گیرنده است که برای فیلتر کردن نتایج کشف دستگاه Cast و اجرای برنامه گیرنده هنگام شروع جلسه Cast استفاده میشود.
متد application(_:didFinishLaunchingWithOptions:) همچنین جای خوبی برای تنظیم یک نماینده ثبت وقایع (logging delegate) است تا پیامهای ثبت وقایع را از چارچوب Cast دریافت کند. این موارد میتوانند برای اشکالزدایی و عیبیابی مفید باشند.
وقتی برنامهی خود را که قابلیت Cast دارد توسعه میدهید، باید به عنوان توسعهدهندهی Cast ثبتنام کنید و سپس یک شناسهی برنامه برای برنامهی خود دریافت کنید. برای این آزمایشگاه کد، ما از یک شناسهی برنامهی نمونه استفاده خواهیم کرد.
کد زیر را به AppDelegate.swift اضافه کنید تا GCKCastContext با شناسه برنامه از پیشفرضهای کاربر مقداردهی اولیه کنید و یک logger برای چارچوب Google Cast اضافه کنید:
import GoogleCast
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
fileprivate var enableSDKLogging = true
...
func application(_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
let options = GCKCastOptions(discoveryCriteria: GCKDiscoveryCriteria(applicationID: kReceiverAppID))
options.physicalVolumeButtonsWillControlDeviceVolume = true
GCKCastContext.setSharedInstanceWith(options)
window?.clipsToBounds = true
setupCastLogging()
...
}
...
func setupCastLogging() {
let logFilter = GCKLoggerFilter()
let classesToLog = ["GCKDeviceScanner", "GCKDeviceProvider", "GCKDiscoveryManager", "GCKCastChannel",
"GCKMediaControlChannel", "GCKUICastButton", "GCKUIMediaController", "NSMutableDictionary"]
logFilter.setLoggingLevel(.verbose, forClasses: classesToLog)
GCKLogger.sharedInstance().filter = logFilter
GCKLogger.sharedInstance().delegate = self
}
}
...
// MARK: - GCKLoggerDelegate
extension AppDelegate: GCKLoggerDelegate {
func logMessage(_ message: String,
at _: GCKLoggerLevel,
fromFunction function: String,
location: String) {
if enableSDKLogging {
// Send SDK's log messages directly to the console.
print("\(location): \(function) - \(message)")
}
}
}
دکمهی ارسال
حالا که GCKCastContext مقداردهی اولیه شده است، باید دکمهی Cast را اضافه کنیم تا کاربر بتواند دستگاه Cast را انتخاب کند. Cast SDK یک کامپوننت دکمهی Cast به نام GCKUICastButton را به عنوان یک زیرکلاس UIButton ارائه میدهد. میتوان آن را با قرار دادن در یک UIBarButtonItem به نوار عنوان برنامه اضافه کرد. باید دکمهی Cast را هم به MediaTableViewController و هم به MediaViewController اضافه کنیم.
کد زیر را به MediaTableViewController.swift و MediaViewController.swift اضافه کنید:
import GoogleCast
@objc(MediaTableViewController)
class MediaTableViewController: UITableViewController, GCKSessionManagerListener,
MediaListModelDelegate, GCKRequestDelegate {
private var castButton: GCKUICastButton!
...
override func viewDidLoad() {
print("MediaTableViewController - viewDidLoad")
super.viewDidLoad()
...
castButton = GCKUICastButton(frame: CGRect(x: CGFloat(0), y: CGFloat(0),
width: CGFloat(24), height: CGFloat(24)))
// Overwrite the UIAppearance theme in the AppDelegate.
castButton.tintColor = UIColor.white
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)
...
}
...
}
سپس، کد زیر را به MediaViewController.swift خود اضافه کنید:
import GoogleCast
@objc(MediaViewController)
class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemoteMediaClientListener,
LocalPlayerViewDelegate, GCKRequestDelegate {
private var castButton: GCKUICastButton!
...
override func viewDidLoad() {
super.viewDidLoad()
print("in MediaViewController viewDidLoad")
...
castButton = GCKUICastButton(frame: CGRect(x: CGFloat(0), y: CGFloat(0),
width: CGFloat(24), height: CGFloat(24)))
// Overwrite the UIAppearance theme in the AppDelegate.
castButton.tintColor = UIColor.white
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)
...
}
...
}
حالا برنامه را اجرا کنید. باید یک دکمه Cast در نوار ناوبری برنامه ببینید و وقتی روی آن کلیک کنید، دستگاههای Cast موجود در شبکه محلی شما را فهرست میکند. کشف دستگاه به طور خودکار توسط GCKCastContext مدیریت میشود. دستگاه Cast خود را انتخاب کنید و برنامه گیرنده نمونه روی دستگاه Cast بارگذاری میشود. میتوانید بین فعالیت مرور و فعالیت پخشکننده محلی حرکت کنید و وضعیت دکمه Cast همگامسازی میشود.
ما هنوز هیچ پشتیبانی برای پخش رسانه ارائه نکردهایم، بنابراین هنوز نمیتوانید ویدیوها را در دستگاه Cast پخش کنید. برای توقف پخش، روی دکمه Cast کلیک کنید.
۶. پخش محتوای ویدیویی

ما برنامه نمونه را طوری توسعه خواهیم داد که ویدیوها را از راه دور روی دستگاه Cast نیز پخش کند. برای انجام این کار، باید به رویدادهای مختلف تولید شده توسط چارچوب Cast گوش دهیم.
رسانههای ریختهگری
در سطح بالا، اگر میخواهید یک رسانه را در دستگاه Cast پخش کنید، موارد زیر باید اتفاق بیفتد:
- یک شیء
GCKMediaInformationاز Cast SDK ایجاد کنید که یک آیتم رسانهای را مدلسازی کند. - کاربر برای اجرای برنامه گیرنده شما به دستگاه Cast متصل میشود.
- شیء
GCKMediaInformationرا در گیرنده خود بارگذاری کرده و محتوا را پخش کنید. - وضعیت رسانه را پیگیری کنید.
- ارسال دستورات پخش به گیرنده بر اساس تعاملات کاربر.
مرحله ۱ به نگاشت یک شیء به شیء دیگر مربوط میشود؛ GCKMediaInformation چیزی است که Cast SDK آن را درک میکند و MediaItem کپسولهسازی برنامه ما برای یک آیتم رسانهای است؛ میتوانیم به راحتی یک MediaItem به GCKMediaInformation نگاشت کنیم. ما قبلاً مرحله ۲ را در بخش قبلی انجام دادهایم. انجام مرحله ۳ با Cast SDK آسان است.
برنامه نمونه MediaViewController از قبل با استفاده از این enum بین پخش محلی و پخش از راه دور تمایز قائل میشود:
enum PlaybackMode: Int {
case none = 0
case local
case remote
}
private var playbackMode = PlaybackMode.none
در این آزمایشگاه کد، مهم نیست که دقیقاً بفهمید منطق پخشکنندهی نمونه چگونه کار میکند. مهم این است که بدانید پخشکنندهی رسانهی برنامهی شما باید اصلاح شود تا از دو مکان پخش به روشی مشابه آگاه باشد.
در حال حاضر، پخشکننده محلی همیشه در حالت پخش محلی است، زیرا هنوز چیزی در مورد حالتهای Casting نمیداند. ما باید رابط کاربری را بر اساس انتقال حالتهایی که در چارچوب Cast اتفاق میافتد، بهروزرسانی کنیم. برای مثال، اگر شروع به Cast کردن کنیم، باید پخش محلی را متوقف کنیم و برخی از کنترلها را غیرفعال کنیم. به طور مشابه، اگر Cast کردن را در حالی که در این کنترلر نما هستیم متوقف کنیم، باید به پخش محلی منتقل شویم. برای مدیریت این موضوع، باید به رویدادهای مختلف تولید شده توسط چارچوب Cast گوش دهیم.
مدیریت جلسه بازیگران
برای چارچوب Cast، یک جلسه Cast مراحل اتصال به یک دستگاه، راهاندازی (یا پیوستن)، اتصال به یک برنامه گیرنده و در صورت لزوم، مقداردهی اولیه یک کانال کنترل رسانه را ترکیب میکند. کانال کنترل رسانه نحوه ارسال و دریافت پیامها از پخشکننده رسانه گیرنده توسط چارچوب Cast است.
جلسهی Cast به طور خودکار زمانی که کاربر دستگاهی را از دکمهی Cast انتخاب میکند، آغاز میشود و زمانی که اتصال کاربر قطع میشود، به طور خودکار متوقف میشود. اتصال مجدد به جلسهی گیرنده به دلیل مشکلات شبکه نیز به طور خودکار توسط چارچوب Cast مدیریت میشود.
جلسات Cast توسط GCKSessionManager مدیریت میشوند که از طریق GCKCastContext.sharedInstance().sessionManager قابل دسترسی است. فراخوانیهای GCKSessionManagerListener میتوانند برای نظارت بر رویدادهای جلسه، مانند ایجاد، تعلیق، از سرگیری و خاتمه، استفاده شوند.
ابتدا باید شنوندهی جلسه (session listener) خود را ثبت کنیم و چند متغیر را مقداردهی اولیه کنیم:
class MediaViewController: UIViewController, GCKSessionManagerListener,
GCKRemoteMediaClientListener, LocalPlayerViewDelegate, GCKRequestDelegate {
...
private var sessionManager: GCKSessionManager!
...
required init?(coder: NSCoder) {
super.init(coder: coder)
sessionManager = GCKCastContext.sharedInstance().sessionManager
...
}
override func viewWillAppear(_ animated: Bool) {
...
let hasConnectedSession: Bool = (sessionManager.hasConnectedSession())
if hasConnectedSession, (playbackMode != .remote) {
populateMediaInfo(false, playPosition: 0)
switchToRemotePlayback()
} else if sessionManager.currentSession == nil, (playbackMode != .local) {
switchToLocalPlayback()
}
sessionManager.add(self)
...
}
override func viewWillDisappear(_ animated: Bool) {
...
sessionManager.remove(self)
sessionManager.currentCastSession?.remoteMediaClient?.remove(self)
...
super.viewWillDisappear(animated)
}
func switchToLocalPlayback() {
...
sessionManager.currentCastSession?.remoteMediaClient?.remove(self)
...
}
func switchToRemotePlayback() {
...
sessionManager.currentCastSession?.remoteMediaClient?.add(self)
...
}
// MARK: - GCKSessionManagerListener
func sessionManager(_: GCKSessionManager, didStart session: GCKSession) {
print("MediaViewController: sessionManager didStartSession \(session)")
setQueueButtonVisible(true)
switchToRemotePlayback()
}
func sessionManager(_: GCKSessionManager, didResumeSession session: GCKSession) {
print("MediaViewController: sessionManager didResumeSession \(session)")
setQueueButtonVisible(true)
switchToRemotePlayback()
}
func sessionManager(_: GCKSessionManager, didEnd _: GCKSession, withError error: Error?) {
print("session ended with error: \(String(describing: error))")
let message = "The Casting session has ended.\n\(String(describing: error))"
if let window = appDelegate?.window {
Toast.displayMessage(message, for: 3, in: window)
}
setQueueButtonVisible(false)
switchToLocalPlayback()
}
func sessionManager(_: GCKSessionManager, didFailToStartSessionWithError error: Error?) {
if let error = error {
showAlert(withTitle: "Failed to start a session", message: error.localizedDescription)
}
setQueueButtonVisible(false)
}
func sessionManager(_: GCKSessionManager,
didFailToResumeSession _: GCKSession, withError _: Error?) {
if let window = UIApplication.shared.delegate?.window {
Toast.displayMessage("The Casting session could not be resumed.",
for: 3, in: window)
}
setQueueButtonVisible(false)
switchToLocalPlayback()
}
...
}
در MediaViewController ، ما علاقهمندیم که هنگام اتصال یا قطع اتصال از دستگاه Cast مطلع شویم تا بتوانیم به پخشکننده محلی یا از آن تغییر وضعیت دهیم. توجه داشته باشید که اتصال نه تنها میتواند توسط نمونهای از برنامه شما که روی دستگاه تلفن همراه شما اجرا میشود، مختل شود، بلکه میتواند توسط نمونه دیگری از برنامه شما (یا برنامه دیگری) که روی یک دستگاه تلفن همراه متفاوت اجرا میشود نیز مختل شود.
جلسه فعال فعلی از طریق GCKCastContext.sharedInstance().sessionManager.currentCastSession قابل دسترسی است. جلسات به طور خودکار در پاسخ به حرکات کاربر از طریق پنجرههای محاورهای Cast ایجاد و حذف میشوند.
بارگیری رسانه
در Cast SDK، GCKRemoteMediaClient مجموعهای از APIهای مناسب را برای مدیریت پخش رسانه از راه دور در گیرنده فراهم میکند. برای یک GCKCastSession که از پخش رسانه پشتیبانی میکند، یک نمونه از GCKRemoteMediaClient به طور خودکار توسط SDK ایجاد میشود. میتوان به آن به عنوان ویژگی remoteMediaClient از نمونه GCKCastSession دسترسی داشت.
کد زیر را به MediaViewController.swift اضافه کنید تا ویدیوی انتخاب شده فعلی در گیرنده بارگذاری شود:
@objc(MediaViewController)
class MediaViewController: UIViewController, GCKSessionManagerListener,
GCKRemoteMediaClientListener, LocalPlayerViewDelegate, GCKRequestDelegate {
...
@objc func playSelectedItemRemotely() {
loadSelectedItem(byAppending: false)
}
/**
* Loads the currently selected item in the current cast media session.
* @param appending If YES, the item is appended to the current queue if there
* is one. If NO, or if
* there is no queue, a new queue containing only the selected item is created.
*/
func loadSelectedItem(byAppending appending: Bool) {
print("enqueue item \(String(describing: mediaInfo))")
if let remoteMediaClient = sessionManager.currentCastSession?.remoteMediaClient {
let mediaQueueItemBuilder = GCKMediaQueueItemBuilder()
mediaQueueItemBuilder.mediaInformation = mediaInfo
mediaQueueItemBuilder.autoplay = true
mediaQueueItemBuilder.preloadTime = TimeInterval(UserDefaults.standard.integer(forKey: kPrefPreloadTime))
let mediaQueueItem = mediaQueueItemBuilder.build()
if appending {
let request = remoteMediaClient.queueInsert(mediaQueueItem, beforeItemWithID: kGCKMediaQueueInvalidItemID)
request.delegate = self
} else {
let queueDataBuilder = GCKMediaQueueDataBuilder(queueType: .generic)
queueDataBuilder.items = [mediaQueueItem]
queueDataBuilder.repeatMode = remoteMediaClient.mediaStatus?.queueRepeatMode ?? .off
let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
mediaLoadRequestDataBuilder.mediaInformation = mediaInfo
mediaLoadRequestDataBuilder.queueData = queueDataBuilder.build()
let request = remoteMediaClient.loadMedia(with: mediaLoadRequestDataBuilder.build())
request.delegate = self
}
}
}
...
}
اکنون روشهای مختلف موجود را بهروزرسانی کنید تا از منطق Cast Session برای پشتیبانی از پخش از راه دور استفاده شود:
required init?(coder: NSCoder) {
super.init(coder: coder)
...
castMediaController = GCKUIMediaController()
...
}
func switchToLocalPlayback() {
print("switchToLocalPlayback")
if playbackMode == .local {
return
}
setQueueButtonVisible(false)
var playPosition: TimeInterval = 0
var paused: Bool = false
var ended: Bool = false
if playbackMode == .remote {
playPosition = castMediaController.lastKnownStreamPosition
paused = (castMediaController.lastKnownPlayerState == .paused)
ended = (castMediaController.lastKnownPlayerState == .idle)
print("last player state: \(castMediaController.lastKnownPlayerState), ended: \(ended)")
}
populateMediaInfo((!paused && !ended), playPosition: playPosition)
sessionManager.currentCastSession?.remoteMediaClient?.remove(self)
playbackMode = .local
}
func switchToRemotePlayback() {
print("switchToRemotePlayback; mediaInfo is \(String(describing: mediaInfo))")
if playbackMode == .remote {
return
}
// If we were playing locally, load the local media on the remote player
if playbackMode == .local, (_localPlayerView.playerState != .stopped), (mediaInfo != nil) {
print("loading media: \(String(describing: mediaInfo))")
let paused: Bool = (_localPlayerView.playerState == .paused)
let mediaQueueItemBuilder = GCKMediaQueueItemBuilder()
mediaQueueItemBuilder.mediaInformation = mediaInfo
mediaQueueItemBuilder.autoplay = !paused
mediaQueueItemBuilder.preloadTime = TimeInterval(UserDefaults.standard.integer(forKey: kPrefPreloadTime))
mediaQueueItemBuilder.startTime = _localPlayerView.streamPosition ?? 0
let mediaQueueItem = mediaQueueItemBuilder.build()
let queueDataBuilder = GCKMediaQueueDataBuilder(queueType: .generic)
queueDataBuilder.items = [mediaQueueItem]
queueDataBuilder.repeatMode = .off
let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
mediaLoadRequestDataBuilder.queueData = queueDataBuilder.build()
let request = sessionManager.currentCastSession?.remoteMediaClient?.loadMedia(with: mediaLoadRequestDataBuilder.build())
request?.delegate = self
}
_localPlayerView.stop()
_localPlayerView.showSplashScreen()
setQueueButtonVisible(true)
sessionManager.currentCastSession?.remoteMediaClient?.add(self)
playbackMode = .remote
}
/* Play has been pressed in the LocalPlayerView. */
func continueAfterPlayButtonClicked() -> Bool {
let hasConnectedCastSession = sessionManager.hasConnectedCastSession
if mediaInfo != nil, hasConnectedCastSession() {
// Display an alert box to allow the user to add to queue or play
// immediately.
if actionSheet == nil {
actionSheet = ActionSheet(title: "Play Item", message: "Select an action", cancelButtonText: "Cancel")
actionSheet?.addAction(withTitle: "Play Now", target: self,
selector: #selector(playSelectedItemRemotely))
}
actionSheet?.present(in: self, sourceView: _localPlayerView)
return false
}
return true
}
حالا، برنامه را روی دستگاه تلفن همراه خود اجرا کنید. به دستگاه Cast خود متصل شوید و پخش ویدیو را شروع کنید. باید پخش ویدیو را روی گیرنده ببینید.
۷. مینی کنترلر
چک لیست طراحی Cast ایجاب میکند که همه برنامههای Cast یک مینی کنترلر داشته باشند تا هنگام خروج کاربر از صفحه محتوای فعلی، ظاهر شود. مینی کنترلر دسترسی فوری و یک یادآوری قابل مشاهده برای جلسه Cast فعلی را فراهم میکند.

کیت توسعه نرمافزار Cast یک نوار کنترل به نام GCKUIMiniMediaControlsViewController ارائه میدهد که میتوان آن را به صحنههایی که میخواهید کنترلهای پایدار را در آنها نمایش دهید، اضافه کرد.
برای برنامه نمونه، ما قصد داریم از GCKUICastContainerViewController استفاده کنیم که یک view controller دیگر را در بر میگیرد و یک GCKUIMiniMediaControlsViewController در پایین اضافه میکند.
فایل AppDelegate.swift تغییر دهید و کد زیر را برای شرط if useCastContainerViewController در متد زیر اضافه کنید:
func application(_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
let appStoryboard = UIStoryboard(name: "Main", bundle: nil)
guard let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation")
as? UINavigationController else { return false }
let castContainerVC = GCKCastContext.sharedInstance().createCastContainerController(for: navigationController)
as GCKUICastContainerViewController
castContainerVC.miniMediaControlsItemEnabled = true
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = castContainerVC
window?.makeKeyAndVisible()
...
}
این ویژگی و setter/getter را برای کنترل نمایش مینی کنترلر اضافه کنید (در بخش بعدی از این موارد استفاده خواهیم کرد):
var isCastControlBarsEnabled: Bool {
get {
if useCastContainerViewController {
let castContainerVC = (window?.rootViewController as? GCKUICastContainerViewController)
return castContainerVC!.miniMediaControlsItemEnabled
} else {
let rootContainerVC = (window?.rootViewController as? RootContainerViewController)
return rootContainerVC!.miniMediaControlsViewEnabled
}
}
set(notificationsEnabled) {
if useCastContainerViewController {
var castContainerVC: GCKUICastContainerViewController?
castContainerVC = (window?.rootViewController as? GCKUICastContainerViewController)
castContainerVC?.miniMediaControlsItemEnabled = notificationsEnabled
} else {
var rootContainerVC: RootContainerViewController?
rootContainerVC = (window?.rootViewController as? RootContainerViewController)
rootContainerVC?.miniMediaControlsViewEnabled = notificationsEnabled
}
}
}
برنامه را اجرا کنید و یک ویدیو پخش کنید. وقتی پخش در گیرنده شروع میشود، باید شاهد نمایش مینی کنترلر در پایین هر صحنه باشید. میتوانید با استفاده از مینی کنترلر، پخش از راه دور را کنترل کنید. اگر بین فعالیت مرور و فعالیت پخشکننده محلی حرکت کنید، وضعیت مینی کنترلر باید با وضعیت پخش رسانه گیرنده همگام بماند.
۸. پوشش مقدماتی
چک لیست طراحی Google Cast از یک برنامه فرستنده میخواهد که دکمه Cast را به کاربران فعلی معرفی کند تا به آنها اطلاع دهد که برنامه فرستنده اکنون از Casting پشتیبانی میکند و همچنین به کاربران جدید Google Cast کمک میکند.

کلاس GCKCastContext دارای متدی به presentCastInstructionsViewControllerOnce است که میتواند برای برجسته کردن دکمهی Cast هنگام اولین نمایش به کاربران استفاده شود. کد زیر را به MediaViewController.swift و MediaTableViewController.swift اضافه کنید:
override func viewDidLoad() {
...
NotificationCenter.default.addObserver(self, selector: #selector(castDeviceDidChange),
name: NSNotification.Name.gckCastStateDidChange,
object: GCKCastContext.sharedInstance())
}
@objc func castDeviceDidChange(_: Notification) {
if GCKCastContext.sharedInstance().castState != .noDevicesAvailable {
// You can present the instructions on how to use Google Cast on
// the first time the user uses you app
GCKCastContext.sharedInstance().presentCastInstructionsViewControllerOnce(with: castButton)
}
}
برنامه را روی دستگاه تلفن همراه خود اجرا کنید و باید صفحه مقدماتی را ببینید.
۹. کنترلر گسترشیافته
چک لیست طراحی گوگل کست به یک برنامه فرستنده نیاز دارد تا یک کنترلکننده گسترشیافته برای رسانهای که قرار است پخش شود، فراهم کند. این کنترلکننده گسترشیافته، نسخه تمامصفحهای از یک کنترلکننده کوچک است.

کنترلکنندهی گسترشیافته، یک نمای تمامصفحه است که کنترل کامل پخش رسانه از راه دور را ارائه میدهد. این نما باید به یک برنامهی پخش اجازه دهد تا هر جنبهی قابل مدیریت یک جلسهی پخش را مدیریت کند، به استثنای کنترل صدای گیرنده و چرخهی عمر جلسه (اتصال/توقف پخش). همچنین تمام اطلاعات وضعیت مربوط به جلسهی رسانه (طرح هنری، عنوان، زیرنویس و غیره) را ارائه میدهد.
عملکرد این view توسط کلاس GCKUIExpandedMediaControlsViewController پیادهسازی شده است.
اولین کاری که باید انجام دهید فعال کردن کنترلر بسطیافتهی پیشفرض در زمینهی تبدیل (cast context) است. فایل AppDelegate.swift را برای فعال کردن کنترلر بسطیافتهی پیشفرض تغییر دهید:
import GoogleCast
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
...
func application(_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
// Add after the setShareInstanceWith(options) is set.
GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true
...
}
...
}
کد زیر را به MediaViewController.swift اضافه کنید تا کنترلر توسعهیافته هنگام شروع پخش ویدیو توسط کاربر، بارگذاری شود:
@objc func playSelectedItemRemotely() {
...
appDelegate?.isCastControlBarsEnabled = false
GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls()
}
همچنین وقتی کاربر روی مینی کنترلر ضربه بزند، کنترلر گسترشیافته بهطور خودکار اجرا میشود.
برنامه را اجرا کنید و یک ویدیو پخش کنید. باید کنترلر باز شده را ببینید. به لیست ویدیوها برگردید و وقتی روی مینی کنترلر کلیک کنید، کنترلر باز شده دوباره بارگذاری میشود.
۱۰. پشتیبانی از اتصال بازیگران (Cast Connect) را اضافه کنید
کتابخانه Cast Connect به برنامههای فرستنده موجود اجازه میدهد تا از طریق پروتکل Cast با برنامههای Android TV ارتباط برقرار کنند. Cast Connect بر روی زیرساخت Cast ساخته میشود و برنامه Android TV شما به عنوان گیرنده عمل میکند.
وابستگیها
در Podfile خود، مطمئن شوید که google-cast-sdk مطابق با لیست زیر به نسخه 4.4.8 یا بالاتر اشاره دارد. اگر تغییری در فایل ایجاد کردهاید، pod update از کنسول اجرا کنید تا تغییر با پروژه شما همگامسازی شود.
pod 'google-cast-sdk', '>=4.4.8'
گزینههای راهاندازی GCK
برای اجرای برنامه Android TV که به عنوان Android Receiver نیز شناخته میشود، باید پرچم androidReceiverCompatible را در شیء GCKLaunchOptions روی true تنظیم کنیم. این شیء GCKLaunchOptions نحوه اجرای گیرنده را تعیین میکند و به GCKCastOptions که در نمونه مشترک با استفاده از GCKCastContext.setSharedInstanceWith تنظیم شدهاند، ارسال میشود.
خطوط زیر را به AppDelegate.swift خود اضافه کنید:
let options = GCKCastOptions(discoveryCriteria:
GCKDiscoveryCriteria(applicationID: kReceiverAppID))
...
/** Following code enables CastConnect */
let launchOptions = GCKLaunchOptions()
launchOptions.androidReceiverCompatible = true
options.launchOptions = launchOptions
GCKCastContext.setSharedInstanceWith(options)
اعتبارنامههای راهاندازی را تنظیم کنید
در سمت فرستنده، میتوانید GCKCredentialsData برای نشان دادن اینکه چه کسی به جلسه میپیوندد، مشخص کنید. credentials رشتهای هستند که میتوانند توسط کاربر تعریف شوند، تا زمانی که برنامه ATV شما بتواند آن را بفهمد. GCKCredentialsData فقط در زمان راهاندازی یا اتصال به برنامه Android TV شما منتقل میشود. اگر آن را دوباره در حین اتصال تنظیم کنید، به برنامه Android TV شما منتقل نمیشود.
برای تنظیم اعتبارنامههای راهاندازی، GCKCredentialsData باید هر زمان پس از تنظیم GCKLaunchOptions تعریف شود. برای نشان دادن این موضوع، بیایید منطقی را برای دکمه Creds اضافه کنیم تا اعتبارنامههایی را که هنگام برقراری جلسه ارسال میشوند، تنظیم کند. کد زیر را به MediaTableViewController.swift خود اضافه کنید:
class MediaTableViewController: UITableViewController, GCKSessionManagerListener, MediaListModelDelegate, GCKRequestDelegate {
...
private var credentials: String? = nil
...
override func viewDidLoad() {
...
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Creds", style: .plain,
target: self, action: #selector(toggleLaunchCreds))
...
setLaunchCreds()
}
...
@objc func toggleLaunchCreds(_: Any){
if (credentials == nil) {
credentials = "{\"userId\":\"id123\"}"
} else {
credentials = nil
}
Toast.displayMessage("Launch Credentials: "+(credentials ?? "Null"), for: 3, in: appDelegate?.window)
print("Credentials set: "+(credentials ?? "Null"))
setLaunchCreds()
}
...
func setLaunchCreds() {
GCKCastContext.sharedInstance()
.setLaunch(GCKCredentialsData(credentials: credentials))
}
}
تنظیم اعتبارنامهها در صورت درخواست بارگذاری
برای مدیریت credentials در هر دو برنامهی گیرندهی تلویزیون وب و اندروید، کد زیر را در کلاس MediaTableViewController.swift خود، زیر تابع loadSelectedItem اضافه کنید:
let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
...
mediaLoadRequestDataBuilder.credentials = credentials
...
بسته به برنامه گیرندهای که فرستنده شما به آن ارسال میکند، SDK به طور خودکار اعتبارنامههای فوق را در جلسه جاری اعمال میکند.
تست اتصال کست
مراحل نصب APK اندروید تیوی روی کرومکست با گوگل تیوی
- آدرس IP دستگاه Android TV خود را پیدا کنید. معمولاً این آدرس در قسمت تنظیمات > شبکه و اینترنت > (نام شبکهای که دستگاه شما به آن متصل است) موجود است. در سمت راست، جزئیات و IP دستگاه شما در شبکه نشان داده میشود.
- از آدرس IP دستگاه خود برای اتصال به آن از طریق ADB با استفاده از ترمینال استفاده کنید:
$ adb connect <device_ip_address>:5555
- از پنجره ترمینال خود، به پوشه سطح بالا برای نمونههای codelab که در ابتدای این codelab دانلود کردهاید، بروید. برای مثال:
$ cd Desktop/ios_codelab_src
- فایل .apk موجود در این پوشه را با اجرای دستور زیر روی تلویزیون اندروید خود نصب کنید:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
- اکنون باید بتوانید برنامهای با نام Cast Videos را در منوی برنامههای خود در دستگاه Android TV خود مشاهده کنید.
- پس از اتمام، برنامه را روی یک شبیهساز یا دستگاه تلفن همراه بسازید و اجرا کنید. با ایجاد یک جلسه پخش با دستگاه تلویزیون اندروید خود، اکنون باید برنامه گیرنده اندروید را در تلویزیون اندروید خود اجرا کنید. با پخش ویدیو از فرستنده تلفن همراه iOS خود، باید ویدیو در گیرنده اندروید اجرا شود و به شما امکان دهد پخش را با استفاده از ریموت دستگاه تلویزیون اندروید خود کنترل کنید.
۱۱. سفارشیسازی ویجتهای Cast
مقداردهی اولیه
با پوشه App-Done شروع کنید. کد زیر را به متد applicationDidFinishLaunchingWithOptions در فایل AppDelegate.swift خود اضافه کنید.
func application(_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
let styler = GCKUIStyle.sharedInstance()
...
}
پس از اعمال یک یا چند سفارشیسازی همانطور که در بقیه این آزمایشگاه کد ذکر شده است، استایلها را با فراخوانی کد زیر اعمال کنید.
styler.apply()
سفارشیسازی نماهای Cast
شما میتوانید تمام نماهایی را که چارچوب برنامهی Cast مدیریت میکند، با داشتن دستورالعملهای پیشفرض برای استایلبندی در نماها، سفارشیسازی کنید. به عنوان مثال، بیایید رنگ سایهی آیکون را تغییر دهیم.
styler.castViews.iconTintColor = .lightGray
در صورت نیاز میتوانید پیشفرضها را برای هر صفحه نمایش لغو کنید. برای مثال، برای لغو lightGrayColor برای رنگ سایه آیکون، فقط برای کنترلکننده رسانه توسعهیافته.
styler.castViews.mediaControl.expandedController.iconTintColor = .green
تغییر رنگها
شما میتوانید رنگ پسزمینه را برای همه نماها (یا به صورت جداگانه برای هر نما) سفارشی کنید. کد زیر رنگ پسزمینه را برای همه نماهای ارائه شده توسط چارچوب برنامه Cast شما به رنگ آبی تنظیم میکند.
styler.castViews.backgroundColor = .blue
styler.castViews.mediaControl.miniController.backgroundColor = .yellow
تغییر فونتها
شما میتوانید فونتها را برای برچسبهای مختلف که در نماهای پخش دیده میشوند، سفارشی کنید. بیایید برای اهداف نمایشی، همه فونتها را روی «Courier-Oblique» تنظیم کنیم.
styler.castViews.headingTextFont = UIFont.init(name: "Courier-Oblique", size: 16) ?? UIFont.systemFont(ofSize: 16)
styler.castViews.mediaControl.headingTextFont = UIFont.init(name: "Courier-Oblique", size: 6) ?? UIFont.systemFont(ofSize: 6)
تغییر تصاویر پیشفرض دکمهها
تصاویر سفارشی خود را به پروژه اضافه کنید و تصاویر را به دکمههای خود اختصاص دهید تا به آنها سبک دهید.
let muteOnImage = UIImage.init(named: "yourImage.png")
if let muteOnImage = muteOnImage {
styler.castViews.muteOnImage = muteOnImage
}
تغییر تم دکمهی Cast
شما همچنین میتوانید با استفاده از پروتکل UIAppearance، تم ویجتهای Cast را تغییر دهید. کد زیر تم GCKUICastButton را در تمام نماهایی که نمایش داده میشود، تغییر میدهد:
GCKUICastButton.appearance().tintColor = UIColor.gray
۱۲. تبریک
اکنون میدانید که چگونه با استفاده از ویجتهای Cast SDK در iOS، قابلیت پخش ویدیو را در یک برنامهی ویدیویی فعال کنید.
برای جزئیات بیشتر، به راهنمای توسعهدهندهی iOS Sender مراجعه کنید.