Bu geliştirici kılavuzunda, iOS gönderen SDK'sını kullanarak iOS gönderen uygulamanıza Google Cast desteğinin nasıl ekleneceği açıklanmaktadır.
Mobil cihaz veya dizüstü bilgisayar, oynatmayı kontrol eden gönderen, Google Cast cihazı ise içeriği TV'de gösteren alıcıdır.
Gönderen çerçevesi, gönderende çalışma zamanında bulunan Cast sınıf kitaplığı ikili programını ve ilişkili kaynakları ifade eder. Gönderen uygulama veya Cast uygulaması, gönderende de çalışan bir uygulamayı ifade eder. Web Alıcısı uygulaması, Web Alıcısı'nda çalışan HTML uygulamasını ifade eder.
Gönderen çerçevesi, gönderen uygulamayı etkinlikler hakkında bilgilendirmek ve Cast uygulama yaşam döngüsünün çeşitli durumları arasında geçiş yapmak için eşzamansız bir geri çağırma tasarımı kullanır.
Uygulama akışı
Aşağıdaki adımlarda, gönderen iOS uygulaması için tipik üst düzey yürütme akışı açıklanmaktadır:
- Cast çerçevesi, cihazları taramaya başlamak için
GCKCastOptionsiçinde sağlanan özelliklere göreGCKDiscoveryManageröğesini başlatır. - Kullanıcı, Yayınla düğmesini tıkladığında çerçeve, keşfedilen yayın cihazlarının listesini içeren Yayınla iletişim kutusunu gösterir.
- Kullanıcı bir yayın cihazı seçtiğinde çerçeve, yayın cihazında Web Alıcı uygulamasını başlatmaya çalışır.
- Çerçeve, Web Alıcı uygulamasının başlatıldığını onaylamak için gönderen uygulamadaki geri çağırmaları çağırır.
- Çerçeve, gönderen ve Web Alıcı uygulamaları arasında bir iletişim kanalı oluşturur.
- Çerçeve, Web Alıcı'da medya oynatmayı yüklemek ve kontrol etmek için iletişim kanalını kullanır.
- Çerçeve, medya oynatma durumunu gönderen ile Web Alıcısı arasında senkronize eder: Kullanıcı, gönderen kullanıcı arayüzü işlemlerini yaptığında çerçeve, bu medya kontrol isteklerini Web Alıcısı'na iletir ve Web Alıcısı medya durumu güncellemelerini gönderdiğinde çerçeve, gönderen kullanıcı arayüzünün durumunu günceller.
- Kullanıcı, yayın cihazıyla bağlantıyı kesmek için yayın düğmesini tıkladığında çerçeve, gönderen uygulamanın web alıcısıyla bağlantısını keser.
Göndericinizle ilgili sorunları gidermek için günlük kaydını etkinleştirmeniz gerekir.
Google Cast iOS çerçevesindeki tüm sınıfların, yöntemlerin ve etkinliklerin kapsamlı bir listesi için Google Cast iOS API Referansı'na bakın. Aşağıdaki bölümlerde, Cast'i iOS uygulamanıza entegre etme adımları açıklanmaktadır.
Ana iş parçacığından yöntemleri çağırma
Cast bağlamını başlatma
Cast çerçevesinde, çerçevenin tüm etkinliklerini koordine eden global bir tekil nesne olan GCKCastContext bulunur. Gönderen uygulama yeniden başlatıldığında otomatik oturum devam ettirme özelliğinin düzgün şekilde tetiklenebilmesi için bu nesne, uygulamanın yaşam döngüsünün başlarında (genellikle uygulama temsilcisinin -[application:didFinishLaunchingWithOptions:] yönteminde) başlatılmalıdır.
GCKCastContext başlatılırken bir GCKCastOptions nesnesi sağlanmalıdır.
Bu sınıf, çerçevenin davranışını etkileyen seçenekler içerir. Bunlardan en önemlisi, keşif sonuçlarını filtrelemek ve bir yayın oturumu başlatıldığında Web Alıcısı uygulamasını başlatmak için kullanılan Web Alıcısı uygulama kimliğidir.
-[application:didFinishLaunchingWithOptions:] yöntemi, çerçeveden günlük mesajlarını almak için bir günlük kaydı temsilcisi oluşturmak için de iyi bir yerdir.
Bu bilgiler, hata ayıklama ve sorun giderme için yararlı olabilir.
@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 kullanıcı deneyimi widget'ları
Cast iOS SDK'sı, Cast Tasarım Kontrol Listesi'ne uygun olan şu widget'ları sağlar:
Tanıtım amaçlı yer paylaşımı:
GCKCastContextsınıfında, bir Web Alıcı ilk kez kullanılabilir olduğunda Yayınla düğmesini öne çıkarmak için kullanılabilecek birpresentCastInstructionsViewControllerOnceWithCastButtonyöntemi vardır. Gönderen uygulama, metni, başlık metninin konumunu ve Kapat düğmesini özelleştirebilir.Yayınla düğmesi: Cast iOS gönderen SDK'sı 4.6.0 sürümünden itibaren, gönderen cihaz kablosuz ağa bağlıyken yayınla düğmesi her zaman görünür. Kullanıcı, uygulamayı ilk kez başlattıktan sonra Yayınla düğmesine ilk kez dokunduğunda bir izin iletişim kutusu görünür. Böylece kullanıcı, uygulamaya ağdaki cihazlara yerel ağ erişimi izni verebilir. Ardından, kullanıcı yayınla düğmesine dokunduğunda, keşfedilen cihazların listelendiği bir yayınlama iletişim kutusu gösterilir. Cihaz bağlıyken kullanıcı yayın düğmesine dokunduğunda mevcut medya meta verileri (ör. başlık, kayıt stüdyosunun adı ve küçük resim) gösterilir veya kullanıcının yayın cihazıyla bağlantısını kesmesine izin verilir. Kullanıcı, kullanılabilir cihaz yokken yayınla düğmesine dokunduğunda, cihazların neden bulunamadığı ve sorunun nasıl giderileceği hakkında bilgi veren bir ekran gösterilir.
Mini kumanda: Kullanıcı içerik yayınlarken mevcut içerik sayfasından veya genişletilmiş kumandadan gönderen uygulamadaki başka bir ekrana gittiğinde, kullanıcının o anda yayınlanan medya meta verilerini görmesine ve oynatmayı kontrol etmesine olanak tanımak için ekranın alt kısmında mini kumanda gösterilir.
Genişletilmiş kumanda: Kullanıcı içerik yayınlarken medya bildirimini veya mini kumandayı tıklarsa genişletilmiş kumanda açılır. Bu kumanda, o anda oynatılan medya meta verilerini gösterir ve medya oynatmayı kontrol etmek için çeşitli düğmeler sunar.
Yayınla düğmesi ekleme
Çerçeve, UIButton alt sınıfı olarak bir Yayınla düğmesi bileşeni sağlar. UIBarButtonItem içine sarmalanarak uygulamanın başlık çubuğuna eklenebilir. Tipik bir UIViewController alt sınıfı, Yayınla düğmesini aşağıdaki gibi yükleyebilir:
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];
Varsayılan olarak, düğmeye dokunulduğunda çerçeve tarafından sağlanan Cast iletişim kutusu açılır.
GCKUICastButton
doğrudan storyboard'a da eklenebilir.
Cihaz keşfini yapılandırma
Çerçevede cihaz keşfi otomatik olarak gerçekleşir. Özel bir kullanıcı arayüzü uygulamadığınız sürece keşif sürecini açıkça başlatmanız veya durdurmanız gerekmez.
Çerçevedeki keşif, GCKCastContext'nin bir özelliği olan GCKDiscoveryManager sınıfı tarafından yönetilir. Çerçeve, cihaz seçimi ve kontrolü için varsayılan bir Cast iletişim kutusu bileşeni sağlar. Cihaz listesi, cihazın kolay adına göre alfabetik olarak sıralanır.
Oturum yönetiminin işleyiş şekli
Cast SDK'sı, Cast oturumu kavramını sunar. Cast oturumu oluşturulurken bir cihaza bağlanma, Web Alıcı uygulamasını başlatma (veya uygulamaya katılma), bu uygulamaya bağlanma ve medya kontrol kanalı başlatma adımları birleştirilir. Yayın oturumları ve Web Alıcısı yaşam döngüsü hakkında daha fazla bilgi için Web Alıcısı Uygulama yaşam döngüsü kılavuzuna bakın.
Oturumlar, GCKCastContext'ın bir özelliği olan GCKSessionManager sınıfı tarafından yönetilir.
Bağımsız oturumlar, GCKSession sınıfının alt sınıflarıyla temsil edilir. Örneğin, GCKCastSession, Cast cihazlarıyla yapılan oturumları temsil eder. GCKSessionManager öğesinin currentCastSession özelliği olarak, etkin durumdaki yayın oturumuna (varsa) erişebilirsiniz.
GCKSessionManagerListener arayüzü, oturum oluşturma, askıya alma, devam ettirme ve sonlandırma gibi oturum etkinliklerini izlemek için kullanılabilir. Çerçeve, gönderen uygulama arka plana geçtiğinde oturumları otomatik olarak askıya alır ve uygulama ön plana döndüğünde (veya bir oturum etkinken anormal/ani bir uygulama sonlandırmasından sonra yeniden başlatıldığında) oturumları devam ettirmeye çalışır.
Yayınlama iletişim kutusu kullanılıyorsa oturumlar, kullanıcı hareketlerine yanıt olarak otomatik olarak oluşturulur ve kaldırılır. Aksi takdirde uygulama, GCKSessionManager yöntemleri aracılığıyla oturumları açıkça başlatıp sonlandırabilir.
Uygulamanın, oturum yaşam döngüsü etkinliklerine yanıt olarak özel işlem yapması gerekiyorsa GCKSessionManager ile bir veya daha fazla GCKSessionManagerListener örneği kaydedebilir. GCKSessionManagerListener, oturum başlangıcı ve oturum sonu gibi etkinlikler için geri çağırmaları tanımlayan bir protokoldür.
Akış aktarma
Oturum durumunu koruma, akış aktarmanın temelidir. Kullanıcılar sesli komutlar, Google Home uygulaması veya akıllı ekranlar aracılığıyla mevcut ses ve video akışlarını cihazlar arasında taşıyabilir. Medya bir cihazda (kaynak) durur ve başka bir cihazda (hedef) devam eder. En yeni donanım yazılımına sahip tüm Cast cihazları, akış aktarma işleminde kaynak veya hedef olarak kullanılabilir.
Akış aktarma sırasında yeni hedef cihazı almak için [sessionManager:didResumeCastSession:] geri çağırma sırasında GCKCastSession#device özelliğini kullanın.
Daha fazla bilgi için Web Alıcısı'nda akış aktarma başlıklı makaleyi inceleyin.
Otomatik yeniden bağlanma
Cast çerçevesi, aşağıdaki gibi birçok küçük uç durumda yeniden bağlanmayı otomatik olarak işlemek için yeniden bağlanma mantığı ekler:
- Geçici kablosuz bağlantı kaybından kurtarma
- Cihazın uyku modundan çıkması
- Uygulamayı arka plana alma işleminden kurtarma
- Uygulama kilitlendiyse kurtarma
Medya kontrolünün işleyiş şekli
Medya ad alanını destekleyen bir Web Alıcısı uygulamasıyla yayın oturumu oluşturulursa çerçeve tarafından otomatik olarak bir GCKRemoteMediaClient örneği oluşturulur. Bu örneğe, GCKCastSession örneğinin remoteMediaClient özelliği olarak erişilebilir.
GCKRemoteMediaClient üzerinde Web Alıcı'ya istek gönderen tüm yöntemler, bu isteği izlemek için kullanılabilecek bir GCKRequest nesnesi döndürür. İşlemin nihai sonucuyla ilgili bildirim almak için bu nesneye bir GCKRequestDelegate atanabilir.
GCKRemoteMediaClient örneğinin, uygulamanın birden fazla bölümü tarafından paylaşılması beklenir. Hatta Cast iletişim kutusu ve mini medya kontrolleri gibi çerçevenin bazı dahili bileşenleri de bu örneği paylaşır. Bu amaçla GCKRemoteMediaClient, birden fazla GCKRemoteMediaClientListener kaydını destekler.
Medya meta verilerini ayarlama
GCKMediaMetadata
sınıfı, yayınlamak istediğiniz bir medya öğesiyle ilgili bilgileri temsil eder. Aşağıdaki örnekte, bir filmin yeni bir GCKMediaMetadata örneği oluşturulmakta ve başlık, alt başlık, kayıt stüdyosunun adı ve iki resim ayarlanmaktadır.
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]];
Medya meta verileriyle resimlerin kullanımı hakkında bilgi edinmek için Resim Seçimi ve Önbelleğe Alma bölümüne bakın.
Medyayı yükle
Bir medya öğesini yüklemek için medyanın meta verilerini kullanarak bir GCKMediaInformation örneği oluşturun. Ardından geçerli GCKCastSession nesnesini alın ve medya içeriğini alıcı uygulamaya yüklemek için bu nesnenin GCKRemoteMediaClient yöntemini kullanın. Daha sonra, alıcıda çalışan bir medya oynatıcı uygulamasını kontrol etmek (ör. oynatmak, duraklatmak ve durdurmak) için GCKRemoteMediaClient yöntemini kullanabilirsiniz.
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; }
Medya parçalarını kullanma ile ilgili bölüme de göz atın.
4K video biçimi
Medyalarınızın video biçimini belirlemek için GCKMediaStatus öğesinin videoInfo özelliğini kullanarak GCKVideoInfo öğesinin geçerli örneğini alın.
Bu örnek, HDR TV biçiminin türünü ve piksel cinsinden yükseklik ile genişliği içerir. 4K biçiminin varyantları, hdrType özelliğinde GCKVideoInfoHDRType enum değerleriyle belirtilir.
Mini kumanda ekleme
Cast Tasarım Kontrol Listesi'ne göre, gönderen uygulaması, kullanıcı mevcut içerik sayfasından ayrıldığında görünmesi gereken mini kumanda olarak bilinen kalıcı bir kontrol sağlamalıdır. Mini kumanda, mevcut yayın oturumuna anında erişim ve görünür bir hatırlatıcı sağlar.
Cast çerçevesi, mini kumandayı göstermek istediğiniz sahnelere eklenebilecek bir kontrol çubuğu (GCKUIMiniMediaControlsViewController) sağlar.
Gönderen uygulamanız bir video veya ses canlı yayını oynatırken SDK, mini kumandadaki oynat/duraklat düğmesinin yerine otomatik olarak bir oynat/durdur düğmesi gösterir.
Gönderen uygulamanızın, Cast widget'larının görünümünü nasıl yapılandırabileceğini öğrenmek için iOS Gönderen Kullanıcı Arayüzünü Özelleştirme başlıklı makaleyi inceleyin.
Mini kumandayı gönderen uygulamaya eklemenin iki yolu vardır:
- Mevcut görünüm denetleyicinizi kendi görünüm denetleyicisiyle sarmalayarak Cast çerçevesinin mini kumandanın düzenini yönetmesine izin verin.
- Film şeridinde bir alt görünüm sağlayarak mini kumanda widget'ını mevcut görünüm denetleyicinize ekleyip düzenini kendiniz yönetin.
GCKUICastContainerViewController kullanarak sarmalama
İlk yöntem, başka bir görünüm denetleyiciyi sarmalayan ve alt kısma GCKUIMiniMediaControlsViewController ekleyen GCKUICastContainerViewController kullanmaktır. Bu yaklaşım, animasyonu özelleştiremediğiniz ve kapsayıcı görünüm denetleyicisinin davranışını yapılandıramadığınız için sınırlıdır.
Bu ilk yöntem genellikle uygulama temsilcisinin -[application:didFinishLaunchingWithOptions:] yönteminde yapılır:
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
Mevcut görünüm denetleyicisine yerleştirme
İkinci yöntem, mini kumandayı doğrudan mevcut görünüm kumandanıza eklemektir. Bunun için
createMiniMediaControlsViewController
kullanarak bir
GCKUIMiniMediaControlsViewController
örneği oluşturun ve bunu kapsayıcı görünüm kumandasına alt görünüm olarak ekleyin.
Uygulama temsilcisinde görünüm denetleyicinizi ayarlayın:
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; }
Kök görünüm denetleyicinizde bir GCKUIMiniMediaControlsViewController örneği oluşturun ve bunu alt görünüm olarak kapsayıcı görünüm denetleyicisine ekleyin:
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,
ana makine görünüm denetleyicisine mini denetleyicinin ne zaman görünür olması gerektiğini bildirir:
func miniMediaControlsViewController(_: GCKUIMiniMediaControlsViewController, shouldAppear _: Bool) { updateControlBarsVisibility() }
- (void)miniMediaControlsViewController: (GCKUIMiniMediaControlsViewController *)miniMediaControlsViewController shouldAppear:(BOOL)shouldAppear { [self updateControlBarsVisibility]; }
Genişletilmiş kumanda ekleme
Google Cast Tasarım Kontrol Listesi, gönderen uygulamanın, yayınlanan medya için genişletilmiş bir denetleyici sağlamasını gerektirir. Genişletilmiş kumanda, mini kumandanın tam ekran sürümüdür.
Genişletilmiş kumanda, uzaktan medya oynatmanın tam kontrolünü sunan tam ekran bir görünümdür. Bu görünüm, yayınlama uygulamasının, Web Alıcısı ses seviyesi kontrolü ve oturum yaşam döngüsü (yayınlamayı bağlama/durdurma) hariç olmak üzere yayın oturumunun yönetilebilir her yönünü yönetmesine olanak tanımalıdır. Ayrıca medya oturumuyla ilgili tüm durum bilgilerini (poster, başlık, alt yazı vb.) sağlar.
Bu görünümün işlevi, GCKUIExpandedMediaControlsViewController sınıfı tarafından uygulanır.
İlk olarak, yayın bağlamında varsayılan genişletilmiş kumandayı etkinleştirmeniz gerekir. Varsayılan genişletilmiş denetleyiciyi etkinleştirmek için uygulama temsilcisini değiştirin:
func applicationDidFinishLaunching(_ application: UIApplication) { .. GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true ... }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES; .. }
Kullanıcı bir video yayınlamaya başladığında genişletilmiş kumandayı yüklemek için görünüm denetleyicinize aşağıdaki kodu ekleyin:
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]; }
Kullanıcı mini kumandaya dokunduğunda genişletilmiş kumanda da otomatik olarak başlatılır.
Gönderen uygulamanız bir video veya ses canlı yayını oynatırken SDK, genişletilmiş kumandadaki oynat/duraklat düğmesinin yerine otomatik olarak bir oynat/durdur düğmesi gösterir.
Gönderen uygulamanızın, Cast widget'larının görünümünü nasıl yapılandırabileceğini öğrenmek için iOS Uygulamanıza Özel Stiller Uygulama başlıklı makaleyi inceleyin.
Ses düzeyi kontrolü
Yayın çerçevesi, gönderen uygulamanın ses seviyesini otomatik olarak yönetir. Çerçeve, sağlanan kullanıcı arayüzü widget'ları için Web Alıcısı ses seviyesiyle otomatik olarak senkronize edilir. Uygulama tarafından sağlanan bir kaydırma çubuğunu senkronize etmek için GCKUIDeviceVolumeController simgesini kullanın.
Fiziksel düğmeyle ses seviyesi kontrolü
Gönderen cihazdaki fiziksel ses düğmeleri, GCKCastContext üzerinde ayarlanan GCKCastOptions üzerindeki physicalVolumeButtonsWillControlDeviceVolume işaretini kullanarak Web Alıcısı'ndaki yayın oturumunun ses seviyesini değiştirmek için kullanılabilir.
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];
Hataları işleme
Gönderen uygulamaların tüm hata geri çağırmalarını işlemesi ve Cast yaşam döngüsünün her aşaması için en iyi yanıtı belirlemesi çok önemlidir. Uygulama, kullanıcıya hata iletişim kutuları gösterebilir veya Cast oturumunu sonlandırmaya karar verebilir.
GCKErrorCode
GCKErrorCodeCancelled dahil olmak üzere bazı hataların beklenen davranış olduğunu unutmayın.
GCKErrorCodeCancelled ile başarısız olan bir bağlantıyı yeniden denemeyin.
Aksi takdirde beklenmedik davranışlarla karşılaşabilirsiniz.
Günlük Kaydı
GCKLogger,
çerçeve tarafından günlük kaydı için kullanılan bir tekildir. Günlük mesajlarını nasıl işleyeceğinizi özelleştirmek için
GCKLoggerDelegate
kullanın.
SDK, GCKLogger kullanarak hata ayıklama mesajları, hatalar ve uyarılar şeklinde günlük çıkışı oluşturur. Bu günlük mesajları, hata ayıklamaya yardımcı olur ve sorun giderme ile sorunları belirleme konusunda faydalıdır. Varsayılan olarak günlük çıkışı engellenir ancak gönderen uygulama, bir GCKLoggerDelegate atayarak bu mesajları SDK'dan alabilir ve sistem konsoluna kaydedebilir.
@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
Hata ayıklama ve ayrıntılı mesajları da etkinleştirmek için temsilciyi ayarladıktan sonra (önceki adımlarda gösterilmiştir) koda şu satırı ekleyin:
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 tarafından oluşturulan günlük mesajlarını da filtreleyebilirsiniz.
Sınıf başına minimum günlük kaydı düzeyini ayarlayın. Örneğin:
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;
Sınıf adları, tam adlar veya glob kalıpları olabilir (ör. GCKUI\* ve GCK\*Session).