این راهنمای توسعهدهنده نحوه افزودن پشتیبانی Google Cast را با استفاده از iOS Sender SDK به برنامه فرستنده iOS خود توضیح میدهد.
دستگاه تلفن همراه یا لپ تاپ فرستنده ای است که پخش را کنترل می کند و دستگاه Google Cast گیرنده ای است که محتوا را روی تلویزیون نمایش می دهد.
چارچوب فرستنده به کتابخانه باینری کلاس Cast و منابع مرتبط موجود در زمان اجرا بر روی فرستنده اشاره دارد. برنامه فرستنده یا برنامه Cast به برنامه ای اشاره دارد که روی فرستنده نیز اجرا می شود. برنامه Web Receiver به برنامه HTML در حال اجرا بر روی گیرنده وب اشاره دارد.
چارچوب فرستنده از یک طراحی پاسخ به تماس ناهمزمان برای اطلاع رسانی به برنامه فرستنده از رویدادها و انتقال بین حالت های مختلف چرخه عمر برنامه Cast استفاده می کند.
جریان برنامه
مراحل زیر جریان اجرای معمولی سطح بالا را برای یک برنامه فرستنده iOS توصیف می کند:
- چارچوب Cast
GCKDiscoveryManager
را بر اساس ویژگیهای ارائه شده درGCKCastOptions
راهاندازی میکند تا اسکن دستگاهها را آغاز کند. - هنگامی که کاربر روی دکمه Cast کلیک میکند، چارچوب گفتگوی Cast را با لیست دستگاههای Cast کشف شده نشان میدهد.
- وقتی کاربر یک دستگاه Cast را انتخاب میکند، چارچوب تلاش میکند تا برنامه Web Receiver را در دستگاه Cast راهاندازی کند.
- این چارچوب برای تأیید راهاندازی برنامه گیرنده وب، تماسهای برگشتی را در برنامه فرستنده فراخوانی میکند.
- این چارچوب یک کانال ارتباطی بین برنامههای فرستنده و گیرنده وب ایجاد میکند.
- این چارچوب از کانال ارتباطی برای بارگیری و کنترل پخش رسانه در گیرنده وب استفاده می کند.
- این فریم ورک حالت پخش رسانه را بین فرستنده و گیرنده وب همگام میکند: زمانی که کاربر اقدامات رابط کاربر فرستنده را انجام میدهد، فریم ورک آن درخواستهای کنترل رسانه را به گیرنده وب ارسال میکند و هنگامی که گیرنده وب بهروزرسانیهای وضعیت رسانه را ارسال میکند، چارچوب وضعیت رابط کاربر فرستنده را بهروزرسانی میکند.
- هنگامی که کاربر برای قطع ارتباط از دستگاه Cast، روی دکمه Cast کلیک میکند، چارچوب برنامه فرستنده را از گیرنده وب قطع میکند.
برای عیب یابی فرستنده خود، باید ورود به سیستم را فعال کنید.
برای فهرستی جامع از همه کلاسها، روشها و رویدادها در چارچوب Google Cast iOS، به مرجع Google Cast iOS API مراجعه کنید. بخشهای زیر مراحل ادغام Cast در برنامه iOS شما را پوشش میدهند.
روش های فراخوانی از موضوع اصلی
زمینه Cast را راهاندازی کنید
چارچوب Cast دارای یک شی تکتنه جهانی به نام GCKCastContext
است که همه فعالیتهای چارچوب را هماهنگ میکند. این شی باید در اوایل چرخه عمر برنامه، معمولاً در روش -[application:didFinishLaunchingWithOptions:]
از نماینده برنامه، مقداردهی اولیه شود، به طوری که از سرگیری جلسه خودکار در راه اندازی مجدد برنامه فرستنده به درستی راه اندازی شود.
یک شی GCKCastOptions
باید هنگام مقداردهی اولیه GCKCastContext
ارائه شود. این کلاس شامل گزینه هایی است که بر رفتار فریم ورک تأثیر می گذارد. مهمترین آنها شناسه برنامه Web Receiver است که برای فیلتر کردن نتایج کشف و راه اندازی برنامه Web Receiver هنگام شروع جلسه Cast استفاده می شود.
-[application:didFinishLaunchingWithOptions:]
نیز مکان خوبی برای راهاندازی یک نماینده گزارش برای دریافت پیامهای گزارشگیری از چارچوب است. اینها می توانند برای رفع اشکال و عیب یابی مفید باشند.
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate { let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID let kDebugLoggingEnabled = true var window: UIWindow? func applicationDidFinishLaunching(_ application: UIApplication) { let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID) let options = GCKCastOptions(discoveryCriteria: criteria) GCKCastContext.setSharedInstanceWith(options) // Enable logger. GCKLogger.sharedInstance().delegate = self ... } // MARK: - GCKLoggerDelegate func logMessage(_ message: String, at level: GCKLoggerLevel, fromFunction function: String, location: String) { if (kDebugLoggingEnabled) { print(function + " - " + message) } } }
AppDelegate.h
@interface AppDelegate () <GCKLoggerDelegate> @end
AppDelegate.m
@implementation AppDelegate static NSString *const kReceiverAppID = @"AABBCCDD"; static const BOOL kDebugLoggingEnabled = YES; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc] initWithApplicationID:kReceiverAppID]; GCKCastOptions *options = [[GCKCastOptions alloc] initWithDiscoveryCriteria:criteria]; [GCKCastContext setSharedInstanceWithOptions:options]; // Enable logger. [GCKLogger sharedInstance].delegate = self; ... return YES; } ... #pragma mark - GCKLoggerDelegate - (void)logMessage:(NSString *)message atLevel:(GCKLoggerLevel)level fromFunction:(NSString *)function location:(NSString *)location { if (kDebugLoggingEnabled) { NSLog(@"%@ - %@, %@", function, message, location); } } @end
ویجت های Cast UX
Cast iOS SDK این ویجتها را فراهم میکند که با فهرست چک طراحی Cast مطابقت دارند:
پوشش مقدماتی : کلاس
GCKCastContext
روشی دارد،presentCastInstructionsViewControllerOnceWithCastButton
، که می تواند برای برجسته کردن دکمه Cast در اولین باری که یک گیرنده وب در دسترس است استفاده شود. برنامه فرستنده می تواند متن، موقعیت متن عنوان و دکمه رد کردن را سفارشی کند.دکمه Cast : با شروع Cast iOS sender SDK 4.6.0، دکمه Cast همیشه وقتی دستگاه فرستنده به Wi-Fi متصل است قابل مشاهده است. اولین باری که کاربر پس از شروع اولیه برنامه، روی دکمه Cast ضربه میزند، یک گفتگوی مجوزها ظاهر میشود تا کاربر بتواند به برنامه دسترسی شبکه محلی را به دستگاههای موجود در شبکه بدهد. پس از آن، هنگامی که کاربر روی دکمه Cast ضربه میزند، یک گفتگوی ارسال نمایش داده میشود که دستگاههای کشف شده را فهرست میکند. هنگامی که کاربر در حالی که دستگاه متصل است، روی دکمه Cast ضربه میزند، متادیتای رسانه فعلی (مانند عنوان، نام استودیوی ضبط و یک تصویر کوچک) را نمایش میدهد یا به کاربر اجازه میدهد ارتباط خود را با دستگاه پخش قطع کند. هنگامی که کاربر روی دکمه Cast ضربه میزند در حالی که هیچ دستگاهی در دسترس نیست، صفحهای نمایش داده میشود که به کاربر اطلاعاتی درباره علت پیدا نشدن دستگاهها و نحوه عیبیابی نشان میدهد.
مینی کنترلر : هنگامی که کاربر در حال ارسال محتوا است و از صفحه محتوای فعلی یا کنترلر گسترش یافته دور شده و به صفحه دیگری در برنامه فرستنده رفته است، مینی کنترلر در پایین صفحه نمایش داده می شود تا به کاربر امکان دیدن فراداده رسانه در حال ارسال و کنترل پخش را بدهد.
Expanded Controller : هنگامی که کاربر در حال ارسال محتوا است، اگر روی اعلان رسانه یا مینی کنترلر کلیک کند، کنترلر توسعه یافته راه اندازی می شود که متادیتای رسانه در حال پخش را نمایش می دهد و چندین دکمه برای کنترل پخش رسانه ارائه می دهد.
یک دکمه Cast اضافه کنید
این فریم ورک یک مؤلفه دکمه Cast را به عنوان یک زیر کلاس UIButton
ارائه می دهد. با قرار دادن آن در UIBarButtonItem
می توان آن را به نوار عنوان برنامه اضافه کرد. یک زیر کلاس معمولی UIViewController
می تواند یک دکمه Cast را به صورت زیر نصب کند:
let castButton = GCKUICastButton(frame: CGRect(x: 0, y: 0, width: 24, height: 24)) castButton.tintColor = UIColor.gray navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)
GCKUICastButton *castButton = [[GCKUICastButton alloc] initWithFrame:CGRectMake(0, 0, 24, 24)]; castButton.tintColor = [UIColor grayColor]; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:castButton];
به طور پیش فرض، با ضربه زدن روی دکمه، کادر گفتگوی Cast که توسط فریمورک ارائه شده است باز می شود.
GCKUICastButton
همچنین می تواند مستقیماً به استوری بورد اضافه شود.
پیکربندی کشف دستگاه
در چارچوب، کشف دستگاه به طور خودکار اتفاق می افتد. نیازی به شروع یا توقف صریح فرآیند کشف نیست مگر اینکه یک رابط کاربری سفارشی را پیاده سازی کنید.
کشف در چارچوب توسط کلاس GCKDiscoveryManager
مدیریت می شود که یکی از ویژگی های GCKCastContext
است. چارچوب یک مؤلفه محاوره ای پیش فرض Cast برای انتخاب و کنترل دستگاه فراهم می کند. فهرست دستگاه از نظر واژگانی با نام مناسب دستگاه مرتب شده است.
نحوه عملکرد مدیریت جلسه
Cast SDK مفهوم جلسه Cast را معرفی می کند که ایجاد آن ترکیبی از مراحل اتصال به یک دستگاه، راه اندازی (یا پیوستن) یک برنامه گیرنده وب، اتصال به آن برنامه و راه اندازی یک کانال کنترل رسانه است. برای اطلاعات بیشتر در مورد جلسات Cast و چرخه عمر گیرنده وب، به راهنمای چرخه عمر برنامه گیرنده وب مراجعه کنید.
جلسات توسط کلاس GCKSessionManager
مدیریت می شوند که یکی از ویژگی های GCKCastContext
است. جلسات فردی با زیر کلاسهای کلاس GCKSession
نشان داده میشوند: برای مثال، GCKCastSession
جلسات را با دستگاههای Cast نشان میدهد. میتوانید به جلسه Cast فعال فعلی (در صورت وجود)، به عنوان ویژگی currentCastSession
GCKSessionManager
دسترسی داشته باشید.
رابط GCKSessionManagerListener
را می توان برای نظارت بر رویدادهای جلسه، مانند ایجاد جلسه، تعلیق، از سرگیری و خاتمه استفاده کرد. هنگامی که برنامه فرستنده به پسزمینه میرود، چارچوب بهطور خودکار جلسات را به حالت تعلیق در میآورد و زمانی که برنامه به پیشزمینه بازمیگردد، سعی میکند آنها را از سر بگیرد (یا پس از پایان غیرعادی/ ناگهانی برنامه در حالی که یک جلسه فعال بود، دوباره راهاندازی میشود).
اگر از کادر گفتگوی Cast استفاده می شود، در پاسخ به حرکات کاربر، جلسات ایجاد شده و به طور خودکار حذف می شوند. در غیر این صورت، برنامه می تواند جلسات را به طور صریح از طریق روش هایی در GCKSessionManager
شروع و پایان دهد.
اگر برنامه نیاز به پردازش خاصی در پاسخ به رویدادهای چرخه عمر جلسه داشته باشد، می تواند یک یا چند نمونه GCKSessionManagerListener
با GCKSessionManager
ثبت کند. GCKSessionManagerListener
پروتکلی است که برای رویدادهایی مانند شروع جلسه، پایان جلسه و غیره، فراخوانی را تعریف می کند.
انتقال جریان
حفظ وضعیت جلسه اساس انتقال جریان است، جایی که کاربران میتوانند با استفاده از دستورات صوتی، برنامه Google Home یا نمایشگرهای هوشمند، جریانهای صوتی و تصویری موجود را در دستگاهها جابهجا کنند. پخش رسانه در یک دستگاه (منبع) متوقف می شود و در دستگاه دیگر (مقصد) ادامه می یابد. هر دستگاه Cast با آخرین سیستمافزار میتواند به عنوان منبع یا مقصد در انتقال جریان عمل کند.
برای دریافت دستگاه مقصد جدید در حین انتقال جریان، از ویژگی GCKCastSession#device
در طول پاسخ تماس [sessionManager:didResumeCastSession:]
استفاده کنید.
برای اطلاعات بیشتر به انتقال جریان در گیرنده وب مراجعه کنید.
اتصال مجدد خودکار
چارچوب Cast منطق اتصال مجدد را اضافه می کند تا به طور خودکار اتصال مجدد را در بسیاری از موارد گوشه ظریف کنترل کند، مانند:
- بهبودی از از دست دادن موقت WiFi
- بازیابی از خواب دستگاه
- بازیابی از پسزمینه برنامه
- در صورت خراب شدن برنامه بازیابی کنید
کنترل رسانه چگونه کار می کند
اگر یک جلسه Cast با یک برنامه گیرنده وب ایجاد شود که از فضای نام رسانه پشتیبانی می کند، یک نمونه از GCKRemoteMediaClient
به طور خودکار توسط چارچوب ایجاد می شود. می توان به عنوان ویژگی remoteMediaClient
نمونه GCKCastSession
به آن دسترسی داشت.
همه روشهای موجود در GCKRemoteMediaClient
که درخواستهایی را به گیرنده وب ارسال میکنند، یک شی GCKRequest
را برمیگردانند که میتواند برای ردیابی آن درخواست استفاده شود. یک GCKRequestDelegate
میتواند به این شی اختصاص داده شود تا اعلانهایی درباره نتیجه نهایی عملیات دریافت کند.
انتظار میرود که نمونه GCKRemoteMediaClient
ممکن است توسط چندین بخش از برنامه به اشتراک گذاشته شود، و در واقع برخی از اجزای داخلی چارچوب مانند گفتگوی Cast و کنترلهای رسانه کوچک، نمونه را به اشتراک میگذارند. برای این منظور، GCKRemoteMediaClient
از ثبت چندین GCKRemoteMediaClientListener
پشتیبانی می کند.
متادیتا رسانه را تنظیم کنید
کلاس GCKMediaMetadata
اطلاعاتی را در مورد یک آیتم رسانه ای نشان می دهد که می خواهید ارسال کنید. مثال زیر یک نمونه GCKMediaMetadata
جدید از یک فیلم ایجاد می کند و عنوان، زیرنویس، نام استودیو ضبط و دو تصویر را تنظیم می کند.
let metadata = GCKMediaMetadata() metadata.setString("Big Buck Bunny (2008)", forKey: kGCKMetadataKeyTitle) metadata.setString("Big Buck Bunny tells the story of a giant rabbit with a heart bigger than " + "himself. When one sunny day three rodents rudely harass him, something " + "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon " + "tradition he prepares the nasty rodents a comical revenge.", forKey: kGCKMetadataKeySubtitle) metadata.addImage(GCKImage(url: URL(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg")!, width: 480, height: 360))
GCKMediaMetadata *metadata = [[GCKMediaMetadata alloc] initWithMetadataType:GCKMediaMetadataTypeMovie]; [metadata setString:@"Big Buck Bunny (2008)" forKey:kGCKMetadataKeyTitle]; [metadata setString:@"Big Buck Bunny tells the story of a giant rabbit with a heart bigger than " "himself. When one sunny day three rodents rudely harass him, something " "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon " "tradition he prepares the nasty rodents a comical revenge." forKey:kGCKMetadataKeySubtitle]; [metadata addImage:[[GCKImage alloc] initWithURL:[[NSURL alloc] initWithString:@"https://commondatastorage.googleapis.com/" "gtv-videos-bucket/sample/images/BigBuckBunny.jpg"] width:480 height:360]];
بخش انتخاب تصویر و ذخیره سازی در مورد استفاده از تصاویر با ابرداده رسانه را ببینید.
رسانه را بارگیری کنید
برای بارگیری یک مورد رسانه، یک نمونه GCKMediaInformation
با استفاده از فراداده رسانه ایجاد کنید. سپس GCKCastSession
فعلی را دریافت کنید و از GCKRemoteMediaClient
آن برای بارگیری رسانه در برنامه گیرنده استفاده کنید. سپس می توانید از GCKRemoteMediaClient
برای کنترل برنامه پخش کننده رسانه در حال اجرا بر روی گیرنده، مانند پخش، مکث و توقف استفاده کنید.
let url = URL.init(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4") guard let mediaURL = url else { print("invalid mediaURL") return } let mediaInfoBuilder = GCKMediaInformationBuilder.init(contentURL: mediaURL) mediaInfoBuilder.streamType = GCKMediaStreamType.none; mediaInfoBuilder.contentType = "video/mp4" mediaInfoBuilder.metadata = metadata; mediaInformation = mediaInfoBuilder.build() guard let mediaInfo = mediaInformation else { print("invalid mediaInformation") return } if let request = sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInfo) { request.delegate = self }
GCKMediaInformationBuilder *mediaInfoBuilder = [[GCKMediaInformationBuilder alloc] initWithContentURL: [NSURL URLWithString:@"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"]]; mediaInfoBuilder.streamType = GCKMediaStreamTypeNone; mediaInfoBuilder.contentType = @"video/mp4"; mediaInfoBuilder.metadata = metadata; self.mediaInformation = [mediaInfoBuilder build]; GCKRequest *request = [self.sessionManager.currentSession.remoteMediaClient loadMedia:self.mediaInformation]; if (request != nil) { request.delegate = self; }
همچنین به بخش استفاده از آهنگ های رسانه ای مراجعه کنید.
فرمت ویدیویی 4K
برای تعیین فرمت ویدیوی رسانه شما، از ویژگی videoInfo
GCKMediaStatus
برای دریافت نمونه فعلی GCKVideoInfo
استفاده کنید. این نمونه شامل نوع فرمت تلویزیون HDR و ارتفاع و عرض بر حسب پیکسل است. انواع فرمت 4K در ویژگی hdrType
با مقادیر enum GCKVideoInfoHDRType
نشان داده می شوند.
مینی کنترلرها را اضافه کنید
با توجه به چک لیست طراحی Cast ، یک برنامه فرستنده باید یک کنترل دائمی به نام کنترلر کوچک ارائه دهد که وقتی کاربر از صفحه محتوای فعلی دور میشود ظاهر شود. مینی کنترلر دسترسی فوری و یک یادآوری قابل مشاهده را برای جلسه Cast فعلی فراهم می کند.
چارچوب Cast یک نوار کنترل به GCKUIMiniMediaControlsViewController
را ارائه میکند که میتواند به صحنههایی که میخواهید کنترلر کوچک را در آنها نشان دهید اضافه شود.
هنگامی که برنامه فرستنده شما در حال پخش جریانی زنده ویدیویی یا صوتی است، SDK به طور خودکار یک دکمه پخش/توقف را به جای دکمه پخش/مکث در کنترلر کوچک نمایش می دهد.
برای اینکه چگونه برنامه فرستنده شما می تواند ظاهر ویجت های Cast را پیکربندی کند، به سفارشی کردن رابط کاربر فرستنده iOS مراجعه کنید.
دو راه برای اضافه کردن کنترلر کوچک به برنامه فرستنده وجود دارد:
- به چارچوب Cast اجازه دهید طرحبندی کنترلکننده کوچک را با بستهکردن نمای کنترلکننده موجود با کنترلکننده مشاهده خود مدیریت کند.
- طرح بندی ویجت مینی کنترلر را خودتان با اضافه کردن آن به نمای کنترلر موجود خود با ارائه یک نمای فرعی در استوری بورد مدیریت کنید.
با استفاده از GCKUICastContainerViewController بسته بندی کنید
راه اول استفاده از GCKUICastContainerViewController
است که یک view controller دیگر را میپیچد و یک GCKUIMiniMediaControlsViewController
در پایین اضافه میکند. این رویکرد از این جهت محدود است که نمیتوانید انیمیشن را سفارشی کنید و نمیتوانید رفتار کنترلر نمای کانتینر را پیکربندی کنید.
این روش اول معمولاً در روش -[application:didFinishLaunchingWithOptions:]
مربوط به نماینده برنامه انجام می شود:
func applicationDidFinishLaunching(_ application: UIApplication) { ... // Wrap main view in the GCKUICastContainerViewController and display the mini controller. let appStoryboard = UIStoryboard(name: "Main", bundle: nil) let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation") let castContainerVC = GCKCastContext.sharedInstance().createCastContainerController(for: navigationController) castContainerVC.miniMediaControlsItemEnabled = true window = UIWindow(frame: UIScreen.main.bounds) window!.rootViewController = castContainerVC window!.makeKeyAndVisible() ... }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // Wrap main view in the GCKUICastContainerViewController and display the mini controller. UIStoryboard *appStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; UINavigationController *navigationController = [appStoryboard instantiateViewControllerWithIdentifier:@"MainNavigation"]; GCKUICastContainerViewController *castContainerVC = [[GCKCastContext sharedInstance] createCastContainerControllerForViewController:navigationController]; castContainerVC.miniMediaControlsItemEnabled = YES; self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; self.window.rootViewController = castContainerVC; [self.window makeKeyAndVisible]; ... }
var castControlBarsEnabled: Bool { set(enabled) { if let castContainerVC = self.window?.rootViewController as? GCKUICastContainerViewController { castContainerVC.miniMediaControlsItemEnabled = enabled } else { print("GCKUICastContainerViewController is not correctly configured") } } get { if let castContainerVC = self.window?.rootViewController as? GCKUICastContainerViewController { return castContainerVC.miniMediaControlsItemEnabled } else { print("GCKUICastContainerViewController is not correctly configured") return false } } }
AppDelegate.h
@interface AppDelegate : UIResponder <UIApplicationDelegate> @property (nonatomic, strong) UIWindow *window; @property (nonatomic, assign) BOOL castControlBarsEnabled; @end
AppDelegate.m
@implementation AppDelegate ... - (void)setCastControlBarsEnabled:(BOOL)notificationsEnabled { GCKUICastContainerViewController *castContainerVC; castContainerVC = (GCKUICastContainerViewController *)self.window.rootViewController; castContainerVC.miniMediaControlsItemEnabled = notificationsEnabled; } - (BOOL)castControlBarsEnabled { GCKUICastContainerViewController *castContainerVC; castContainerVC = (GCKUICastContainerViewController *)self.window.rootViewController; return castContainerVC.miniMediaControlsItemEnabled; } ... @end
جاسازی در نمای کنترلر موجود
راه دوم این است که با استفاده از createMiniMediaControlsViewController
برای ایجاد یک نمونه GCKUIMiniMediaControlsViewController
مینی کنترلر را مستقیماً به نمای کنترلر موجود خود اضافه کنید و سپس آن را به عنوان یک نمای فرعی به کنترلر نمای کانتینر اضافه کنید.
نمایش کنترلر خود را در نمایندگی برنامه تنظیم کنید:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { ... GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true window?.clipsToBounds = true let rootContainerVC = (window?.rootViewController as? RootContainerViewController) rootContainerVC?.miniMediaControlsViewEnabled = true ... return true }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES; self.window.clipsToBounds = YES; RootContainerViewController *rootContainerVC; rootContainerVC = (RootContainerViewController *)self.window.rootViewController; rootContainerVC.miniMediaControlsViewEnabled = YES; ... return YES; }
در کنترلر نمای ریشه خود، یک نمونه GCKUIMiniMediaControlsViewController
ایجاد کنید و آن را به عنوان یک نمای فرعی به کنترلر نمای کانتینر اضافه کنید:
let kCastControlBarsAnimationDuration: TimeInterval = 0.20 @objc(RootContainerViewController) class RootContainerViewController: UIViewController, GCKUIMiniMediaControlsViewControllerDelegate { @IBOutlet weak private var _miniMediaControlsContainerView: UIView! @IBOutlet weak private var _miniMediaControlsHeightConstraint: NSLayoutConstraint! private var miniMediaControlsViewController: GCKUIMiniMediaControlsViewController! var miniMediaControlsViewEnabled = false { didSet { if self.isViewLoaded { self.updateControlBarsVisibility() } } } var overriddenNavigationController: UINavigationController? override var navigationController: UINavigationController? { get { return overriddenNavigationController } set { overriddenNavigationController = newValue } } var miniMediaControlsItemEnabled = false override func viewDidLoad() { super.viewDidLoad() let castContext = GCKCastContext.sharedInstance() self.miniMediaControlsViewController = castContext.createMiniMediaControlsViewController() self.miniMediaControlsViewController.delegate = self self.updateControlBarsVisibility() self.installViewController(self.miniMediaControlsViewController, inContainerView: self._miniMediaControlsContainerView) } func updateControlBarsVisibility() { if self.miniMediaControlsViewEnabled && self.miniMediaControlsViewController.active { self._miniMediaControlsHeightConstraint.constant = self.miniMediaControlsViewController.minHeight self.view.bringSubview(toFront: self._miniMediaControlsContainerView) } else { self._miniMediaControlsHeightConstraint.constant = 0 } UIView.animate(withDuration: kCastControlBarsAnimationDuration, animations: {() -> Void in self.view.layoutIfNeeded() }) self.view.setNeedsLayout() } func installViewController(_ viewController: UIViewController?, inContainerView containerView: UIView) { if let viewController = viewController { self.addChildViewController(viewController) viewController.view.frame = containerView.bounds containerView.addSubview(viewController.view) viewController.didMove(toParentViewController: self) } } func uninstallViewController(_ viewController: UIViewController) { viewController.willMove(toParentViewController: nil) viewController.view.removeFromSuperview() viewController.removeFromParentViewController() } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "NavigationVCEmbedSegue" { self.navigationController = (segue.destination as? UINavigationController) } } ...
RootContainerViewController.h
static const NSTimeInterval kCastControlBarsAnimationDuration = 0.20; @interface RootContainerViewController () <GCKUIMiniMediaControlsViewControllerDelegate> { __weak IBOutlet UIView *_miniMediaControlsContainerView; __weak IBOutlet NSLayoutConstraint *_miniMediaControlsHeightConstraint; GCKUIMiniMediaControlsViewController *_miniMediaControlsViewController; } @property(nonatomic, weak, readwrite) UINavigationController *navigationController; @property(nonatomic, assign, readwrite) BOOL miniMediaControlsViewEnabled; @property(nonatomic, assign, readwrite) BOOL miniMediaControlsItemEnabled; @end
RootContainerViewController.m
@implementation RootContainerViewController - (void)viewDidLoad { [super viewDidLoad]; GCKCastContext *castContext = [GCKCastContext sharedInstance]; _miniMediaControlsViewController = [castContext createMiniMediaControlsViewController]; _miniMediaControlsViewController.delegate = self; [self updateControlBarsVisibility]; [self installViewController:_miniMediaControlsViewController inContainerView:_miniMediaControlsContainerView]; } - (void)setMiniMediaControlsViewEnabled:(BOOL)miniMediaControlsViewEnabled { _miniMediaControlsViewEnabled = miniMediaControlsViewEnabled; if (self.isViewLoaded) { [self updateControlBarsVisibility]; } } - (void)updateControlBarsVisibility { if (self.miniMediaControlsViewEnabled && _miniMediaControlsViewController.active) { _miniMediaControlsHeightConstraint.constant = _miniMediaControlsViewController.minHeight; [self.view bringSubviewToFront:_miniMediaControlsContainerView]; } else { _miniMediaControlsHeightConstraint.constant = 0; } [UIView animateWithDuration:kCastControlBarsAnimationDuration animations:^{ [self.view layoutIfNeeded]; }]; [self.view setNeedsLayout]; } - (void)installViewController:(UIViewController *)viewController inContainerView:(UIView *)containerView { if (viewController) { [self addChildViewController:viewController]; viewController.view.frame = containerView.bounds; [containerView addSubview:viewController.view]; [viewController didMoveToParentViewController:self]; } } - (void)uninstallViewController:(UIViewController *)viewController { [viewController willMoveToParentViewController:nil]; [viewController.view removeFromSuperview]; [viewController removeFromParentViewController]; } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"NavigationVCEmbedSegue"]) { self.navigationController = (UINavigationController *)segue.destinationViewController; } } ... @end
GCKUIMiniMediaControlsViewControllerDelegate
به کنترلر نمای میزبان می گوید که چه زمانی مینی کنترلر باید قابل مشاهده باشد:
func miniMediaControlsViewController(_: GCKUIMiniMediaControlsViewController, shouldAppear _: Bool) { updateControlBarsVisibility() }
- (void)miniMediaControlsViewController: (GCKUIMiniMediaControlsViewController *)miniMediaControlsViewController shouldAppear:(BOOL)shouldAppear { [self updateControlBarsVisibility]; }
اضافه کردن کنترلر توسعه یافته
چک لیست طراحی Google Cast به یک برنامه فرستنده نیاز دارد تا یک کنترل کننده گسترده برای رسانه در حال پخش ارائه دهد. کنترلر توسعه یافته یک نسخه تمام صفحه از مینی کنترلر است.
کنترلر گسترش یافته یک نمای تمام صفحه است که کنترل کامل پخش رسانه از راه دور را ارائه می دهد. این نما باید به یک برنامه ریخته گری اجازه دهد تا هر جنبه قابل مدیریت یک جلسه پخش را مدیریت کند، به استثنای کنترل حجم گیرنده وب و چرخه عمر جلسه (اتصال/توقف ارسال محتوا). همچنین تمام اطلاعات وضعیت جلسه رسانه (آثار هنری، عنوان، زیرنویس و غیره) را ارائه می دهد.
عملکرد این نما توسط کلاس GCKUIExpandedMediaControlsViewController
پیاده سازی شده است.
اولین کاری که باید انجام دهید این است که کنترلر توسعه یافته پیش فرض را در زمینه Cast فعال کنید. برای فعال کردن کنترلر توسعه یافته پیش فرض، نماینده برنامه را تغییر دهید:
func applicationDidFinishLaunching(_ application: UIApplication) { .. GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true ... }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES; .. }
کد زیر را به کنترلکننده مشاهده خود اضافه کنید تا وقتی کاربر شروع به پخش ویدیو میکند، کنترلکننده بازشده بارگیری شود:
func playSelectedItemRemotely() { GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls() ... // Load your media sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInformation) }
- (void)playSelectedItemRemotely { [[GCKCastContext sharedInstance] presentDefaultExpandedMediaControls]; ... // Load your media [self.sessionManager.currentSession.remoteMediaClient loadMedia:mediaInformation]; }
هنگامی که کاربر روی مینی کنترلر ضربه می زند، کنترلر گسترش یافته نیز به طور خودکار راه اندازی می شود.
هنگامی که برنامه فرستنده شما در حال پخش یک پخش زنده ویدیویی یا صوتی است، SDK به طور خودکار یک دکمه پخش/توقف را به جای دکمه پخش/مکث در کنترلر گسترش یافته نمایش می دهد.
برای اینکه چگونه برنامه فرستنده شما می تواند ظاهر ویجت های Cast را پیکربندی کند، به Apply Custom Styles to Your App iOS مراجعه کنید.
کنترل صدا
چارچوب Cast به طور خودکار حجم برنامه فرستنده را مدیریت می کند. چارچوب به طور خودکار با حجم گیرنده وب برای ویجت های UI ارائه شده همگام می شود. برای همگامسازی یک نوار لغزنده ارائه شده توسط برنامه، از GCKUIDeviceVolumeController
استفاده کنید.
کنترل صدا دکمه فیزیکی
دکمه های فیزیکی صدا در دستگاه فرستنده را می توان برای تغییر صدای جلسه Cast در گیرنده وب با استفاده از پرچم physicalVolumeButtonsWillControlDeviceVolume
در GCKCastOptions
که در GCKCastContext
تنظیم شده است، استفاده کرد.
let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID) let options = GCKCastOptions(discoveryCriteria: criteria) options.physicalVolumeButtonsWillControlDeviceVolume = true GCKCastContext.setSharedInstanceWith(options)
GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc] initWithApplicationID:kReceiverAppID]; GCKCastOptions *options = [[GCKCastOptions alloc] initWithDiscoveryCriteria :criteria]; options.physicalVolumeButtonsWillControlDeviceVolume = YES; [GCKCastContext setSharedInstanceWithOptions:options];
رسیدگی به خطاها
برای برنامههای فرستنده بسیار مهم است که همه تماسهای خطا را مدیریت کنند و بهترین پاسخ را برای هر مرحله از چرخه حیات Cast تصمیم بگیرند. برنامه می تواند گفتگوهای خطا را به کاربر نمایش دهد یا می تواند تصمیم بگیرد که جلسه Cast را پایان دهد.
ورود به سیستم
GCKLogger
یک تکی است که برای لاگ کردن توسط فریمورک استفاده می شود. از GCKLoggerDelegate
برای سفارشی کردن نحوه مدیریت پیامهای گزارش استفاده کنید.
با استفاده از GCKLogger
، SDK خروجی ورود به سیستم را به شکل پیام های اشکال زدایی، خطاها و هشدارها تولید می کند. این پیامهای گزارش به اشکالزدایی کمک میکنند و برای عیبیابی و شناسایی مشکلات مفید هستند. به طور پیشفرض، خروجی گزارش متوقف میشود، اما با اختصاص یک GCKLoggerDelegate
، برنامه فرستنده میتواند این پیامها را از SDK دریافت کرده و آنها را به کنسول سیستم وارد کند.
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate { let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID let kDebugLoggingEnabled = true var window: UIWindow? func applicationDidFinishLaunching(_ application: UIApplication) { ... // Enable logger. GCKLogger.sharedInstance().delegate = self ... } // MARK: - GCKLoggerDelegate func logMessage(_ message: String, at level: GCKLoggerLevel, fromFunction function: String, location: String) { if (kDebugLoggingEnabled) { print(function + " - " + message) } } }
AppDelegate.h
@interface AppDelegate () <GCKLoggerDelegate> @end
AppDelegate.m
@implementation AppDelegate static NSString *const kReceiverAppID = @"AABBCCDD"; static const BOOL kDebugLoggingEnabled = YES; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // Enable logger. [GCKLogger sharedInstance].delegate = self; ... return YES; } ... #pragma mark - GCKLoggerDelegate - (void)logMessage:(NSString *)message atLevel:(GCKLoggerLevel)level fromFunction:(NSString *)function location:(NSString *)location { if (kDebugLoggingEnabled) { NSLog(@"%@ - %@, %@", function, message, location); } } @end
برای فعال کردن پیام های اشکال زدایی و پرمخاطب نیز، این خط را پس از تنظیم نماینده (نشان داده شده در قبل) به کد اضافه کنید:
let filter = GCKLoggerFilter.init() filter.minimumLevel = GCKLoggerLevel.verbose GCKLogger.sharedInstance().filter = filter
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init]; [filter setMinimumLevel:GCKLoggerLevelVerbose]; [GCKLogger sharedInstance].filter = filter;
همچنین می توانید پیام های گزارش تولید شده توسط GCKLogger
را فیلتر کنید. حداقل سطح ورود به سیستم را برای هر کلاس تنظیم کنید، به عنوان مثال:
let filter = GCKLoggerFilter.init() filter.setLoggingLevel(GCKLoggerLevel.verbose, forClasses: ["GCKUICastButton", "GCKUIImageCache", "NSMutableDictionary"]) GCKLogger.sharedInstance().filter = filter
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init]; [filter setLoggingLevel:GCKLoggerLevelVerbose forClasses:@[@"GCKUICastButton", @"GCKUIImageCache", @"NSMutableDictionary" ]]; [GCKLogger sharedInstance].filter = filter;
نام کلاس ها می تواند نام های تحت اللفظی یا الگوهای glob باشد، به عنوان مثال، GCKUI\*
و GCK\*Session
.
این راهنمای توسعهدهنده نحوه افزودن پشتیبانی Google Cast را با استفاده از iOS Sender SDK به برنامه فرستنده iOS خود توضیح میدهد.
دستگاه تلفن همراه یا لپ تاپ فرستنده ای است که پخش را کنترل می کند و دستگاه Google Cast گیرنده ای است که محتوا را روی تلویزیون نمایش می دهد.
چارچوب فرستنده به کتابخانه باینری کلاس Cast و منابع مرتبط موجود در زمان اجرا بر روی فرستنده اشاره دارد. برنامه فرستنده یا برنامه Cast به برنامه ای اشاره دارد که روی فرستنده نیز اجرا می شود. برنامه Web Receiver به برنامه HTML در حال اجرا بر روی گیرنده وب اشاره دارد.
چارچوب فرستنده از یک طراحی پاسخ به تماس ناهمزمان برای اطلاع رسانی به برنامه فرستنده از رویدادها و انتقال بین حالت های مختلف چرخه عمر برنامه Cast استفاده می کند.
جریان برنامه
مراحل زیر جریان اجرای معمولی سطح بالا را برای یک برنامه فرستنده iOS توصیف می کند:
- چارچوب Cast
GCKDiscoveryManager
را بر اساس ویژگیهای ارائه شده درGCKCastOptions
راهاندازی میکند تا اسکن دستگاهها را آغاز کند. - هنگامی که کاربر روی دکمه Cast کلیک میکند، چارچوب گفتگوی Cast را با لیست دستگاههای Cast کشف شده نشان میدهد.
- وقتی کاربر یک دستگاه Cast را انتخاب میکند، چارچوب تلاش میکند تا برنامه Web Receiver را در دستگاه Cast راهاندازی کند.
- این چارچوب برای تأیید راهاندازی برنامه گیرنده وب، تماسهای برگشتی را در برنامه فرستنده فراخوانی میکند.
- این چارچوب یک کانال ارتباطی بین برنامههای فرستنده و گیرنده وب ایجاد میکند.
- این چارچوب از کانال ارتباطی برای بارگیری و کنترل پخش رسانه در گیرنده وب استفاده می کند.
- این فریم ورک حالت پخش رسانه را بین فرستنده و گیرنده وب همگام میکند: زمانی که کاربر اقدامات رابط کاربر فرستنده را انجام میدهد، فریم ورک آن درخواستهای کنترل رسانه را به گیرنده وب ارسال میکند و هنگامی که گیرنده وب بهروزرسانیهای وضعیت رسانه را ارسال میکند، چارچوب وضعیت رابط کاربر فرستنده را بهروزرسانی میکند.
- هنگامی که کاربر برای قطع ارتباط از دستگاه Cast، روی دکمه Cast کلیک میکند، چارچوب برنامه فرستنده را از گیرنده وب قطع میکند.
برای عیب یابی فرستنده خود، باید ورود به سیستم را فعال کنید.
برای فهرستی جامع از همه کلاسها، روشها و رویدادها در چارچوب Google Cast iOS، به مرجع Google Cast iOS API مراجعه کنید. بخشهای زیر مراحل ادغام Cast در برنامه iOS شما را پوشش میدهند.
روش های فراخوانی از موضوع اصلی
زمینه Cast را راهاندازی کنید
چارچوب Cast دارای یک شی تکتنه جهانی به نام GCKCastContext
است که همه فعالیتهای چارچوب را هماهنگ میکند. این شی باید در اوایل چرخه عمر برنامه، معمولاً در روش -[application:didFinishLaunchingWithOptions:]
از نماینده برنامه، مقداردهی اولیه شود، به طوری که از سرگیری جلسه خودکار در راه اندازی مجدد برنامه فرستنده به درستی راه اندازی شود.
یک شی GCKCastOptions
باید هنگام مقداردهی اولیه GCKCastContext
ارائه شود. این کلاس شامل گزینه هایی است که بر رفتار فریم ورک تأثیر می گذارد. مهمترین آنها شناسه برنامه Web Receiver است که برای فیلتر کردن نتایج کشف و راه اندازی برنامه Web Receiver هنگام شروع جلسه Cast استفاده می شود.
-[application:didFinishLaunchingWithOptions:]
نیز مکان خوبی برای راهاندازی یک نماینده گزارش برای دریافت پیامهای گزارشگیری از چارچوب است. اینها می توانند برای رفع اشکال و عیب یابی مفید باشند.
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate { let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID let kDebugLoggingEnabled = true var window: UIWindow? func applicationDidFinishLaunching(_ application: UIApplication) { let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID) let options = GCKCastOptions(discoveryCriteria: criteria) GCKCastContext.setSharedInstanceWith(options) // Enable logger. GCKLogger.sharedInstance().delegate = self ... } // MARK: - GCKLoggerDelegate func logMessage(_ message: String, at level: GCKLoggerLevel, fromFunction function: String, location: String) { if (kDebugLoggingEnabled) { print(function + " - " + message) } } }
AppDelegate.h
@interface AppDelegate () <GCKLoggerDelegate> @end
AppDelegate.m
@implementation AppDelegate static NSString *const kReceiverAppID = @"AABBCCDD"; static const BOOL kDebugLoggingEnabled = YES; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc] initWithApplicationID:kReceiverAppID]; GCKCastOptions *options = [[GCKCastOptions alloc] initWithDiscoveryCriteria:criteria]; [GCKCastContext setSharedInstanceWithOptions:options]; // Enable logger. [GCKLogger sharedInstance].delegate = self; ... return YES; } ... #pragma mark - GCKLoggerDelegate - (void)logMessage:(NSString *)message atLevel:(GCKLoggerLevel)level fromFunction:(NSString *)function location:(NSString *)location { if (kDebugLoggingEnabled) { NSLog(@"%@ - %@, %@", function, message, location); } } @end
ویجت های Cast UX
Cast iOS SDK این ویجتها را فراهم میکند که با فهرست چک طراحی Cast مطابقت دارند:
پوشش مقدماتی : کلاس
GCKCastContext
روشی دارد،presentCastInstructionsViewControllerOnceWithCastButton
، که می تواند برای برجسته کردن دکمه Cast در اولین باری که یک گیرنده وب در دسترس است استفاده شود. برنامه فرستنده می تواند متن، موقعیت متن عنوان و دکمه رد کردن را سفارشی کند.دکمه Cast : با شروع Cast iOS sender SDK 4.6.0، دکمه Cast همیشه وقتی دستگاه فرستنده به Wi-Fi متصل است قابل مشاهده است. اولین باری که کاربر پس از شروع اولیه برنامه، روی دکمه Cast ضربه میزند، یک گفتگوی مجوزها ظاهر میشود تا کاربر بتواند به برنامه دسترسی شبکه محلی را به دستگاههای موجود در شبکه بدهد. پس از آن، هنگامی که کاربر روی دکمه Cast ضربه میزند، یک گفتگوی ارسال نمایش داده میشود که دستگاههای کشف شده را فهرست میکند. هنگامی که کاربر در حالی که دستگاه متصل است، روی دکمه Cast ضربه میزند، متادیتای رسانه فعلی (مانند عنوان، نام استودیوی ضبط و یک تصویر کوچک) را نمایش میدهد یا به کاربر اجازه میدهد ارتباط خود را با دستگاه پخش قطع کند. هنگامی که کاربر روی دکمه Cast ضربه میزند در حالی که هیچ دستگاهی در دسترس نیست، صفحهای نمایش داده میشود که به کاربر اطلاعاتی درباره علت پیدا نشدن دستگاهها و نحوه عیبیابی نشان میدهد.
مینی کنترلر : هنگامی که کاربر در حال ارسال محتوا است و از صفحه محتوای فعلی یا کنترلر گسترش یافته دور شده و به صفحه دیگری در برنامه فرستنده رفته است، مینی کنترلر در پایین صفحه نمایش داده می شود تا به کاربر امکان دیدن فراداده رسانه در حال ارسال و کنترل پخش را بدهد.
Expanded Controller : هنگامی که کاربر در حال ارسال محتوا است، اگر روی اعلان رسانه یا مینی کنترلر کلیک کند، کنترلر توسعه یافته راه اندازی می شود که متادیتای رسانه در حال پخش را نمایش می دهد و چندین دکمه برای کنترل پخش رسانه ارائه می دهد.
یک دکمه Cast اضافه کنید
این فریم ورک یک مؤلفه دکمه Cast را به عنوان یک زیر کلاس UIButton
ارائه می دهد. با قرار دادن آن در UIBarButtonItem
می توان آن را به نوار عنوان برنامه اضافه کرد. یک زیر کلاس معمولی UIViewController
می تواند یک دکمه Cast را به صورت زیر نصب کند:
let castButton = GCKUICastButton(frame: CGRect(x: 0, y: 0, width: 24, height: 24)) castButton.tintColor = UIColor.gray navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)
GCKUICastButton *castButton = [[GCKUICastButton alloc] initWithFrame:CGRectMake(0, 0, 24, 24)]; castButton.tintColor = [UIColor grayColor]; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:castButton];
به طور پیش فرض، با ضربه زدن روی دکمه، کادر گفتگوی Cast که توسط فریمورک ارائه شده است باز می شود.
GCKUICastButton
همچنین می تواند مستقیماً به استوری بورد اضافه شود.
پیکربندی کشف دستگاه
در چارچوب، کشف دستگاه به طور خودکار اتفاق می افتد. نیازی به شروع یا توقف صریح فرآیند کشف نیست مگر اینکه یک رابط کاربری سفارشی را پیاده سازی کنید.
کشف در چارچوب توسط کلاس GCKDiscoveryManager
مدیریت می شود که یکی از ویژگی های GCKCastContext
است. چارچوب یک مؤلفه محاوره ای پیش فرض Cast برای انتخاب و کنترل دستگاه فراهم می کند. فهرست دستگاه از نظر واژگانی با نام مناسب دستگاه مرتب شده است.
نحوه عملکرد مدیریت جلسه
Cast SDK مفهوم جلسه Cast را معرفی می کند که ایجاد آن ترکیبی از مراحل اتصال به یک دستگاه، راه اندازی (یا پیوستن) یک برنامه گیرنده وب، اتصال به آن برنامه و راه اندازی یک کانال کنترل رسانه است. برای اطلاعات بیشتر در مورد جلسات Cast و چرخه عمر گیرنده وب، به راهنمای چرخه عمر برنامه گیرنده وب مراجعه کنید.
جلسات توسط کلاس GCKSessionManager
مدیریت می شوند که یکی از ویژگی های GCKCastContext
است. جلسات فردی با زیر کلاسهای کلاس GCKSession
نشان داده میشوند: برای مثال، GCKCastSession
جلسات را با دستگاههای Cast نشان میدهد. میتوانید به جلسه Cast فعال فعلی (در صورت وجود)، به عنوان ویژگی currentCastSession
GCKSessionManager
دسترسی داشته باشید.
رابط GCKSessionManagerListener
را می توان برای نظارت بر رویدادهای جلسه، مانند ایجاد جلسه، تعلیق، از سرگیری و خاتمه استفاده کرد. هنگامی که برنامه فرستنده به پسزمینه میرود، چارچوب بهطور خودکار جلسات را به حالت تعلیق در میآورد و زمانی که برنامه به پیشزمینه بازمیگردد، سعی میکند آنها را از سر بگیرد (یا پس از پایان غیرعادی/ ناگهانی برنامه در حالی که یک جلسه فعال بود، دوباره راهاندازی میشود).
اگر از کادر گفتگوی Cast استفاده می شود، در پاسخ به حرکات کاربر، جلسات ایجاد شده و به طور خودکار حذف می شوند. در غیر این صورت، برنامه می تواند جلسات را به طور صریح از طریق روش هایی در GCKSessionManager
شروع و پایان دهد.
اگر برنامه نیاز به پردازش خاصی در پاسخ به رویدادهای چرخه عمر جلسه داشته باشد، می تواند یک یا چند نمونه GCKSessionManagerListener
با GCKSessionManager
ثبت کند. GCKSessionManagerListener
پروتکلی است که برای رویدادهایی مانند شروع جلسه، پایان جلسه و غیره، فراخوانی را تعریف می کند.
انتقال جریان
حفظ وضعیت جلسه اساس انتقال جریان است، جایی که کاربران میتوانند با استفاده از دستورات صوتی، برنامه Google Home یا نمایشگرهای هوشمند، جریانهای صوتی و تصویری موجود را در دستگاهها جابهجا کنند. پخش رسانه در یک دستگاه (منبع) متوقف می شود و در دستگاه دیگر (مقصد) ادامه می یابد. هر دستگاه Cast با آخرین سیستمافزار میتواند به عنوان منبع یا مقصد در انتقال جریان عمل کند.
برای دریافت دستگاه مقصد جدید در حین انتقال جریان، از ویژگی GCKCastSession#device
در طول پاسخ تماس [sessionManager:didResumeCastSession:]
استفاده کنید.
برای اطلاعات بیشتر به انتقال جریان در گیرنده وب مراجعه کنید.
اتصال مجدد خودکار
چارچوب Cast منطق اتصال مجدد را اضافه می کند تا به طور خودکار اتصال مجدد را در بسیاری از موارد گوشه ظریف کنترل کند، مانند:
- بهبودی از از دست دادن موقت WiFi
- بازیابی از خواب دستگاه
- بازیابی از پسزمینه برنامه
- در صورت خراب شدن برنامه بازیابی کنید
کنترل رسانه چگونه کار می کند
اگر یک جلسه Cast با یک برنامه گیرنده وب ایجاد شود که از فضای نام رسانه پشتیبانی می کند، یک نمونه از GCKRemoteMediaClient
به طور خودکار توسط چارچوب ایجاد می شود. می توان به عنوان ویژگی remoteMediaClient
نمونه GCKCastSession
به آن دسترسی داشت.
همه روشهای موجود در GCKRemoteMediaClient
که درخواستهایی را به گیرنده وب ارسال میکنند، یک شی GCKRequest
را برمیگردانند که میتواند برای ردیابی آن درخواست استفاده شود. یک GCKRequestDelegate
میتواند به این شی اختصاص داده شود تا اعلانهایی درباره نتیجه نهایی عملیات دریافت کند.
انتظار میرود که نمونه GCKRemoteMediaClient
ممکن است توسط چندین بخش از برنامه به اشتراک گذاشته شود، و در واقع برخی از اجزای داخلی چارچوب مانند گفتگوی Cast و کنترلهای رسانه کوچک، نمونه را به اشتراک میگذارند. برای این منظور، GCKRemoteMediaClient
از ثبت چندین GCKRemoteMediaClientListener
پشتیبانی می کند.
متادیتا رسانه را تنظیم کنید
کلاس GCKMediaMetadata
اطلاعاتی را در مورد یک آیتم رسانه ای نشان می دهد که می خواهید ارسال کنید. مثال زیر یک نمونه GCKMediaMetadata
جدید از یک فیلم ایجاد می کند و عنوان، زیرنویس، نام استودیو ضبط و دو تصویر را تنظیم می کند.
let metadata = GCKMediaMetadata() metadata.setString("Big Buck Bunny (2008)", forKey: kGCKMetadataKeyTitle) metadata.setString("Big Buck Bunny tells the story of a giant rabbit with a heart bigger than " + "himself. When one sunny day three rodents rudely harass him, something " + "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon " + "tradition he prepares the nasty rodents a comical revenge.", forKey: kGCKMetadataKeySubtitle) metadata.addImage(GCKImage(url: URL(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg")!, width: 480, height: 360))
GCKMediaMetadata *metadata = [[GCKMediaMetadata alloc] initWithMetadataType:GCKMediaMetadataTypeMovie]; [metadata setString:@"Big Buck Bunny (2008)" forKey:kGCKMetadataKeyTitle]; [metadata setString:@"Big Buck Bunny tells the story of a giant rabbit with a heart bigger than " "himself. When one sunny day three rodents rudely harass him, something " "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon " "tradition he prepares the nasty rodents a comical revenge." forKey:kGCKMetadataKeySubtitle]; [metadata addImage:[[GCKImage alloc] initWithURL:[[NSURL alloc] initWithString:@"https://commondatastorage.googleapis.com/" "gtv-videos-bucket/sample/images/BigBuckBunny.jpg"] width:480 height:360]];
بخش انتخاب تصویر و ذخیره سازی در مورد استفاده از تصاویر با ابرداده رسانه را ببینید.
رسانه را بارگیری کنید
برای بارگیری یک مورد رسانه، یک نمونه GCKMediaInformation
با استفاده از فراداده رسانه ایجاد کنید. سپس GCKCastSession
فعلی را دریافت کنید و از GCKRemoteMediaClient
آن برای بارگیری رسانه در برنامه گیرنده استفاده کنید. سپس می توانید از GCKRemoteMediaClient
برای کنترل برنامه پخش کننده رسانه در حال اجرا بر روی گیرنده، مانند پخش، مکث و توقف استفاده کنید.
let url = URL.init(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4") guard let mediaURL = url else { print("invalid mediaURL") return } let mediaInfoBuilder = GCKMediaInformationBuilder.init(contentURL: mediaURL) mediaInfoBuilder.streamType = GCKMediaStreamType.none; mediaInfoBuilder.contentType = "video/mp4" mediaInfoBuilder.metadata = metadata; mediaInformation = mediaInfoBuilder.build() guard let mediaInfo = mediaInformation else { print("invalid mediaInformation") return } if let request = sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInfo) { request.delegate = self }
GCKMediaInformationBuilder *mediaInfoBuilder = [[GCKMediaInformationBuilder alloc] initWithContentURL: [NSURL URLWithString:@"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"]]; mediaInfoBuilder.streamType = GCKMediaStreamTypeNone; mediaInfoBuilder.contentType = @"video/mp4"; mediaInfoBuilder.metadata = metadata; self.mediaInformation = [mediaInfoBuilder build]; GCKRequest *request = [self.sessionManager.currentSession.remoteMediaClient loadMedia:self.mediaInformation]; if (request != nil) { request.delegate = self; }
همچنین به بخش استفاده از آهنگ های رسانه ای مراجعه کنید.
فرمت ویدیویی 4K
برای تعیین فرمت ویدیوی رسانه شما، از ویژگی videoInfo
GCKMediaStatus
برای دریافت نمونه فعلی GCKVideoInfo
استفاده کنید. این نمونه شامل نوع فرمت تلویزیون HDR و ارتفاع و عرض بر حسب پیکسل است. انواع فرمت 4K در ویژگی hdrType
با مقادیر enum GCKVideoInfoHDRType
نشان داده می شوند.
مینی کنترلرها را اضافه کنید
با توجه به چک لیست طراحی Cast ، یک برنامه فرستنده باید یک کنترل دائمی به نام کنترلر کوچک ارائه دهد که وقتی کاربر از صفحه محتوای فعلی دور میشود ظاهر شود. مینی کنترلر دسترسی فوری و یک یادآوری قابل مشاهده را برای جلسه Cast فعلی فراهم می کند.
چارچوب Cast یک نوار کنترل به GCKUIMiniMediaControlsViewController
را ارائه میکند که میتواند به صحنههایی که میخواهید کنترلر کوچک را در آنها نشان دهید اضافه شود.
هنگامی که برنامه فرستنده شما در حال پخش جریانی زنده ویدیویی یا صوتی است، SDK به طور خودکار یک دکمه پخش/توقف را به جای دکمه پخش/مکث در کنترلر کوچک نمایش می دهد.
برای اینکه چگونه برنامه فرستنده شما می تواند ظاهر ویجت های Cast را پیکربندی کند، به سفارشی کردن رابط کاربر فرستنده iOS مراجعه کنید.
دو راه برای اضافه کردن کنترلر کوچک به برنامه فرستنده وجود دارد:
- به چارچوب Cast اجازه دهید طرحبندی کنترلکننده کوچک را با بستهکردن نمای کنترلکننده موجود با کنترلکننده مشاهده خود مدیریت کند.
- طرح بندی ویجت مینی کنترلر را خودتان با اضافه کردن آن به نمای کنترلر موجود خود با ارائه یک نمای فرعی در استوری بورد مدیریت کنید.
با استفاده از GCKUICastContainerViewController بسته بندی کنید
راه اول استفاده از GCKUICastContainerViewController
است که یک view controller دیگر را میپیچد و یک GCKUIMiniMediaControlsViewController
در پایین اضافه میکند. این رویکرد از این جهت محدود است که نمیتوانید انیمیشن را سفارشی کنید و نمیتوانید رفتار کنترلر نمای کانتینر را پیکربندی کنید.
این روش اول معمولاً در روش -[application:didFinishLaunchingWithOptions:]
مربوط به نماینده برنامه انجام می شود:
func applicationDidFinishLaunching(_ application: UIApplication) { ... // Wrap main view in the GCKUICastContainerViewController and display the mini controller. let appStoryboard = UIStoryboard(name: "Main", bundle: nil) let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation") let castContainerVC = GCKCastContext.sharedInstance().createCastContainerController(for: navigationController) castContainerVC.miniMediaControlsItemEnabled = true window = UIWindow(frame: UIScreen.main.bounds) window!.rootViewController = castContainerVC window!.makeKeyAndVisible() ... }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // Wrap main view in the GCKUICastContainerViewController and display the mini controller. UIStoryboard *appStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; UINavigationController *navigationController = [appStoryboard instantiateViewControllerWithIdentifier:@"MainNavigation"]; GCKUICastContainerViewController *castContainerVC = [[GCKCastContext sharedInstance] createCastContainerControllerForViewController:navigationController]; castContainerVC.miniMediaControlsItemEnabled = YES; self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; self.window.rootViewController = castContainerVC; [self.window makeKeyAndVisible]; ... }
var castControlBarsEnabled: Bool { set(enabled) { if let castContainerVC = self.window?.rootViewController as? GCKUICastContainerViewController { castContainerVC.miniMediaControlsItemEnabled = enabled } else { print("GCKUICastContainerViewController is not correctly configured") } } get { if let castContainerVC = self.window?.rootViewController as? GCKUICastContainerViewController { return castContainerVC.miniMediaControlsItemEnabled } else { print("GCKUICastContainerViewController is not correctly configured") return false } } }
AppDelegate.h
@interface AppDelegate : UIResponder <UIApplicationDelegate> @property (nonatomic, strong) UIWindow *window; @property (nonatomic, assign) BOOL castControlBarsEnabled; @end
AppDelegate.m
@implementation AppDelegate ... - (void)setCastControlBarsEnabled:(BOOL)notificationsEnabled { GCKUICastContainerViewController *castContainerVC; castContainerVC = (GCKUICastContainerViewController *)self.window.rootViewController; castContainerVC.miniMediaControlsItemEnabled = notificationsEnabled; } - (BOOL)castControlBarsEnabled { GCKUICastContainerViewController *castContainerVC; castContainerVC = (GCKUICastContainerViewController *)self.window.rootViewController; return castContainerVC.miniMediaControlsItemEnabled; } ... @end
جاسازی در نمای کنترلر موجود
راه دوم این است که با استفاده از createMiniMediaControlsViewController
برای ایجاد یک نمونه GCKUIMiniMediaControlsViewController
مینی کنترلر را مستقیماً به نمای کنترلر موجود خود اضافه کنید و سپس آن را به عنوان یک نمای فرعی به کنترلر نمای کانتینر اضافه کنید.
نمایش کنترلر خود را در نمایندگی برنامه تنظیم کنید:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { ... GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true window?.clipsToBounds = true let rootContainerVC = (window?.rootViewController as? RootContainerViewController) rootContainerVC?.miniMediaControlsViewEnabled = true ... return true }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES; self.window.clipsToBounds = YES; RootContainerViewController *rootContainerVC; rootContainerVC = (RootContainerViewController *)self.window.rootViewController; rootContainerVC.miniMediaControlsViewEnabled = YES; ... return YES; }
در کنترلر نمای ریشه خود، یک نمونه GCKUIMiniMediaControlsViewController
ایجاد کنید و آن را به عنوان یک نمای فرعی به کنترلر نمای کانتینر اضافه کنید:
let kCastControlBarsAnimationDuration: TimeInterval = 0.20 @objc(RootContainerViewController) class RootContainerViewController: UIViewController, GCKUIMiniMediaControlsViewControllerDelegate { @IBOutlet weak private var _miniMediaControlsContainerView: UIView! @IBOutlet weak private var _miniMediaControlsHeightConstraint: NSLayoutConstraint! private var miniMediaControlsViewController: GCKUIMiniMediaControlsViewController! var miniMediaControlsViewEnabled = false { didSet { if self.isViewLoaded { self.updateControlBarsVisibility() } } } var overriddenNavigationController: UINavigationController? override var navigationController: UINavigationController? { get { return overriddenNavigationController } set { overriddenNavigationController = newValue } } var miniMediaControlsItemEnabled = false override func viewDidLoad() { super.viewDidLoad() let castContext = GCKCastContext.sharedInstance() self.miniMediaControlsViewController = castContext.createMiniMediaControlsViewController() self.miniMediaControlsViewController.delegate = self self.updateControlBarsVisibility() self.installViewController(self.miniMediaControlsViewController, inContainerView: self._miniMediaControlsContainerView) } func updateControlBarsVisibility() { if self.miniMediaControlsViewEnabled && self.miniMediaControlsViewController.active { self._miniMediaControlsHeightConstraint.constant = self.miniMediaControlsViewController.minHeight self.view.bringSubview(toFront: self._miniMediaControlsContainerView) } else { self._miniMediaControlsHeightConstraint.constant = 0 } UIView.animate(withDuration: kCastControlBarsAnimationDuration, animations: {() -> Void in self.view.layoutIfNeeded() }) self.view.setNeedsLayout() } func installViewController(_ viewController: UIViewController?, inContainerView containerView: UIView) { if let viewController = viewController { self.addChildViewController(viewController) viewController.view.frame = containerView.bounds containerView.addSubview(viewController.view) viewController.didMove(toParentViewController: self) } } func uninstallViewController(_ viewController: UIViewController) { viewController.willMove(toParentViewController: nil) viewController.view.removeFromSuperview() viewController.removeFromParentViewController() } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "NavigationVCEmbedSegue" { self.navigationController = (segue.destination as? UINavigationController) } } ...
RootContainerViewController.h
static const NSTimeInterval kCastControlBarsAnimationDuration = 0.20; @interface RootContainerViewController () <GCKUIMiniMediaControlsViewControllerDelegate> { __weak IBOutlet UIView *_miniMediaControlsContainerView; __weak IBOutlet NSLayoutConstraint *_miniMediaControlsHeightConstraint; GCKUIMiniMediaControlsViewController *_miniMediaControlsViewController; } @property(nonatomic, weak, readwrite) UINavigationController *navigationController; @property(nonatomic, assign, readwrite) BOOL miniMediaControlsViewEnabled; @property(nonatomic, assign, readwrite) BOOL miniMediaControlsItemEnabled; @end
RootContainerViewController.m
@implementation RootContainerViewController - (void)viewDidLoad { [super viewDidLoad]; GCKCastContext *castContext = [GCKCastContext sharedInstance]; _miniMediaControlsViewController = [castContext createMiniMediaControlsViewController]; _miniMediaControlsViewController.delegate = self; [self updateControlBarsVisibility]; [self installViewController:_miniMediaControlsViewController inContainerView:_miniMediaControlsContainerView]; } - (void)setMiniMediaControlsViewEnabled:(BOOL)miniMediaControlsViewEnabled { _miniMediaControlsViewEnabled = miniMediaControlsViewEnabled; if (self.isViewLoaded) { [self updateControlBarsVisibility]; } } - (void)updateControlBarsVisibility { if (self.miniMediaControlsViewEnabled && _miniMediaControlsViewController.active) { _miniMediaControlsHeightConstraint.constant = _miniMediaControlsViewController.minHeight; [self.view bringSubviewToFront:_miniMediaControlsContainerView]; } else { _miniMediaControlsHeightConstraint.constant = 0; } [UIView animateWithDuration:kCastControlBarsAnimationDuration animations:^{ [self.view layoutIfNeeded]; }]; [self.view setNeedsLayout]; } - (void)installViewController:(UIViewController *)viewController inContainerView:(UIView *)containerView { if (viewController) { [self addChildViewController:viewController]; viewController.view.frame = containerView.bounds; [containerView addSubview:viewController.view]; [viewController didMoveToParentViewController:self]; } } - (void)uninstallViewController:(UIViewController *)viewController { [viewController willMoveToParentViewController:nil]; [viewController.view removeFromSuperview]; [viewController removeFromParentViewController]; } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"NavigationVCEmbedSegue"]) { self.navigationController = (UINavigationController *)segue.destinationViewController; } } ... @end
GCKUIMiniMediaControlsViewControllerDelegate
به کنترلر نمای میزبان می گوید که چه زمانی مینی کنترلر باید قابل مشاهده باشد:
func miniMediaControlsViewController(_: GCKUIMiniMediaControlsViewController, shouldAppear _: Bool) { updateControlBarsVisibility() }
- (void)miniMediaControlsViewController: (GCKUIMiniMediaControlsViewController *)miniMediaControlsViewController shouldAppear:(BOOL)shouldAppear { [self updateControlBarsVisibility]; }
اضافه کردن کنترلر توسعه یافته
چک لیست طراحی Google Cast به یک برنامه فرستنده نیاز دارد تا یک کنترل کننده گسترده برای رسانه در حال پخش ارائه دهد. کنترلر توسعه یافته یک نسخه تمام صفحه از مینی کنترلر است.
کنترلر گسترش یافته یک نمای تمام صفحه است که کنترل کامل پخش رسانه از راه دور را ارائه می دهد. این نما باید به یک برنامه ریخته گری اجازه دهد تا هر جنبه قابل مدیریت یک جلسه پخش را مدیریت کند، به استثنای کنترل حجم گیرنده وب و چرخه عمر جلسه (اتصال/توقف ارسال محتوا). همچنین تمام اطلاعات وضعیت جلسه رسانه (آثار هنری، عنوان، زیرنویس و غیره) را ارائه می دهد.
عملکرد این نما توسط کلاس GCKUIExpandedMediaControlsViewController
پیاده سازی شده است.
اولین کاری که باید انجام دهید این است که کنترلر توسعه یافته پیش فرض را در زمینه Cast فعال کنید. برای فعال کردن کنترلر توسعه یافته پیش فرض، نماینده برنامه را تغییر دهید:
func applicationDidFinishLaunching(_ application: UIApplication) { .. GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true ... }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES; .. }
کد زیر را به کنترلکننده مشاهده خود اضافه کنید تا وقتی کاربر شروع به پخش ویدیو میکند، کنترلکننده بازشده بارگیری شود:
func playSelectedItemRemotely() { GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls() ... // Load your media sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInformation) }
- (void)playSelectedItemRemotely { [[GCKCastContext sharedInstance] presentDefaultExpandedMediaControls]; ... // Load your media [self.sessionManager.currentSession.remoteMediaClient loadMedia:mediaInformation]; }
هنگامی که کاربر روی مینی کنترلر ضربه می زند، کنترلر گسترش یافته نیز به طور خودکار راه اندازی می شود.
هنگامی که برنامه فرستنده شما در حال پخش یک پخش زنده ویدیویی یا صوتی است، SDK به طور خودکار یک دکمه پخش/توقف را به جای دکمه پخش/مکث در کنترلر گسترش یافته نمایش می دهد.
برای اینکه چگونه برنامه فرستنده شما می تواند ظاهر ابزارک های بازیگران را پیکربندی کند ، سبک های سفارشی را در برنامه iOS خود اعمال کنید .
کنترل صدا
چارچوب بازیگران به طور خودکار حجم برنامه Sender را مدیریت می کند. این چارچوب به طور خودکار با حجم گیرنده وب برای ابزارک های UI عرضه شده همزمان می شود. برای همگام سازی یک کشویی ارائه شده توسط برنامه ، از GCKUIDeviceVolumeController
استفاده کنید.
کنترل حجم دکمه فیزیکی
از دکمه های حجم فیزیکی در دستگاه فرستنده می توان برای تغییر حجم جلسه ریخته گری در گیرنده وب با استفاده از پرچم physicalVolumeButtonsWillControlDeviceVolume
در GCKCastOptions
استفاده کرد ، که در GCKCastContext
تنظیم شده است.
let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID) let options = GCKCastOptions(discoveryCriteria: criteria) options.physicalVolumeButtonsWillControlDeviceVolume = true GCKCastContext.setSharedInstanceWith(options)
GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc] initWithApplicationID:kReceiverAppID]; GCKCastOptions *options = [[GCKCastOptions alloc] initWithDiscoveryCriteria :criteria]; options.physicalVolumeButtonsWillControlDeviceVolume = YES; [GCKCastContext setSharedInstanceWithOptions:options];
رسیدگی به خطاها
برای برنامه های فرستنده بسیار مهم است که همه تماس های خطای خطا را انجام دهند و بهترین پاسخ را برای هر مرحله از چرخه زندگی بازیگران تصمیم بگیرند. برنامه می تواند گفتگوی خطا را به کاربر نمایش دهد یا می تواند تصمیم بگیرد که جلسه بازیگران را پایان دهد.
ورود به سیستم
GCKLogger
یک تک آهنگ است که برای ورود به سیستم توسط چارچوب استفاده می شود. برای سفارشی کردن نحوه رسیدگی به پیام های ورود به سیستم ، از GCKLoggerDelegate
استفاده کنید.
SDK با استفاده از GCKLogger
، خروجی ورود به سیستم را به صورت پیام های اشکال زدایی ، خطاها و هشدارها تولید می کند. این پیام های ورود به سیستم اشکال زدایی کمک می کنند و برای عیب یابی و شناسایی مشکلات مفید هستند. به طور پیش فرض ، خروجی ورود به سیستم سرکوب می شود ، اما با اختصاص GCKLoggerDelegate
، برنامه فرستنده می تواند این پیام ها را از SDK دریافت کرده و آنها را به کنسول سیستم وارد کند.
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate { let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID let kDebugLoggingEnabled = true var window: UIWindow? func applicationDidFinishLaunching(_ application: UIApplication) { ... // Enable logger. GCKLogger.sharedInstance().delegate = self ... } // MARK: - GCKLoggerDelegate func logMessage(_ message: String, at level: GCKLoggerLevel, fromFunction function: String, location: String) { if (kDebugLoggingEnabled) { print(function + " - " + message) } } }
AppDelegate.h
@interface AppDelegate () <GCKLoggerDelegate> @end
AppDelegate.m
@implementation AppDelegate static NSString *const kReceiverAppID = @"AABBCCDD"; static const BOOL kDebugLoggingEnabled = YES; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // Enable logger. [GCKLogger sharedInstance].delegate = self; ... return YES; } ... #pragma mark - GCKLoggerDelegate - (void)logMessage:(NSString *)message atLevel:(GCKLoggerLevel)level fromFunction:(NSString *)function location:(NSString *)location { if (kDebugLoggingEnabled) { NSLog(@"%@ - %@, %@", function, message, location); } } @end
برای فعال کردن پیام های اشکال زدایی و Verbose نیز ، این خط را پس از تنظیم نماینده (که قبلاً نشان داده شده است) به کد اضافه کنید:
let filter = GCKLoggerFilter.init() filter.minimumLevel = GCKLoggerLevel.verbose GCKLogger.sharedInstance().filter = filter
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init]; [filter setMinimumLevel:GCKLoggerLevelVerbose]; [GCKLogger sharedInstance].filter = filter;
همچنین می توانید پیام های ورود به سیستم تولید شده توسط GCKLogger
را فیلتر کنید. به عنوان مثال حداقل سطح ورود به سیستم را در هر کلاس تنظیم کنید:
let filter = GCKLoggerFilter.init() filter.setLoggingLevel(GCKLoggerLevel.verbose, forClasses: ["GCKUICastButton", "GCKUIImageCache", "NSMutableDictionary"]) GCKLogger.sharedInstance().filter = filter
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init]; [filter setLoggingLevel:GCKLoggerLevelVerbose forClasses:@[@"GCKUICastButton", @"GCKUIImageCache", @"NSMutableDictionary" ]]; [GCKLogger sharedInstance].filter = filter;
نام کلاس می تواند نام تحت اللفظی یا الگوهای کره باشد ، به عنوان مثال ، GCK\*Session
GCKUI\*
و GCK \*.
این راهنمای توسعه دهنده نحوه اضافه کردن پشتیبانی از بازیگران Google به برنامه ارسال کننده iOS خود را با استفاده از IOS Sender SDK توضیح می دهد.
دستگاه تلفن همراه یا لپ تاپ فرستنده ای است که پخش را کنترل می کند و دستگاه Google Cast گیرنده ای است که محتوا را در تلویزیون نمایش می دهد.
چارچوب فرستنده به منابع باینری و مرتبط با کتابخانه کلاس بازیگران موجود در زمان اجرا روی فرستنده اشاره دارد. برنامه Sender یا برنامه CAST به برنامه ای که روی فرستنده نیز اجرا می شود ، اشاره دارد. برنامه گیرنده وب به برنامه HTML که در گیرنده وب اجرا می شود ، اشاره دارد.
چارچوب Sender از یک طرح پاسخ به تماس ناهمزمان برای اطلاع رسانی به برنامه فرستنده رویدادها و انتقال بین حالتهای مختلف چرخه عمر برنامه بازیگران استفاده می کند.
جریان برنامه
مراحل زیر جریان معمول اجرای سطح بالا برای یک برنامه iOS فرستنده را شرح می دهد:
- چارچوب بازیگران
GCKDiscoveryManager
را بر اساس خواص ارائه شده درGCKCastOptions
شروع می کند تا اسکن دستگاه ها را شروع کند. - هنگامی که کاربر روی دکمه CAST کلیک می کند ، Framework گفتگوی بازیگران را با لیست دستگاه های بازیگران کشف شده ارائه می دهد.
- هنگامی که کاربر یک دستگاه ریخته گری را انتخاب می کند ، چارچوب سعی در راه اندازی برنامه گیرنده وب در دستگاه ریخته گری دارد.
- این چارچوب برای تأیید اینکه برنامه گیرنده وب راه اندازی شده است ، در برنامه ارسال کننده تماس تلفنی را فراخوانی می کند.
- این چارچوب یک کانال ارتباطی بین برنامه های فرستنده و گیرنده وب ایجاد می کند.
- این چارچوب از کانال ارتباطی برای بارگیری و کنترل پخش رسانه در گیرنده وب استفاده می کند.
- این چارچوب همگام سازی وضعیت پخش رسانه بین فرستنده و گیرنده وب: هنگامی که کاربر اقدامات UI ارسال کننده را انجام می دهد ، چارچوب آن درخواست های کنترل رسانه را به گیرنده وب منتقل می کند و هنگامی که گیرنده وب به روزرسانی های وضعیت رسانه را ارسال می کند ، چارچوب وضعیت UI فرستنده را به روز می کند.
- هنگامی که کاربر برای جدا کردن از دستگاه بازیگران روی دکمه CAST کلیک می کند ، Framework برنامه فرستنده را از گیرنده وب جدا می کند.
برای عیب یابی فرستنده خود ، باید ورود به سیستم را فعال کنید.
برای یک لیست جامع از کلیه کلاس ها ، روش ها و رویدادها در چارچوب iOS Google Cast ، به مرجع API Google Cast IOS مراجعه کنید. بخش های زیر مراحل ادغام بازیگران را در برنامه iOS شما پوشش می دهد.
روش های فراخوانی از موضوع اصلی
زمینه بازیگران را آغاز کنید
چارچوب بازیگران دارای یک شیء جهانی Singleton ، GCKCastContext
است که همه فعالیت های این چارچوب را هماهنگ می کند. این شیء باید در اوایل چرخه عمر برنامه ، به طور معمول در -[application:didFinishLaunchingWithOptions:]
روش نماینده برنامه ، به گونه ای که از سرگیری خودکار جلسه در برنامه فرستنده شروع می شود ، به درستی تحریک شود.
هنگام اولیه سازی GCKCastContext
یک شیء GCKCastOptions
باید تأمین شود. این کلاس شامل گزینه هایی است که بر رفتار چارچوب تأثیر می گذارد. مهمترین آنها شناسه برنامه گیرنده وب است که برای فیلتر کردن نتایج کشف و راه اندازی برنامه گیرنده وب هنگام شروع جلسه بازیگران استفاده می شود.
-[application:didFinishLaunchingWithOptions:]
همچنین مکان مناسبی برای تنظیم یک نماینده ورود به سیستم برای دریافت پیام های ورود به سیستم از چارچوب است. اینها می توانند برای اشکال زدایی و عیب یابی مفید باشند.
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate { let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID let kDebugLoggingEnabled = true var window: UIWindow? func applicationDidFinishLaunching(_ application: UIApplication) { let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID) let options = GCKCastOptions(discoveryCriteria: criteria) GCKCastContext.setSharedInstanceWith(options) // Enable logger. GCKLogger.sharedInstance().delegate = self ... } // MARK: - GCKLoggerDelegate func logMessage(_ message: String, at level: GCKLoggerLevel, fromFunction function: String, location: String) { if (kDebugLoggingEnabled) { print(function + " - " + message) } } }
AppDelegate.h
@interface AppDelegate () <GCKLoggerDelegate> @end
AppDelegate.m
@implementation AppDelegate static NSString *const kReceiverAppID = @"AABBCCDD"; static const BOOL kDebugLoggingEnabled = YES; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc] initWithApplicationID:kReceiverAppID]; GCKCastOptions *options = [[GCKCastOptions alloc] initWithDiscoveryCriteria:criteria]; [GCKCastContext setSharedInstanceWithOptions:options]; // Enable logger. [GCKLogger sharedInstance].delegate = self; ... return YES; } ... #pragma mark - GCKLoggerDelegate - (void)logMessage:(NSString *)message atLevel:(GCKLoggerLevel)level fromFunction:(NSString *)function location:(NSString *)location { if (kDebugLoggingEnabled) { NSLog(@"%@ - %@, %@", function, message, location); } } @end
ویجت های بازیگران ux
IOS SDK بازیگران این ابزارک هایی را ارائه می دهد که مطابق با چک لیست طراحی بازیگران هستند:
پوشش مقدماتی : کلاس
GCKCastContext
دارای روشی است ،presentCastInstructionsViewControllerOnceWithCastButton
، که می تواند برای اولین بار در دسترس دکمه بازیگران باشد ، اولین بار که یک گیرنده وب در دسترس است. برنامه فرستنده می تواند متن ، موقعیت متن عنوان و دکمه Dismiss را سفارشی کند.دکمه CAST : با شروع CAST IOS Sender SDK 4.6.0 ، وقتی دستگاه فرستنده به Wi-Fi وصل می شود ، دکمه CAST همیشه قابل مشاهده است. اولین باری که کاربر پس از شروع برنامه ، روی دکمه CAST ضربه می زند ، یک گفتگوی مجوزها ظاهر می شود تا کاربر بتواند دسترسی شبکه محلی برنامه را به دستگاه های موجود در شبکه اعطا کند. پس از آن ، هنگامی که کاربر روی دکمه CAST ضربه می زند ، یک گفتگوی بازیگران نمایش داده می شود که دستگاه های کشف شده را لیست می کند. هنگامی که کاربر هنگام اتصال دستگاه روی دکمه CAST قرار می گیرد ، ابرداده رسانه فعلی (مانند عنوان ، نام استودیو ضبط و تصویر تصویر کوچک) را نشان می دهد یا به کاربر اجازه می دهد تا از دستگاه بازیگران جدا شود. هنگامی که کاربر در حالی که هیچ دستگاهی در دسترس نیست ، روی دکمه CAST ضربه می زند ، صفحه نمایش داده می شود که اطلاعات کاربر را در مورد عدم یافتن دستگاه ها و نحوه عیب یابی نشان می دهد.
Mini Controller : هنگامی که کاربر در حال پخش محتوا است و از صفحه محتوای فعلی یا کنترلر گسترش یافته به صفحه دیگری در برنامه Sender حرکت کرده است ، Mini Controller در انتهای صفحه نمایش داده می شود تا کاربر بتواند ابرداده رسانه ای در حال حاضر را ببیند و پخش را کنترل کند.
کنترلر گسترش یافته : هنگامی که کاربر در حال پخش محتوا است ، اگر روی اعلان رسانه یا Mini Controller کلیک کند ، کنترلر گسترش یافته راه اندازی می شود ، که ابرداده رسانه ای را که در حال حاضر در حال بازی است ، نشان می دهد و چندین دکمه برای کنترل پخش رسانه فراهم می کند.
دکمه بازیگران را اضافه کنید
این چارچوب یک مؤلفه دکمه بازیگران را به عنوان یک زیر کلاس UIButton
ارائه می دهد. می توان آن را با بسته بندی آن در UIBarButtonItem
به نوار عنوان برنامه اضافه کرد. یک زیر کلاس معمولی UIViewController
می تواند یک دکمه بازیگران را به شرح زیر نصب کند:
let castButton = GCKUICastButton(frame: CGRect(x: 0, y: 0, width: 24, height: 24)) castButton.tintColor = UIColor.gray navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)
GCKUICastButton *castButton = [[GCKUICastButton alloc] initWithFrame:CGRectMake(0, 0, 24, 24)]; castButton.tintColor = [UIColor grayColor]; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:castButton];
به طور پیش فرض ، ضربه زدن به دکمه گفتگوی CAST را که توسط Framework ارائه شده است باز می کند.
GCKUICastButton
همچنین می تواند مستقیماً به صفحه داستانی اضافه شود.
کشف دستگاه را پیکربندی کنید
در چارچوب ، کشف دستگاه به طور خودکار اتفاق می افتد. نیازی به شروع صریح یا متوقف کردن فرآیند Discovery نیست ، مگر اینکه یک UI سفارشی را پیاده سازی کنید.
Discovery در این چارچوب توسط کلاس GCKDiscoveryManager
، که خاصیت GCKCastContext
است ، اداره می شود. این فریم ورک یک مؤلفه گفتگوی پیش فرض بازیگران برای انتخاب و کنترل دستگاه ارائه می دهد. لیست دستگاه به صورت واژگانی توسط نام دوستانه دستگاه سفارش داده می شود.
مدیریت جلسه چگونه کار می کند
Cast SDK مفهوم یک جلسه بازیگران را معرفی می کند ، تأسیس آن مراحل اتصال به یک دستگاه ، راه اندازی (یا پیوستن) یک برنامه گیرنده وب ، اتصال به آن برنامه و اولیه سازی کانال کنترل رسانه را ترکیب می کند. برای کسب اطلاعات بیشتر در مورد جلسات بازیگران و چرخه عمر گیرنده وب ، به راهنمای چرخه عمر برنامه گیرنده وب مراجعه کنید.
جلسات توسط کلاس GCKSessionManager
اداره می شود ، که خاصیت GCKCastContext
است. جلسات فردی توسط زیر کلاسهای کلاس GCKSession
نمایش داده می شود: به عنوان مثال ، GCKCastSession
جلساتی را با دستگاه های بازیگران نشان می دهد. شما می توانید به عنوان خاصیت فعلی currentCastSession
از GCKSessionManager
به جلسه بازیگران فعال (در صورت وجود) دسترسی پیدا کنید.
رابط GCKSessionManagerListener
می تواند برای نظارت بر رویدادهای جلسه مانند ایجاد جلسه ، تعلیق ، از سرگیری و خاتمه استفاده شود. این چارچوب به طور خودکار جلسات را به حالت تعلیق در می آورد که برنامه فرستنده به پس زمینه می رود و سعی می کند هنگام بازگشت برنامه به پیش زمینه ، آنها را از سر بگیرد (یا پس از خاتمه برنامه غیر طبیعی/ناگهانی در حالی که یک جلسه فعال بود ، دوباره راه اندازی می شود).
اگر از گفتگوی بازیگران استفاده شود ، در پاسخ به حرکات کاربر ، جلسات ایجاد می شوند و به طور خودکار پاره می شوند. در غیر این صورت ، برنامه می تواند جلسات صریحاً از طریق روش های GCKSessionManager
شروع و پایان یابد.
اگر برنامه در پاسخ به رویدادهای چرخه عمر جلسه نیاز به انجام پردازش ویژه داشته باشد ، می تواند یک یا چند مورد GCKSessionManagerListener
با GCKSessionManager
ثبت کند. GCKSessionManagerListener
یک پروتکل است که برای رویدادهایی از قبیل شروع جلسه ، پایان جلسه و غیره ، تماس تلفنی را تعریف می کند.
انتقال جریان
حفظ حالت جلسه اساس انتقال جریان است ، جایی که کاربران می توانند با استفاده از دستورات صوتی ، برنامه Google Home یا نمایشگرهای هوشمند ، جریان های صوتی و تصویری موجود را در دستگاه ها جابجا کنند. رسانه ها بازی در یک دستگاه (منبع) را متوقف می کنند و در دیگری (مقصد) ادامه می یابد. هر دستگاه بازیگری با آخرین سیستم عامل می تواند به عنوان منبع یا مقصد در انتقال جریان باشد.
برای به دست آوردن دستگاه مقصد جدید در حین انتقال جریان ، از ویژگی GCKCastSession#device
در طی [sessionManager:didResumeCastSession:]
پاسخ به تماس استفاده کنید.
برای اطلاعات بیشتر به انتقال جریان در گیرنده وب مراجعه کنید.
اتصال مجدد خودکار
چارچوب بازیگران منطق اتصال مجدد را برای رسیدگی به صورت خودکار اتصال مجدد در بسیاری از موارد گوشه ای ظریف ، مانند:
- بهبودی از دست دادن موقت WiFi
- بهبودی از خواب دستگاه
- از پس زمینه برنامه بازیابی کنید
- اگر برنامه خراب شد ، بازیابی کنید
کنترل رسانه چگونه کار می کند
اگر یک جلسه بازیگران با یک برنامه گیرنده وب که از فضای نام رسانه ای پشتیبانی می کند ، ایجاد شود ، نمونه ای از GCKRemoteMediaClient
به طور خودکار توسط چارچوب ایجاد می شود. می توان آن را به عنوان خاصیت remoteMediaClient
نمونه GCKCastSession
دسترسی پیدا کرد.
کلیه روشهای موجود در GCKRemoteMediaClient
که درخواست های مربوط به گیرنده وب را صادر می کند ، یک شی GCKRequest
را باز می گرداند که می تواند برای ردیابی آن درخواست استفاده شود. یک GCKRequestDelegate
می توان به این شیء اختصاص داد تا در مورد نتیجه نهایی عملیات اعلان هایی را دریافت کند.
انتظار می رود که نمونه GCKRemoteMediaClient
توسط چندین قسمت از برنامه به اشتراک گذاشته شود ، و در واقع برخی از مؤلفه های داخلی چارچوب مانند گفتگوی بازیگران و کنترل های مینی رسانه ها نمونه ای را به اشتراک می گذارند. برای این منظور ، GCKRemoteMediaClient
از ثبت نام های مختلف GCKRemoteMediaClientListener
S پشتیبانی می کند.
ابرداده رسانه ای را تنظیم کنید
کلاس GCKMediaMetadata
اطلاعات مربوط به یک مورد رسانه ای را که می خواهید بازی کنید نشان می دهد. مثال زیر یک نمونه جدید GCKMediaMetadata
از یک فیلم ایجاد می کند و عنوان ، زیرنویس ، نام استودیوی ضبط و دو تصویر را تنظیم می کند.
let metadata = GCKMediaMetadata() metadata.setString("Big Buck Bunny (2008)", forKey: kGCKMetadataKeyTitle) metadata.setString("Big Buck Bunny tells the story of a giant rabbit with a heart bigger than " + "himself. When one sunny day three rodents rudely harass him, something " + "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon " + "tradition he prepares the nasty rodents a comical revenge.", forKey: kGCKMetadataKeySubtitle) metadata.addImage(GCKImage(url: URL(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg")!, width: 480, height: 360))
GCKMediaMetadata *metadata = [[GCKMediaMetadata alloc] initWithMetadataType:GCKMediaMetadataTypeMovie]; [metadata setString:@"Big Buck Bunny (2008)" forKey:kGCKMetadataKeyTitle]; [metadata setString:@"Big Buck Bunny tells the story of a giant rabbit with a heart bigger than " "himself. When one sunny day three rodents rudely harass him, something " "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon " "tradition he prepares the nasty rodents a comical revenge." forKey:kGCKMetadataKeySubtitle]; [metadata addImage:[[GCKImage alloc] initWithURL:[[NSURL alloc] initWithString:@"https://commondatastorage.googleapis.com/" "gtv-videos-bucket/sample/images/BigBuckBunny.jpg"] width:480 height:360]];
بخش انتخاب و ذخیره تصویر را در مورد استفاده از تصاویر با ابرداده رسانه مشاهده کنید.
رسانه بار
برای بارگیری یک مورد رسانه ای ، با استفاده از ابرداده رسانه ، یک نمونه GCKMediaInformation
ایجاد کنید. سپس GCKCastSession
فعلی را دریافت کرده و از GCKRemoteMediaClient
خود برای بارگیری رسانه در برنامه گیرنده استفاده کنید. سپس می توانید از GCKRemoteMediaClient
برای کنترل یک برنامه پخش کننده رسانه ای که روی گیرنده اجرا می شود ، مانند بازی ، مکث و توقف استفاده کنید.
let url = URL.init(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4") guard let mediaURL = url else { print("invalid mediaURL") return } let mediaInfoBuilder = GCKMediaInformationBuilder.init(contentURL: mediaURL) mediaInfoBuilder.streamType = GCKMediaStreamType.none; mediaInfoBuilder.contentType = "video/mp4" mediaInfoBuilder.metadata = metadata; mediaInformation = mediaInfoBuilder.build() guard let mediaInfo = mediaInformation else { print("invalid mediaInformation") return } if let request = sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInfo) { request.delegate = self }
GCKMediaInformationBuilder *mediaInfoBuilder = [[GCKMediaInformationBuilder alloc] initWithContentURL: [NSURL URLWithString:@"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"]]; mediaInfoBuilder.streamType = GCKMediaStreamTypeNone; mediaInfoBuilder.contentType = @"video/mp4"; mediaInfoBuilder.metadata = metadata; self.mediaInformation = [mediaInfoBuilder build]; GCKRequest *request = [self.sessionManager.currentSession.remoteMediaClient loadMedia:self.mediaInformation]; if (request != nil) { request.delegate = self; }
همچنین به بخش استفاده از آهنگ های رسانه ای مراجعه کنید.
فرمت ویدیویی 4K
برای تعیین اینکه رسانه شما از چه قالب ویدیویی استفاده می کند ، از ویژگی videoInfo
GCKMediaStatus
استفاده کنید تا نمونه فعلی GCKVideoInfo
را بدست آورید. این نمونه شامل نوع قالب تلویزیون HDR و ارتفاع و عرض در پیکسل ها است. انواع فرمت 4K در ویژگی hdrType
با مقادیر enum GCKVideoInfoHDRType
نشان داده شده است.
کنترل کننده های مینی را اضافه کنید
با توجه به لیست چک لیست بازیگران ، یک برنامه فرستنده باید یک کنترل مداوم به عنوان مینی کنترلر را ارائه دهد که هنگام حرکت کاربر از صفحه محتوای فعلی ، باید ظاهر شود. Mini Controller دسترسی فوری و یادآوری قابل مشاهده برای جلسه بازیگران فعلی را فراهم می کند.
چارچوب بازیگران یک نوار کنترل ، GCKUIMiniMediaControlsViewController
را فراهم می کند ، که می تواند به صحنه هایی اضافه شود که در آن می خواهید مینی کنترلر را نشان دهید.
هنگامی که برنامه Sender شما در حال پخش یک پخش مستقیم ویدیو یا صوتی است ، SDK به طور خودکار دکمه پخش/توقف را به جای دکمه پخش/مکث در مینی کنترلر نمایش می دهد.
برای نحوه ارسال برنامه فرستنده شما می تواند ظاهر ویجت های بازیگران را تنظیم کند.
دو روش برای افزودن مینی کنترلر به یک برنامه فرستنده وجود دارد:
- بگذارید چارچوب بازیگران با پیچیدن کنترلر نمای موجود خود با کنترلر نمای خود ، طرح Mini Controller را مدیریت کند.
- با اضافه کردن آن به کنترل کننده نمای موجود خود ، با ارائه یک نمای زیر در صفحه داستانی ، طرح ویجت Mini Controller را مدیریت کنید.
با استفاده از GCKUICASTCONTAINERVIEWCONTROLLER بسته بندی کنید
اولین راه استفاده از GCKUICastContainerViewController
است که کنترل کننده نمای دیگری را می پیچد و یک GCKUIMiniMediaControlsViewController
در پایین اضافه می کند. این رویکرد محدود است به این دلیل که شما نمی توانید انیمیشن را سفارشی کنید و نمی توانید رفتار کنترلر نمای کانتینر را پیکربندی کنید.
این روش اول به طور معمول در -[application:didFinishLaunchingWithOptions:]
روش نماینده برنامه انجام می شود:
func applicationDidFinishLaunching(_ application: UIApplication) { ... // Wrap main view in the GCKUICastContainerViewController and display the mini controller. let appStoryboard = UIStoryboard(name: "Main", bundle: nil) let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation") let castContainerVC = GCKCastContext.sharedInstance().createCastContainerController(for: navigationController) castContainerVC.miniMediaControlsItemEnabled = true window = UIWindow(frame: UIScreen.main.bounds) window!.rootViewController = castContainerVC window!.makeKeyAndVisible() ... }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // Wrap main view in the GCKUICastContainerViewController and display the mini controller. UIStoryboard *appStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; UINavigationController *navigationController = [appStoryboard instantiateViewControllerWithIdentifier:@"MainNavigation"]; GCKUICastContainerViewController *castContainerVC = [[GCKCastContext sharedInstance] createCastContainerControllerForViewController:navigationController]; castContainerVC.miniMediaControlsItemEnabled = YES; self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; self.window.rootViewController = castContainerVC; [self.window makeKeyAndVisible]; ... }
var castControlBarsEnabled: Bool { set(enabled) { if let castContainerVC = self.window?.rootViewController as? GCKUICastContainerViewController { castContainerVC.miniMediaControlsItemEnabled = enabled } else { print("GCKUICastContainerViewController is not correctly configured") } } get { if let castContainerVC = self.window?.rootViewController as? GCKUICastContainerViewController { return castContainerVC.miniMediaControlsItemEnabled } else { print("GCKUICastContainerViewController is not correctly configured") return false } } }
AppDelegate.h
@interface AppDelegate : UIResponder <UIApplicationDelegate> @property (nonatomic, strong) UIWindow *window; @property (nonatomic, assign) BOOL castControlBarsEnabled; @end
AppDelegate.m
@implementation AppDelegate ... - (void)setCastControlBarsEnabled:(BOOL)notificationsEnabled { GCKUICastContainerViewController *castContainerVC; castContainerVC = (GCKUICastContainerViewController *)self.window.rootViewController; castContainerVC.miniMediaControlsItemEnabled = notificationsEnabled; } - (BOOL)castControlBarsEnabled { GCKUICastContainerViewController *castContainerVC; castContainerVC = (GCKUICastContainerViewController *)self.window.rootViewController; return castContainerVC.miniMediaControlsItemEnabled; } ... @end
در کنترل کننده نمای موجود جاسازی شده است
راه دوم اضافه کردن مینی کنترلر به طور مستقیم به کنترلر مشاهده موجود خود با استفاده از createMiniMediaControlsViewController
برای ایجاد یک نمونه GCKUIMiniMediaControlsViewController
و سپس اضافه کردن آن به کنترلر Container View به عنوان یک نمای زیر.
کنترلر نمایش خود را در نماینده برنامه تنظیم کنید:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { ... GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true window?.clipsToBounds = true let rootContainerVC = (window?.rootViewController as? RootContainerViewController) rootContainerVC?.miniMediaControlsViewEnabled = true ... return true }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES; self.window.clipsToBounds = YES; RootContainerViewController *rootContainerVC; rootContainerVC = (RootContainerViewController *)self.window.rootViewController; rootContainerVC.miniMediaControlsViewEnabled = YES; ... return YES; }
در کنترلر Root View خود ، یک نمونه GCKUIMiniMediaControlsViewController
ایجاد کرده و به عنوان یک نمای زیر به کنترلر نمای کانتینر اضافه کنید:
let kCastControlBarsAnimationDuration: TimeInterval = 0.20 @objc(RootContainerViewController) class RootContainerViewController: UIViewController, GCKUIMiniMediaControlsViewControllerDelegate { @IBOutlet weak private var _miniMediaControlsContainerView: UIView! @IBOutlet weak private var _miniMediaControlsHeightConstraint: NSLayoutConstraint! private var miniMediaControlsViewController: GCKUIMiniMediaControlsViewController! var miniMediaControlsViewEnabled = false { didSet { if self.isViewLoaded { self.updateControlBarsVisibility() } } } var overriddenNavigationController: UINavigationController? override var navigationController: UINavigationController? { get { return overriddenNavigationController } set { overriddenNavigationController = newValue } } var miniMediaControlsItemEnabled = false override func viewDidLoad() { super.viewDidLoad() let castContext = GCKCastContext.sharedInstance() self.miniMediaControlsViewController = castContext.createMiniMediaControlsViewController() self.miniMediaControlsViewController.delegate = self self.updateControlBarsVisibility() self.installViewController(self.miniMediaControlsViewController, inContainerView: self._miniMediaControlsContainerView) } func updateControlBarsVisibility() { if self.miniMediaControlsViewEnabled && self.miniMediaControlsViewController.active { self._miniMediaControlsHeightConstraint.constant = self.miniMediaControlsViewController.minHeight self.view.bringSubview(toFront: self._miniMediaControlsContainerView) } else { self._miniMediaControlsHeightConstraint.constant = 0 } UIView.animate(withDuration: kCastControlBarsAnimationDuration, animations: {() -> Void in self.view.layoutIfNeeded() }) self.view.setNeedsLayout() } func installViewController(_ viewController: UIViewController?, inContainerView containerView: UIView) { if let viewController = viewController { self.addChildViewController(viewController) viewController.view.frame = containerView.bounds containerView.addSubview(viewController.view) viewController.didMove(toParentViewController: self) } } func uninstallViewController(_ viewController: UIViewController) { viewController.willMove(toParentViewController: nil) viewController.view.removeFromSuperview() viewController.removeFromParentViewController() } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "NavigationVCEmbedSegue" { self.navigationController = (segue.destination as? UINavigationController) } } ...
rootContainerViewController.h
static const NSTimeInterval kCastControlBarsAnimationDuration = 0.20; @interface RootContainerViewController () <GCKUIMiniMediaControlsViewControllerDelegate> { __weak IBOutlet UIView *_miniMediaControlsContainerView; __weak IBOutlet NSLayoutConstraint *_miniMediaControlsHeightConstraint; GCKUIMiniMediaControlsViewController *_miniMediaControlsViewController; } @property(nonatomic, weak, readwrite) UINavigationController *navigationController; @property(nonatomic, assign, readwrite) BOOL miniMediaControlsViewEnabled; @property(nonatomic, assign, readwrite) BOOL miniMediaControlsItemEnabled; @end
rootContainerViewController.m
@implementation RootContainerViewController - (void)viewDidLoad { [super viewDidLoad]; GCKCastContext *castContext = [GCKCastContext sharedInstance]; _miniMediaControlsViewController = [castContext createMiniMediaControlsViewController]; _miniMediaControlsViewController.delegate = self; [self updateControlBarsVisibility]; [self installViewController:_miniMediaControlsViewController inContainerView:_miniMediaControlsContainerView]; } - (void)setMiniMediaControlsViewEnabled:(BOOL)miniMediaControlsViewEnabled { _miniMediaControlsViewEnabled = miniMediaControlsViewEnabled; if (self.isViewLoaded) { [self updateControlBarsVisibility]; } } - (void)updateControlBarsVisibility { if (self.miniMediaControlsViewEnabled && _miniMediaControlsViewController.active) { _miniMediaControlsHeightConstraint.constant = _miniMediaControlsViewController.minHeight; [self.view bringSubviewToFront:_miniMediaControlsContainerView]; } else { _miniMediaControlsHeightConstraint.constant = 0; } [UIView animateWithDuration:kCastControlBarsAnimationDuration animations:^{ [self.view layoutIfNeeded]; }]; [self.view setNeedsLayout]; } - (void)installViewController:(UIViewController *)viewController inContainerView:(UIView *)containerView { if (viewController) { [self addChildViewController:viewController]; viewController.view.frame = containerView.bounds; [containerView addSubview:viewController.view]; [viewController didMoveToParentViewController:self]; } } - (void)uninstallViewController:(UIViewController *)viewController { [viewController willMoveToParentViewController:nil]; [viewController.view removeFromSuperview]; [viewController removeFromParentViewController]; } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"NavigationVCEmbedSegue"]) { self.navigationController = (UINavigationController *)segue.destinationViewController; } } ... @end
GCKUIMiniMediaControlsViewControllerDelegate
به کنترل کننده نمای میزبان می گوید که مینی کنترلر قابل مشاهده است:
func miniMediaControlsViewController(_: GCKUIMiniMediaControlsViewController, shouldAppear _: Bool) { updateControlBarsVisibility() }
- (void)miniMediaControlsViewController: (GCKUIMiniMediaControlsViewController *)miniMediaControlsViewController shouldAppear:(BOOL)shouldAppear { [self updateControlBarsVisibility]; }
کنترلر گسترده را اضافه کنید
چک لیست طراحی Google Cast به یک برنامه فرستنده نیاز دارد تا یک کنترلر گسترده را برای رسانه های بازیگران ارائه دهد. کنترلر گسترش یافته یک نسخه کامل از Mini Controller است.
کنترلر گسترش یافته یک نمای تمام صفحه است که کنترل کامل پخش رسانه ای از راه دور را ارائه می دهد. این دیدگاه باید به یک برنامه ریخته گری اجازه دهد تا هر جنبه قابل کنترل در یک جلسه بازیگران را مدیریت کند ، به استثنای کنترل حجم گیرنده وب و چرخه چرخه جلسه (Connect/Stop Casting). همچنین تمام اطلاعات وضعیت در مورد جلسه رسانه (آثار هنری ، عنوان ، زیرنویس و غیره) را ارائه می دهد.
عملکرد این دیدگاه توسط کلاس GCKUIExpandedMediaControlsViewController
اجرا می شود.
اولین کاری که شما باید انجام دهید این است که کنترل کننده پیش فرض گسترش یافته را در زمینه بازیگران فعال کنید. نماینده برنامه را اصلاح کنید تا کنترلر پیش فرض گسترش یافته را فعال کنید:
func applicationDidFinishLaunching(_ application: UIApplication) { .. GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true ... }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES; .. }
کد زیر را به کنترلر مشاهده خود اضافه کنید تا هنگامی که کاربر شروع به تهیه یک ویدیو کرد ، کنترلر گسترش یافته را بارگیری کنید:
func playSelectedItemRemotely() { GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls() ... // Load your media sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInformation) }
- (void)playSelectedItemRemotely { [[GCKCastContext sharedInstance] presentDefaultExpandedMediaControls]; ... // Load your media [self.sessionManager.currentSession.remoteMediaClient loadMedia:mediaInformation]; }
هنگامی که کاربر کنترلر مینی را کنترل می کند ، کنترلر گسترش یافته نیز به طور خودکار راه اندازی می شود.
هنگامی که برنامه Sender شما در حال پخش یک پخش مستقیم ویدیو یا صوتی است ، SDK به طور خودکار دکمه پخش/توقف را به جای دکمه پخش/مکث در کنترلر گسترش یافته نمایش می دهد.
برای اینکه چگونه برنامه فرستنده شما می تواند ظاهر ابزارک های بازیگران را پیکربندی کند ، سبک های سفارشی را در برنامه iOS خود اعمال کنید .
کنترل صدا
چارچوب بازیگران به طور خودکار حجم برنامه Sender را مدیریت می کند. این چارچوب به طور خودکار با حجم گیرنده وب برای ابزارک های UI عرضه شده همزمان می شود. برای همگام سازی یک کشویی ارائه شده توسط برنامه ، از GCKUIDeviceVolumeController
استفاده کنید.
کنترل حجم دکمه فیزیکی
از دکمه های حجم فیزیکی در دستگاه فرستنده می توان برای تغییر حجم جلسه ریخته گری در گیرنده وب با استفاده از پرچم physicalVolumeButtonsWillControlDeviceVolume
در GCKCastOptions
استفاده کرد ، که در GCKCastContext
تنظیم شده است.
let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID) let options = GCKCastOptions(discoveryCriteria: criteria) options.physicalVolumeButtonsWillControlDeviceVolume = true GCKCastContext.setSharedInstanceWith(options)
GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc] initWithApplicationID:kReceiverAppID]; GCKCastOptions *options = [[GCKCastOptions alloc] initWithDiscoveryCriteria :criteria]; options.physicalVolumeButtonsWillControlDeviceVolume = YES; [GCKCastContext setSharedInstanceWithOptions:options];
رسیدگی به خطاها
برای برنامه های فرستنده بسیار مهم است که همه تماس های خطای خطا را انجام دهند و بهترین پاسخ را برای هر مرحله از چرخه زندگی بازیگران تصمیم بگیرند. برنامه می تواند گفتگوی خطا را به کاربر نمایش دهد یا می تواند تصمیم بگیرد که جلسه بازیگران را پایان دهد.
ورود به سیستم
GCKLogger
یک تک آهنگ است که برای ورود به سیستم توسط چارچوب استفاده می شود. برای سفارشی کردن نحوه رسیدگی به پیام های ورود به سیستم ، از GCKLoggerDelegate
استفاده کنید.
SDK با استفاده از GCKLogger
، خروجی ورود به سیستم را به صورت پیام های اشکال زدایی ، خطاها و هشدارها تولید می کند. این پیام های ورود به سیستم اشکال زدایی کمک می کنند و برای عیب یابی و شناسایی مشکلات مفید هستند. به طور پیش فرض ، خروجی ورود به سیستم سرکوب می شود ، اما با اختصاص GCKLoggerDelegate
، برنامه فرستنده می تواند این پیام ها را از SDK دریافت کرده و آنها را به کنسول سیستم وارد کند.
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate { let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID let kDebugLoggingEnabled = true var window: UIWindow? func applicationDidFinishLaunching(_ application: UIApplication) { ... // Enable logger. GCKLogger.sharedInstance().delegate = self ... } // MARK: - GCKLoggerDelegate func logMessage(_ message: String, at level: GCKLoggerLevel, fromFunction function: String, location: String) { if (kDebugLoggingEnabled) { print(function + " - " + message) } } }
AppDelegate.h
@interface AppDelegate () <GCKLoggerDelegate> @end
AppDelegate.m
@implementation AppDelegate static NSString *const kReceiverAppID = @"AABBCCDD"; static const BOOL kDebugLoggingEnabled = YES; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // Enable logger. [GCKLogger sharedInstance].delegate = self; ... return YES; } ... #pragma mark - GCKLoggerDelegate - (void)logMessage:(NSString *)message atLevel:(GCKLoggerLevel)level fromFunction:(NSString *)function location:(NSString *)location { if (kDebugLoggingEnabled) { NSLog(@"%@ - %@, %@", function, message, location); } } @end
برای فعال کردن پیام های اشکال زدایی و Verbose نیز ، این خط را پس از تنظیم نماینده (که قبلاً نشان داده شده است) به کد اضافه کنید:
let filter = GCKLoggerFilter.init() filter.minimumLevel = GCKLoggerLevel.verbose GCKLogger.sharedInstance().filter = filter
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init]; [filter setMinimumLevel:GCKLoggerLevelVerbose]; [GCKLogger sharedInstance].filter = filter;
همچنین می توانید پیام های ورود به سیستم تولید شده توسط GCKLogger
را فیلتر کنید. به عنوان مثال حداقل سطح ورود به سیستم را در هر کلاس تنظیم کنید:
let filter = GCKLoggerFilter.init() filter.setLoggingLevel(GCKLoggerLevel.verbose, forClasses: ["GCKUICastButton", "GCKUIImageCache", "NSMutableDictionary"]) GCKLogger.sharedInstance().filter = filter
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init]; [filter setLoggingLevel:GCKLoggerLevelVerbose forClasses:@[@"GCKUICastButton", @"GCKUIImageCache", @"NSMutableDictionary" ]]; [GCKLogger sharedInstance].filter = filter;
نام کلاس می تواند نام تحت اللفظی یا الگوهای کره باشد ، به عنوان مثال ، GCK\*Session
GCKUI\*
و GCK \*.