Cast'i iOS Uygulamanıza Entegre Edin

Bu geliştirici kılavuzunda, iOS Sender SDK'sını kullanarak iOS gönderen uygulamanıza Google Cast desteğini nasıl ekleyeceğiniz 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ığı ikilisi ve ilişkili kaynakları ifade eder. Gönderen uygulaması veya Yayın uygulaması, gönderende de çalışan bir uygulamayı ifade eder. Web alıcı uygulaması, Web alıcıda çalışan HTML uygulamasını ifade eder.

Gönderen çerçevesi, gönderen uygulamasını etkinlikler hakkında bilgilendirmek ve Cast uygulamasının yaşam döngüsünün çeşitli durumları arasında geçiş yapmak için eşzamansız 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 GCKDiscoveryManager içinde GCKCastOptions ile sağlanan özelliklere göre başlatılır.
  • Kullanıcı Yayınla düğmesini tıkladığında çerçeve, bulunan 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 Receiver uygulamasının başlatıldığını onaylamak için gönderen uygulamadaki geri çağırma işlevlerini çağırır.
  • Çerçeve, gönderen ve Web Receiver 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, gönderen ile Web Alıcı arasındaki medya oynatma durumunu senkronize eder: Kullanıcı, gönderen kullanıcı arayüzünde işlemler yaptığında çerçeve, bu medya kontrol isteklerini Web Alıcı'ya iletir. Web Alıcı, medya durumu güncellemeleri gönderdiğinde ise ç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ınla düğmesini tıkladığında çerçeve, gönderen uygulamanın Web Alıcı ile bağlantısını keser.

Göndericinizle ilgili sorunları gidermek için günlüğü 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çevedeki tüm etkinlikleri koordine eden GCKCastContext adlı genel tekil nesne bulunur. 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. Böylece, gönderen uygulamanın yeniden başlatılmasıyla otomatik oturum devam ettirme işlemi düzgün şekilde tetiklenebilir.

GCKCastContext başlatılırken bir GCKCastOptions nesnesi sağlanmalıdır. Bu sınıf, çerçevenin davranışını etkileyen seçenekleri içerir. Bunlardan en önemlisi, keşif sonuçlarını filtrelemek ve Cast oturumu başlatıldığında Web Receiver uygulamasını başlatmak için kullanılan Web Receiver uygulama kimliğidir.

-[application:didFinishLaunchingWithOptions:] yöntemi, çerçeveden gelen günlük kaydı mesajlarını almak için bir günlük kaydı temsilcisi ayarlamak üzere de kullanılabilir. Bu bilgiler, hata ayıklama ve sorun giderme açısından yararlı olabilir.

Swift
@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)
    }
  }
}
Objective-C

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

Yayın kullanıcı deneyimi widget'ları

Cast iOS SDK'sı, Cast Tasarım Kontrol Listesi'ne uygun aşağıdaki widget'ları sağlar:

  • Tanıtım Yerleşimi: GCKCastContext sınıfında, Web Alıcısı ilk kez kullanıma sunulduğunda Cast düğmesini öne çıkarmak için kullanılabilecek bir yöntem (presentCastInstructionsViewControllerOnceWithCastButton) bulunur. Gönderen uygulama, metni, başlık metninin konumunu ve Kapat düğmesini özelleştirebilir.

  • Yayınla düğmesi: Yayınla 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 Cast düğmesine ilk kez dokunduğunda, uygulamaya ağdaki cihazlara yerel ağ erişimi izni verebilmesi için bir izin iletişim kutusu gösterilir. Ardından, kullanıcı yayınla düğmesine dokunduğunda keşfedilen cihazların listelendiği bir yayın iletişim kutusu gösterilir. Kullanıcı, cihaz bağlıyken 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ın düğmesine dokunduğunda cihazların neden bulunamadığı ve sorun giderme hakkında bilgi veren bir ekran gösterilir.

  • Mini denetleyici: Kullanıcı içerik yayınlarken ve mevcut içerik sayfasından veya genişletilmiş denetleyiciden gönderen uygulamasındaki başka bir ekrana giderken, mini denetleyici ekranın alt kısmında gösterilir. Bu sayede kullanıcı, şu anda yayınlanan medya meta verilerini görebilir ve oynatmayı kontrol edebilir.

  • Genişletilmiş Denetleyici: Kullanıcı içerik yayınlarken medya bildirimini veya mini denetleyiciyi tıkladığında, genişletilmiş denetleyici başlatılır. Bu denetleyicide, oynatılan medyanın meta verileri gösterilir ve medya oynatmayı kontrol etmek için çeşitli düğmeler bulunur.

Yayın düğmesi ekleme

Çerçeve, UIButton alt sınıfı olarak bir Cast düğmesi bileşeni sağlar. UIBarButtonItem içine alınarak uygulamanın başlık çubuğuna eklenebilir. Tipik bir UIViewController alt sınıfı, Cast düğmesini aşağıdaki gibi yükleyebilir:

Swift
let castButton = GCKUICastButton(frame: CGRect(x: 0, y: 0, width: 24, height: 24))
castButton.tintColor = UIColor.gray
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)
Objective-C
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 dokunduğunuzda çerçeve tarafından sağlanan yayın iletişim kutusu açılır.

GCKUICastButton doğrudan storyboard'a da eklenebilir.

Cihaz bulmayı yapılandırma

Çerçevede cihaz keşfi otomatik olarak gerçekleşir. Özel bir kullanıcı arayüzü uygulamadığınız sürece bulma sürecini açıkça başlatmanız veya durdurmanız gerekmez.

Çerçevedeki keşif, GCKDiscoveryManager sınıfı tarafından yönetilir. Bu sınıf, GCKCastContext öğesinin bir özelliğidir. Ç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 sözlük sırasına göre sıralanır.

Oturum yönetiminin işleyiş şekli

Cast SDK, Cast oturumu kavramını sunar. Bu oturumun oluşturulması, bir cihaza bağlanma, Web Alıcı uygulamasını başlatma (veya uygulamaya katılma), bu uygulamaya bağlanma ve medya kontrol kanalını başlatma adımlarını birleştirir. Cast oturumları ve Web Alıcı yaşam döngüsü hakkında daha fazla bilgi için Web Alıcı Uygulama yaşam döngüsü kılavuzu'na bakın.

Oturumlar, GCKSessionManager sınıfı tarafından yönetilir. Bu sınıf, GCKCastContext mülküdür. Ayrı 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. Şu anda etkin olan Cast oturumuna (varsa) GCKSessionManager mülkünün currentCastSession olarak erişebilirsiniz.

GCKSessionManagerListener<0xx0A>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 oturum etkin durumdayken uygulama anormal/ani bir şekilde sonlandırıldıktan sonra yeniden başlatıldığında) oturumları devam ettirmeye çalışır.

Yayın iletişim kutusu kullanılıyorsa oturumlar, kullanıcı hareketlerine yanıt olarak otomatik olarak oluşturulur ve kapatılır. Aksi takdirde uygulama, GCKSessionManager üzerindeki yöntemlerle 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ı, oturum sonu gibi etkinlikler için geri çağırmaları tanımlayan bir protokoldür.

Akış aktarma

Oturum durumunu koruma, akış aktarımının temelini oluşturur. Bu özellik sayesinde kullanıcılar, sesli komutları, Google Home uygulaması veya akıllı ekranları kullanarak mevcut ses ve video akışlarını cihazlar arasında taşıyabilir. Medya, bir cihazda (kaynak) oynatmayı durdurur ve başka bir cihazda (hedef) oynatmaya devam eder. En yeni donanım yazılımına sahip tüm Cast cihazlar, akış aktarımında kaynak veya hedef olarak kullanılabilir.

Akış aktarımı 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ış aktarımı başlıklı makaleyi inceleyin.

Otomatik yeniden bağlanma

Cast çerçevesi, yeniden bağlantı mantığı ekleyerek yeniden bağlantıyı otomatik olarak işler. Bu mantık, aşağıdakiler gibi birçok ince uç durumda geçerlidir:

  • Geçici Wi-Fi kaybından kurtulma
  • Cihaz uyku modundan kurtarma
  • Uygulamayı arka plana aldıktan sonra kurtarma
  • Uygulama kilitlendiyse kurtarma

Medya denetiminin işleyiş şekli

Medya ad alanını destekleyen bir Web Alıcı uygulamasıyla Cast oturumu oluşturulursa çerçeve tarafından otomatik olarak GCKRemoteMediaClient örneği oluşturulur. Bu örneğe, GCKCastSession örneğinin remoteMediaClient özelliği olarak erişilebilir.

Web alıcısına istek gönderen tüm yöntemler GCKRemoteMediaClient, 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. Nitekim, Cast iletişim kutusu ve mini medya kontrolleri gibi bazı dahili çerçeve bileşenleri de örneği paylaşır. Bu amaçla, GCKRemoteMediaClient birden fazla GCKRemoteMediaClientListener'nın kaydedilmesini destekler.

Medya meta verilerini ayarlama

GCKMediaMetadata sınıfı, yayınlamak istediğiniz bir medya öğesiyle ilgili bilgileri temsil eder. Aşağıdaki örnekte, yeni bir GCKMediaMetadata film örneği oluşturuluyor ve başlık, altyazı, kayıt stüdyosunun adı ve iki resim ayarlanıyor.

Swift
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))
Objective-C
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.

Medya yükleme

Bir medya öğesini yüklemek için medyanın meta verilerini kullanarak bir GCKMediaInformation örneği oluşturun. Ardından, alıcı uygulamasında medyayı yüklemek için geçerli GCKCastSession öğesini alın ve GCKRemoteMediaClient öğesini kullanın. Daha sonra, alıcıda çalışan bir medya oynatıcı uygulamasını kontrol etmek için GCKRemoteMediaClient öğesini kullanabilirsiniz (ör. oynatma, duraklatma ve durdurma).

Swift
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
}
Objective-C
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;
}

Ayrıca medya parçalarını kullanma bölümüne de bakın.

4K video biçimi

Medyanızın hangi video biçiminde olduğunu belirlemek için GCKMediaStatus öğesinin videoInfo özelliğini kullanarak GCKVideoInfo öğesinin mevcut örneğini alın. Bu örnekte, HDR TV biçiminin türü ve piksel cinsinden yükseklik ve genişlik değerleri yer alır. 4K biçiminin varyantları, hdrType özelliğinde enum değerleri GCKVideoInfoHDRType ile belirtilir.

Mini kontrol cihazları ekleme

Cast Tasarım Kontrol Listesi'ne göre, gönderen uygulaması, kullanıcının mevcut içerik sayfasından ayrıldığında görünmesi gereken mini denetleyici olarak bilinen kalıcı bir denetim sağlamalıdır. Mini denetleyici, mevcut Cast oturumuna anında erişim ve görünür bir hatırlatıcı sağlar.

Cast çerçevesi, mini denetleyiciyi göstermek istediğiniz sahneler eklenebilen bir kontrol çubuğu, GCKUIMiniMediaControlsViewController, sağlar.

Gönderen uygulamanız bir video veya ses canlı yayını oynatırken SDK, mini oynatıcıdaki oynat/duraklat düğmesi 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ği hakkında bilgi edinmek için iOS Gönderen Kullanıcı Arayüzünü Özelleştirme başlıklı makaleye bakın.

Mini denetleyiciyi gönderen uygulamaya eklemenin iki yolu vardır:

  • Mevcut görünüm denetleyicinizi kendi görünüm denetleyicisiyle sarmalayarak mini denetleyicinin düzenini Cast çerçevesinin yönetmesine izin verin.
  • Storyboard'da bir alt görünüm sağlayarak mini kontrolcü widget'ını mevcut görünüm kontrolcünüze ekleyip düzenini kendiniz yönetin.

GCKUICastContainerViewController ile sarmalama

İlk yöntem, başka bir görünüm denetleyicisini sarmalayan ve alta bir GCKUICastContainerViewController ekleyen GCKUICastContainerViewController kullanmaktır.GCKUIMiniMediaControlsViewController Bu yaklaşım, animasyonu özelleştirememeniz ve kapsayıcı görünüm denetleyicisinin davranışını yapılandıramamanız nedeniyle sınırlıdır.

Bu ilk yöntem genellikle uygulama temsilcisinin -[application:didFinishLaunchingWithOptions:] yönteminde yapılır:

Swift
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()

  ...
}
Objective-C
- (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];
  ...

}
Swift
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
    }
  }
}
Objective-C

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, createMiniMediaControlsViewController kullanarak mini denetleyiciyi doğrudan mevcut görünüm denetleyicinize eklemektir. Bu yöntemle GCKUIMiniMediaControlsViewController örneği oluşturup bunu alt görünüm olarak kapsayıcı görünüm denetleyicisine ekleyebilirsiniz.

Görünüm denetleyicinizi uygulama temsilcisinde ayarlayın:

Swift
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
}
Objective-C
- (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:

Swift
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)
    }
  }

...
Objective-C

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, mini denetleyicinin ne zaman görünür olması gerektiğini ana görünüm denetleyicisine bildirir:

Swift
  func miniMediaControlsViewController(_: GCKUIMiniMediaControlsViewController,
                                       shouldAppear _: Bool) {
    updateControlBarsVisibility()
  }
Objective-C
- (void)miniMediaControlsViewController:
            (GCKUIMiniMediaControlsViewController *)miniMediaControlsViewController
                           shouldAppear:(BOOL)shouldAppear {
  [self updateControlBarsVisibility];
}

Genişletilmiş denetleyici ekleme

Google Cast Tasarım Kontrol Listesi, gönderen uygulamanın yayınlanan medya için genişletilmiş denetleyici sağlamasını zorunlu kılar. Genişletilmiş denetleyici, mini denetleyicinin tam ekran sürümüdür.

Genişletilmiş denetleyici, uzaktan medya oynatma üzerinde tam kontrol sağlayan tam ekran görünümüdür. Bu görünüm, Web Receiver ses kontrolü ve oturum yaşam döngüsü (yayınlama/yayınlamayı durdurma) hariç olmak üzere, yayın oturumunun yönetilebilir her yönünü bir yayınlama uygulamasının yönetmesine olanak tanımalıdır. Ayrıca, medya oturumuyla ilgili tüm durum bilgilerini (sanat eseri, başlık, altyazı vb.) sağlar.

Bu görünümün işlevselliği GCKUIExpandedMediaControlsViewController sınıfı tarafından uygulanır.

Yapmanız gereken ilk şey, yayın bağlamında varsayılan genişletilmiş denetleyiciyi etkinleştirmektir. Varsayılan genişletilmiş denetleyiciyi etkinleştirmek için uygulama temsilcisini değiştirin:

Swift
func applicationDidFinishLaunching(_ application: UIApplication) {
  ..

  GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true

  ...
}
Objective-C
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  ...

  [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES;

  ..
}

Kullanıcı video yayınlamaya başladığında genişletilmiş denetleyiciyi yüklemek için görünüm denetleyicinize aşağıdaki kodu ekleyin:

Swift
func playSelectedItemRemotely() {
  GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls()

  ...

  // Load your media
  sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInformation)
}
Objective-C
- (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ş kontrol panelinde oynat/duraklat düğmesi yerine otomatik olarak oynat/durdur düğmesini 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ü

Cast çerçevesi, gönderen uygulamasının sesini otomatik olarak yönetir. Çerçeve, sağlanan kullanıcı arayüzü widget'ları için Web Alıcı'nın sesiyle otomatik olarak senkronize edilir. Uygulama tarafından sağlanan bir kaydırma çubuğunu senkronize etmek için GCKUIDeviceVolumeController kullanın.

Fiziksel düğmeyle ses kontrolü

Gönderen cihazdaki fiziksel ses düğmeleri, GCKCastContext üzerinde ayarlanan GCKCastOptions üzerindeki physicalVolumeButtonsWillControlDeviceVolume işareti kullanılarak Web Alıcı'daki Cast oturumunun sesini değiştirmek için kullanılabilir.

Swift
let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID)
let options = GCKCastOptions(discoveryCriteria: criteria)
options.physicalVolumeButtonsWillControlDeviceVolume = true
GCKCastContext.setSharedInstanceWith(options)
Objective-C
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 aramaları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.

Günlük Kaydı

GCKLogger, çerçeve tarafından günlüğe kaydetme için kullanılan tekil bir öğedir. Günlük mesajlarını nasıl işleyeceğinizi özelleştirmek için GCKLoggerDelegate simgesini kullanın.

SDK, GCKLogger kullanılarak hata ayıklama mesajları, hatalar ve uyarılar şeklinde günlük kaydı çıktısı oluşturur. Bu günlük mesajları hata ayıklamaya yardımcı olur ve sorun giderme ile sorunları belirleme açısından faydalıdır. Günlük çıkışı varsayılan olarak bastırılır ancak GCKLoggerDelegate atanarak gönderen uygulama, bu mesajları SDK'dan alıp sistem konsoluna kaydedebilir.

Swift
@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)
    }
  }
}
Objective-C

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 temsilci ayarlandıktan sonra (daha önce gösterilmişti) koda şu satırı ekleyin:

Swift
let filter = GCKLoggerFilter.init()
filter.minimumLevel = GCKLoggerLevel.verbose
GCKLogger.sharedInstance().filter = filter
Objective-C
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init];
[filter setMinimumLevel:GCKLoggerLevelVerbose];
[GCKLogger sharedInstance].filter = filter;

Ayrıca, 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:

Swift
let filter = GCKLoggerFilter.init()
filter.setLoggingLevel(GCKLoggerLevel.verbose, forClasses: ["GCKUICastButton",
                                                            "GCKUIImageCache",
                                                            "NSMutableDictionary"])
GCKLogger.sharedInstance().filter = filter
Objective-C
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init];
[filter setLoggingLevel:GCKLoggerLevelVerbose
             forClasses:@[@"GCKUICastButton",
                          @"GCKUIImageCache",
                          @"NSMutableDictionary"
                          ]];
[GCKLogger sharedInstance].filter = filter;

Sınıf adları, değişmez adlar veya glob desenleri olabilir. Örneğin, GCKUI\* ve GCK\*Session.