iOS uygulamasında yayınlama özelliğini etkinleştirme

1. Genel bakış

Google Cast logosu

Bu codelab'de, Google Cast uyumlu bir cihazda içerik yayınlamak için mevcut bir iOS video uygulamasını nasıl değiştireceğinizi öğreneceksiniz.

Google Cast nedir?

Google Cast, kullanıcıların bir mobil cihazdan TV'ye içerik yayınlamasına olanak tanır. Kullanıcılar daha sonra mobil cihazlarını TV'de medya oynatmak için uzaktan kumanda olarak kullanabilir.

Google Cast SDK'sı, uygulamanızı Google Cast uyumlu cihazları (ör. TV veya ses sistemi) kontrol edecek şekilde genişletmenize olanak tanır. Cast SDK'sı, Google Cast Tasarım Kontrol Listesi'ne göre gerekli kullanıcı arayüzü bileşenlerini eklemenize olanak tanır.

Google Cast Tasarım Kontrol Listesi, desteklenen tüm platformlarda Cast kullanıcı deneyimini basit ve tahmin edilebilir hale getirmek için sağlanmıştır.

Neyi inşa edeceğiz?

Bu codelab'i tamamladığınızda videoları Google Cast cihazına yayınlayabilecek bir iOS video uygulamanız olacaktır.

Neler öğreneceksiniz?

  • Örnek bir video uygulamasına Google Cast SDK'sı nasıl eklenir?
  • Google Cast cihazı seçmek için Yayın düğmesi nasıl eklenir?
  • Yayın cihazına bağlanıp medya alıcısı nasıl başlatılır?
  • Video nasıl yayınlanır?
  • Uygulamanıza Cast mini kumanda ekleme.
  • Genişletilmiş kumanda nasıl eklenir?
  • Tanıtım amaçlı yer paylaşımı nasıl sağlanır?
  • Yayın widget'ları nasıl özelleştirilir?
  • Cast Connect nasıl entegre edilir?

Gerekenler

  • En son Xcode.
  • iOS 9 veya üzeri (veya Xcode Simülatörü) yüklü bir mobil cihaz.
  • Mobil cihazınızı geliştirme bilgisayarınıza (cihaz kullanıyorsanız) bağlamak için bir USB veri kablosu.
  • İnternet erişimi olan, Chromecast veya Android TV gibi bir Google Cast cihazı.
  • HDMI girişi olan bir TV veya monitör.
  • Cast Connect entegrasyonunu test etmek için Google TV Yüklü Chromecast gereklidir, ancak Codelab'in geri kalanı için isteğe bağlıdır. Destek kaydınız yoksa bu eğiticinin sonuna doğru olan Cast Connect Desteği Ekleme adımını atlayabilirsiniz.

Deneyim

  • iOS geliştirmeyle ilgili önceden bilgi sahibi olmanız gerekir.
  • Ayrıca TV izleme konusunda da önceden bilgi sahibi olmanız gerekir :)

Bu eğiticiyi nasıl kullanacaksınız?

Yalnızca okuma Okuyun ve alıştırmaları tamamlayın

iOS uygulamaları oluşturma deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Düzey Yeterli

TV izleme deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Düzey Yeterli

2. Örnek kodu alın

Örnek kodun tamamını bilgisayarınıza indirebilirsiniz...

indirilen zip dosyasını açın.

3. Örnek uygulamayı çalıştırma

Apple iOS logosu

Önce tamamlanmış örnek uygulamanın nasıl göründüğüne bakalım. Uygulama, temel bir video oynatıcıdır. Kullanıcı, listeden bir video seçebilir ve videoyu cihazda yerel olarak oynatabilir veya bir Google Cast cihazına yayınlayabilir.

Kod indirildikten sonra aşağıdaki talimatlarda, tamamlanmış örnek uygulamanın Xcode'da nasıl açılacağı ve çalıştırılacağı açıklanmaktadır:

Sık sorulan sorular

CocoaPods kurulumu

CocoaPods'u kurmak için konsolunuza gidin ve macOS'te bulunan varsayılan Ruby'yi kullanarak yükleyin:

sudo gem install cocoapods

Sorun yaşarsanız bağımlılık yöneticisini indirip yüklemek için resmi belgelere bakın.

Proje ayarlama

  1. Terminalinize ve codelab dizinine gidin.
  2. Podfile'dan bağımlılıkları yükleyin.
cd app-done
pod update
pod install
  1. Xcode'u açın ve Başka bir proje aç...'ı seçin.
  2. Örnek kod klasöründeki klasör simgesiapp-done dizininden CastVideos-ios.xcworkspace dosyasını seçin.

Uygulamayı çalıştırma

Hedefi ve simülatörü seçip uygulamayı çalıştırın:

XCode uygulama simülatörü araç çubuğu

Video uygulamasının birkaç saniye sonra görünmesi gerekir.

Gelen ağ bağlantılarını kabul etme ile ilgili bir bildirim göründüğünde "İzin ver"i tıkladığınızdan emin olun. Bu seçenek kabul edilmezse Yayınla simgesi görünmez.

Gelen ağ bağlantılarını kabul etmek için izin isteyen onay iletişim kutusu

Yayınla düğmesini tıklayın ve Google Cast cihazınızı seçin.

Bir video seçip oynat düğmesini tıklayın.

Video, Google Cast cihazınızda oynatılmaya başlar.

Genişletilmiş kumanda gösterilir. Oynatmayı kontrol etmek için oynat/duraklat düğmesini kullanabilirsiniz.

Video listesine geri dönün.

Ekranın alt kısmında artık bir mini kumanda görünüyor.

Alt tarafta mini kumandanın göründüğü, CastVideos uygulamasını çalıştıran bir iPhone görseli

Videoyu alıcıda duraklatmak için mini kumandadaki duraklat düğmesini tıklayın. Videoyu tekrar oynatmaya devam etmek için mini kumandadaki oynat düğmesini tıklayın.

Google Cast cihazına yayını durdurmak için Yayınla düğmesini tıklayın.

4. Başlangıç projesini hazırlama

CastVideos uygulamasını çalıştıran bir iPhone görseli

İndirdiğiniz başlangıç uygulamasına Google Cast desteği eklememiz gerekiyor. Bu codelab'de kullanacağımız bazı Google Cast terminolojisi şöyledir:

  • Mobil cihazda veya dizüstü bilgisayarda çalışan bir gönderen uygulaması ise
  • Google Cast cihazında bir alıcı uygulaması çalışır.

Proje ayarlama

Artık Xcode'u kullanarak başlangıç projesinin temeli oluşturmaya hazırsınız:

  1. Terminalinize ve codelab dizinine gidin.
  2. Podfile'dan bağımlılıkları yükleyin.
cd app-start
pod update
pod install
  1. Xcode'u açın ve Başka bir proje aç...'ı seçin.
  2. Örnek kod klasöründeki klasör simgesiapp-start dizininden CastVideos-ios.xcworkspace dosyasını seçin.

Uygulama tasarımı

Uygulama, uzak bir web sunucusundan video listesi getirir ve kullanıcının göz atabileceği bir liste sağlar. Kullanıcılar bir video seçerek ayrıntılarını görebilir veya videoyu mobil cihazlarında yerel olarak oynatabilir.

Uygulama iki ana görünüm denetleyicisinden oluşur: MediaTableViewController ve MediaViewController.

MediaTableViewController

Bu UITableViewController, bir MediaListModel örneğine ait videoların listesini gösterir. Videoların listesi ve ilişkili meta verileri, JSON dosyası olarak uzak bir sunucuda barındırılır. MediaListModel, bu JSON'u getirir ve MediaItem nesnelerinin listesini oluşturmak için işler.

MediaItem nesnesi, bir videoyu ve video başlığı, açıklaması, resmin URL'si ve akışın URL'si gibi ilişkili meta verilerini modeller.

MediaTableViewController önce bir MediaListModel örneği oluşturur, ardından medya meta verileri indirildiğinde tablo görünümünü yükleyebilmesi için bilgi almak üzere kendisini bir MediaListModelDelegate olarak kaydeder.

Kullanıcıya, her videonun kısa bir açıklamasını içeren video küçük resimlerinden oluşan bir liste sunulur. Bir öğe seçildiğinde, karşılık gelen MediaItem MediaViewController öğesine iletilir.

MediaViewController

Bu görüntüleme denetleyicisi, belirli bir video hakkındaki meta verileri görüntüler ve kullanıcının mobil cihazda videoyu yerel olarak oynatmasına olanak tanır.

Görüntüleme denetleyicisi bir LocalPlayerView, bazı medya denetimleri ve seçilen videonun açıklamasını gösteren bir metin alanı barındırır. Oynatıcı ekranın üst kısmını kaplar ve videonun altında bulunan ayrıntılı açıklama için yer bırakır. Kullanıcı, yerel videoyu oynatabilir/duraklatabilir veya oynatabilir.

Sık sorulan sorular

5. Yayınla düğmesi ekleniyor

CastVideos uygulamasını çalıştıran bir iPhone'un üstteki üçte birlik kısmının sağ üst köşesinde Yayın düğmesinin gösterildiği görsel

Cast uyumlu bir uygulamanın görünüm denetleyicilerinin her birinde Yayın düğmesi görüntülenir. Yayınla düğmesi tıklandığında, kullanıcının seçebileceği Yayın cihazlarının listesi görüntülenir. Kullanıcı, içeriği gönderen cihazda yerel olarak oynatıyorsa, bir yayın cihazı seçildiğinde ilgili yayın cihazında oynatma başlatılır veya devam ettirilir. Yayınlama oturumu sırasında istediği zaman kullanıcı Yayınla düğmesini tıklayabilir ve uygulamanızın Yayın cihazına yayınlanmasını durdurabilir. Kullanıcı, Google Cast Tasarım Kontrol Listesi'nde açıklandığı gibi, uygulamanızın herhangi bir ekranındayken Cast cihazına bağlanabilmeli veya cihaz bağlantısı kesebilmelidir.

Yapılandırma

Start projesi, tamamlanan örnek uygulama için yaptığınızla aynı bağımlılıkları ve Xcode kurulumunu gerektirir. İlgili bölüme dönün ve GoogleCast.framework öğesini başlangıç projesi projesine eklemek için aynı adımları uygulayın.

Başlatma

Cast çerçevesi, çerçevenin tüm etkinliklerini koordine eden genel bir tekil nesneye (GCKCastContext) sahiptir. Gönderen uygulamanın yeniden başlatılmasında otomatik oturum devam ettirmenin düzgün şekilde tetiklenebilmesi ve cihaz taraması başlatılabilmesi için, bu nesnenin uygulamanın yaşam döngüsünün başlarında (genellikle uygulama temsilcisinin application(_:didFinishLaunchingWithOptions:) yönteminde) başlatılması gerekir.

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, yayın cihazının keşif sonuçlarını filtrelemek ve bir yayın oturumu başlatıldığında alıcı uygulamayı başlatmak için kullanılan alıcı uygulama kimliğidir.

application(_:didFinishLaunchingWithOptions:) yöntemi, Cast çerçevesinden günlük kaydı mesajlarını almak üzere günlük kaydı temsilcisi ayarlamak için de iyi bir yerdir. Bunlar hata ayıklama ve sorun giderme için yararlı olabilir.

Cast uyumlu kendi uygulamanızı geliştirdiğinizde, Cast geliştiricisi olarak kaydolmanız ve ardından uygulamanız için bir uygulama kimliği almanız gerekir. Bu codelab için örnek bir uygulama kimliği kullanacağız.

GCKCastContext uygulamasını, kullanıcı varsayılanlarındaki uygulama kimliğiyle başlatmak için AppDelegate.swift alanına aşağıdaki kodu, Google Cast çerçevesine de bir günlük kaydedici ekleyin:

import GoogleCast

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  fileprivate var enableSDKLogging = true

  ...

  func application(_: UIApplication,
                   didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    ...
    let options = GCKCastOptions(discoveryCriteria: GCKDiscoveryCriteria(applicationID: kReceiverAppID))
    options.physicalVolumeButtonsWillControlDeviceVolume = true
    GCKCastContext.setSharedInstanceWith(options)

    window?.clipsToBounds = true
    setupCastLogging()
    ...
  }
  ...
  func setupCastLogging() {
    let logFilter = GCKLoggerFilter()
    let classesToLog = ["GCKDeviceScanner", "GCKDeviceProvider", "GCKDiscoveryManager", "GCKCastChannel",
                        "GCKMediaControlChannel", "GCKUICastButton", "GCKUIMediaController", "NSMutableDictionary"]
    logFilter.setLoggingLevel(.verbose, forClasses: classesToLog)
    GCKLogger.sharedInstance().filter = logFilter
    GCKLogger.sharedInstance().delegate = self
  }
}

...

// MARK: - GCKLoggerDelegate

extension AppDelegate: GCKLoggerDelegate {
  func logMessage(_ message: String,
                  at _: GCKLoggerLevel,
                  fromFunction function: String,
                  location: String) {
    if enableSDKLogging {
      // Send SDK's log messages directly to the console.
      print("\(location): \(function) - \(message)")
    }
  }
}

Yayınla düğmesi

GCKCastContext başlatıldığına göre kullanıcının yayın cihazı seçebilmesi için Yayınla düğmesini eklememiz gerekir. Cast SDK'sı, UIButton alt sınıfı olarak GCKUICastButton adlı bir Yayın düğmesi bileşeni sağlar. UIBarButtonItem içinde sarmalanarak uygulamanın başlık çubuğuna eklenebilir. Yayınla düğmesini hem MediaTableViewController hem de MediaViewController içine eklememiz gerekiyor.

MediaTableViewController.swift ve MediaViewController.swift için şu kodu ekleyin:

import GoogleCast

@objc(MediaTableViewController)
class MediaTableViewController: UITableViewController, GCKSessionManagerListener,
  MediaListModelDelegate, GCKRequestDelegate {
  private var castButton: GCKUICastButton!
  ...
  override func viewDidLoad() {
    print("MediaTableViewController - viewDidLoad")
    super.viewDidLoad()

    ...
    castButton = GCKUICastButton(frame: CGRect(x: CGFloat(0), y: CGFloat(0),
                                               width: CGFloat(24), height: CGFloat(24)))
    // Overwrite the UIAppearance theme in the AppDelegate.
    castButton.tintColor = UIColor.white
    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)

    ...
  }
  ...
}

Sonra, aşağıdaki kodu MediaViewController.swift cihazınıza ekleyin:

import GoogleCast

@objc(MediaViewController)
class MediaViewController: UIViewController, GCKSessionManagerListener, GCKRemoteMediaClientListener,
  LocalPlayerViewDelegate, GCKRequestDelegate {
  private var castButton: GCKUICastButton!
  ...
  override func viewDidLoad() {
    super.viewDidLoad()
    print("in MediaViewController viewDidLoad")
    ...
    castButton = GCKUICastButton(frame: CGRect(x: CGFloat(0), y: CGFloat(0),
                                               width: CGFloat(24), height: CGFloat(24)))
    // Overwrite the UIAppearance theme in the AppDelegate.
    castButton.tintColor = UIColor.white
    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)

    ...
  }
  ...
}

Şimdi uygulamayı çalıştırın. Uygulamanın gezinme çubuğunda bir Yayınla düğmesi görürsünüz. Bu düğmeyi tıkladığınızda yerel ağınızdaki yayın cihazları listelenir. Cihaz keşfi GCKCastContext tarafından otomatik olarak yönetilir. Yayın cihazınızı seçin. Yayın cihazına örnek alıcı uygulaması yüklenir. Göz atma etkinliği ile yerel oynatıcı etkinliği arasında gezinebilirsiniz. Yayın düğmesinin durumu senkronize edilir.

Medya oynatma desteği almadığımızdan henüz yayın cihazında video oynatamıyorsunuz. Yayını durdurmak için Yayınla düğmesini tıklayın.

6. Video içeriği yayınlanıyor

CastVideos uygulamasını çalıştıran bir iPhone'un, belirli bir videoyla ("Tears of Steel") ilgili ayrıntıları gösteren görsel. Altta mini oynatıcı vardır

Örnek uygulamanın kapsamını, videoları bir Cast cihazında uzaktan oynatacak şekilde genişleteceğiz. Bunun için Cast çerçevesi tarafından oluşturulan çeşitli etkinlikleri dinlememiz gerekir.

Medya yayınlanıyor

Yüksek bir düzeyde, bir yayın cihazında medya oynatmak isterseniz aşağıdakilerin gerçekleşmesi gerekir:

  1. Cast SDK'dan bir medya öğesini modelleyen GCKMediaInformation nesnesi oluşturun.
  2. Kullanıcı, alıcı uygulamanızı başlatmak için yayın cihazına bağlanır.
  3. GCKMediaInformation nesnesini alıcınıza yükleyin ve içeriği oynatın.
  4. Medya durumunu izleyin.
  5. Kullanıcı etkileşimlerine bağlı olarak alıcıya oynatma komutları gönderin.

1. adım bir nesneyi diğerine eşleme anlamına gelir. GCKMediaInformation, Cast SDK'nın anladığı bir şeydir ve MediaItem, uygulamamızın bir medya öğesine yönelik kapsülüdür. Bir MediaItem öğesini kolayca bir GCKMediaInformation ile eşleyebiliriz. Önceki bölümde yer alan 2. Adım'ı zaten yapmıştık. 3. adımı Cast SDK ile kolayca yapabilirsiniz.

Örnek uygulama MediaViewController, şu enum'u kullanarak yerel ve uzaktan oynatma arasında zaten ayrım yapmaktadır:

enum PlaybackMode: Int {
  case none = 0
  case local
  case remote
}

private var playbackMode = PlaybackMode.none

Bu codelab'de tüm örnek oynatıcı mantığının tam olarak nasıl çalıştığını anlamanız önemli değildir. Uygulamanızın medya oynatıcısının, iki oynatma konumunu benzer bir şekilde fark etmesi için değiştirilmesi gerektiğini anlamak önemlidir.

Şu anda yerel oynatıcı, Yayınlama durumları hakkında henüz hiçbir şey bilmediğinden her zaman yerel oynatma durumundadır. Kullanıcı arayüzünü, Cast çerçevesinde gerçekleşen durum geçişlerine göre güncellememiz gerekir. Örneğin, yayınlamaya başlarsak yerel oynatmayı durdurmamız ve bazı kontrolleri devre dışı bırakmamız gerekir. Benzer şekilde, bu görünüm denetleyicisindeyken yayını durdurursak yerel oynatmaya geçiş yapmamız gerekir. Bunu halletmek için Cast çerçevesi tarafından oluşturulan çeşitli etkinlikleri dinlememiz gerekir.

Yayın oturumu yönetimi

Yayın çerçevesi için Cast oturumu; cihaza bağlanma, başlatma (veya katılma), alıcı uygulamaya bağlanma ve uygunsa bir medya kontrol kanalını başlatma adımlarını birleştirir. Medya kontrol kanalı, Yayın çerçevesinin alıcı medya oynatıcıdan mesaj gönderip alma yöntemidir.

Yayın oturumu, kullanıcı Yayınla düğmesinden bir cihaz seçtiğinde otomatik olarak başlatılır ve kullanıcı bağlantısı kesildiğinde otomatik olarak durdurulur. Ağ sorunları nedeniyle alıcı oturumuna yeniden bağlanma da Cast çerçevesi tarafından otomatik olarak gerçekleştirilir.

Yayınlama oturumları, GCKCastContext.sharedInstance().sessionManager üzerinden erişilebilen GCKSessionManager tarafından yönetilir. GCKSessionManagerListener geri çağırma işlevleri; oluşturma, askıya alma, devam ettirme ve sonlandırma gibi oturum etkinliklerini izlemek için kullanılabilir.

İlk olarak oturum işleyicimizi kaydetmemiz ve bazı değişkenleri başlatmamız gerekir:

class MediaViewController: UIViewController, GCKSessionManagerListener,
  GCKRemoteMediaClientListener, LocalPlayerViewDelegate, GCKRequestDelegate {

  ...
  private var sessionManager: GCKSessionManager!
  ...

  required init?(coder: NSCoder) {
    super.init(coder: coder)

    sessionManager = GCKCastContext.sharedInstance().sessionManager

    ...
  }

  override func viewWillAppear(_ animated: Bool) {
    ...

    let hasConnectedSession: Bool = (sessionManager.hasConnectedSession())
    if hasConnectedSession, (playbackMode != .remote) {
      populateMediaInfo(false, playPosition: 0)
      switchToRemotePlayback()
    } else if sessionManager.currentSession == nil, (playbackMode != .local) {
      switchToLocalPlayback()
    }

    sessionManager.add(self)

    ...
  }

  override func viewWillDisappear(_ animated: Bool) {
    ...

    sessionManager.remove(self)
    sessionManager.currentCastSession?.remoteMediaClient?.remove(self)
    ...
    super.viewWillDisappear(animated)
  }

  func switchToLocalPlayback() {
    ...

    sessionManager.currentCastSession?.remoteMediaClient?.remove(self)

    ...
  }

  func switchToRemotePlayback() {
    ...

    sessionManager.currentCastSession?.remoteMediaClient?.add(self)

    ...
  }


  // MARK: - GCKSessionManagerListener

  func sessionManager(_: GCKSessionManager, didStart session: GCKSession) {
    print("MediaViewController: sessionManager didStartSession \(session)")
    setQueueButtonVisible(true)
    switchToRemotePlayback()
  }

  func sessionManager(_: GCKSessionManager, didResumeSession session: GCKSession) {
    print("MediaViewController: sessionManager didResumeSession \(session)")
    setQueueButtonVisible(true)
    switchToRemotePlayback()
  }

  func sessionManager(_: GCKSessionManager, didEnd _: GCKSession, withError error: Error?) {
    print("session ended with error: \(String(describing: error))")
    let message = "The Casting session has ended.\n\(String(describing: error))"
    if let window = appDelegate?.window {
      Toast.displayMessage(message, for: 3, in: window)
    }
    setQueueButtonVisible(false)
    switchToLocalPlayback()
  }

  func sessionManager(_: GCKSessionManager, didFailToStartSessionWithError error: Error?) {
    if let error = error {
      showAlert(withTitle: "Failed to start a session", message: error.localizedDescription)
    }
    setQueueButtonVisible(false)
  }

  func sessionManager(_: GCKSessionManager,
                      didFailToResumeSession _: GCKSession, withError _: Error?) {
    if let window = UIApplication.shared.delegate?.window {
      Toast.displayMessage("The Casting session could not be resumed.",
                           for: 3, in: window)
    }
    setQueueButtonVisible(false)
    switchToLocalPlayback()
  }

  ...
}

MediaViewController konumunda, Cast cihazına bağlandığımızda veya yayın bağlantısı kesildiğinde yerel oynatıcıya geçiş yapabilmemiz veya kendisinden geçebilmemiz için bilgi almak isteriz. Bağlantının yalnızca uygulamanızın mobil cihazınızda çalışan örneği nedeniyle kesintiye uğrayabileceğini değil, aynı zamanda uygulamanızın farklı bir mobil cihazda çalışan (ya da başka bir) uygulamanızın başka bir örneği nedeniyle de kesintiye uğrayabileceğini unutmayın.

Şu anda etkin olan oturuma GCKCastContext.sharedInstance().sessionManager.currentCastSession adresinden erişilebilir. Oturumlar, Yayınlama iletişim kutularındaki kullanıcı hareketlerine otomatik olarak oluşturulur ve azaltılır.

Medya yükleniyor

Cast SDK'sında GCKRemoteMediaClient, alıcıdaki uzaktan medya oynatmayı yönetmek için kullanabileceğiniz bir dizi kullanışlı API sağlar. Medya oynatmayı destekleyen bir GCKCastSession için SDK tarafından otomatik olarak GCKRemoteMediaClient örneği oluşturulur. Bu nesneye GCKCastSession örneğinin remoteMediaClient özelliği olarak erişilebilir.

Şu anda seçili olan videoyu alıcıya yüklemek için MediaViewController.swift için aşağıdaki kodu ekleyin:

@objc(MediaViewController)
class MediaViewController: UIViewController, GCKSessionManagerListener,
  GCKRemoteMediaClientListener, LocalPlayerViewDelegate, GCKRequestDelegate {
  ...

  @objc func playSelectedItemRemotely() {
    loadSelectedItem(byAppending: false)
  }

  /**
   * Loads the currently selected item in the current cast media session.
   * @param appending If YES, the item is appended to the current queue if there
   * is one. If NO, or if
   * there is no queue, a new queue containing only the selected item is created.
   */
  func loadSelectedItem(byAppending appending: Bool) {
    print("enqueue item \(String(describing: mediaInfo))")
    if let remoteMediaClient = sessionManager.currentCastSession?.remoteMediaClient {
      let mediaQueueItemBuilder = GCKMediaQueueItemBuilder()
      mediaQueueItemBuilder.mediaInformation = mediaInfo
      mediaQueueItemBuilder.autoplay = true
      mediaQueueItemBuilder.preloadTime = TimeInterval(UserDefaults.standard.integer(forKey: kPrefPreloadTime))
      let mediaQueueItem = mediaQueueItemBuilder.build()
      if appending {
        let request = remoteMediaClient.queueInsert(mediaQueueItem, beforeItemWithID: kGCKMediaQueueInvalidItemID)
        request.delegate = self
      } else {
        let queueDataBuilder = GCKMediaQueueDataBuilder(queueType: .generic)
        queueDataBuilder.items = [mediaQueueItem]
        queueDataBuilder.repeatMode = remoteMediaClient.mediaStatus?.queueRepeatMode ?? .off

        let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
        mediaLoadRequestDataBuilder.mediaInformation = mediaInfo
        mediaLoadRequestDataBuilder.queueData = queueDataBuilder.build()

        let request = remoteMediaClient.loadMedia(with: mediaLoadRequestDataBuilder.build())
        request.delegate = self
      }
    }
  }
  ...
}

Şimdi de uzaktan oynatmayı desteklemek için Yayın Oturumu mantığını kullanmak üzere mevcut çeşitli yöntemleri güncelleyin:

required init?(coder: NSCoder) {
  super.init(coder: coder)
  ...
  castMediaController = GCKUIMediaController()
  ...
}

func switchToLocalPlayback() {
  print("switchToLocalPlayback")
  if playbackMode == .local {
    return
  }
  setQueueButtonVisible(false)
  var playPosition: TimeInterval = 0
  var paused: Bool = false
  var ended: Bool = false
  if playbackMode == .remote {
    playPosition = castMediaController.lastKnownStreamPosition
    paused = (castMediaController.lastKnownPlayerState == .paused)
    ended = (castMediaController.lastKnownPlayerState == .idle)
    print("last player state: \(castMediaController.lastKnownPlayerState), ended: \(ended)")
  }
  populateMediaInfo((!paused && !ended), playPosition: playPosition)
  sessionManager.currentCastSession?.remoteMediaClient?.remove(self)
  playbackMode = .local
}

func switchToRemotePlayback() {
  print("switchToRemotePlayback; mediaInfo is \(String(describing: mediaInfo))")
  if playbackMode == .remote {
    return
  }
  // If we were playing locally, load the local media on the remote player
  if playbackMode == .local, (_localPlayerView.playerState != .stopped), (mediaInfo != nil) {
    print("loading media: \(String(describing: mediaInfo))")
    let paused: Bool = (_localPlayerView.playerState == .paused)
    let mediaQueueItemBuilder = GCKMediaQueueItemBuilder()
    mediaQueueItemBuilder.mediaInformation = mediaInfo
    mediaQueueItemBuilder.autoplay = !paused
    mediaQueueItemBuilder.preloadTime = TimeInterval(UserDefaults.standard.integer(forKey: kPrefPreloadTime))
    mediaQueueItemBuilder.startTime = _localPlayerView.streamPosition ?? 0
    let mediaQueueItem = mediaQueueItemBuilder.build()

    let queueDataBuilder = GCKMediaQueueDataBuilder(queueType: .generic)
    queueDataBuilder.items = [mediaQueueItem]
    queueDataBuilder.repeatMode = .off

    let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
    mediaLoadRequestDataBuilder.queueData = queueDataBuilder.build()

    let request = sessionManager.currentCastSession?.remoteMediaClient?.loadMedia(with: mediaLoadRequestDataBuilder.build())
    request?.delegate = self
  }
  _localPlayerView.stop()
  _localPlayerView.showSplashScreen()
  setQueueButtonVisible(true)
  sessionManager.currentCastSession?.remoteMediaClient?.add(self)
  playbackMode = .remote
}

/* Play has been pressed in the LocalPlayerView. */
func continueAfterPlayButtonClicked() -> Bool {
  let hasConnectedCastSession = sessionManager.hasConnectedCastSession
  if mediaInfo != nil, hasConnectedCastSession() {
    // Display an alert box to allow the user to add to queue or play
    // immediately.
    if actionSheet == nil {
      actionSheet = ActionSheet(title: "Play Item", message: "Select an action", cancelButtonText: "Cancel")
      actionSheet?.addAction(withTitle: "Play Now", target: self,
                             selector: #selector(playSelectedItemRemotely))
    }
    actionSheet?.present(in: self, sourceView: _localPlayerView)
    return false
  }
  return true
}

Şimdi uygulamayı mobil cihazınızda çalıştırın. Yayın cihazınıza bağlanın ve bir videoyu oynatmaya başlayın. Videonun alıcıda oynatıldığını görüyor olmanız gerekir.

7. Mini kumanda

Yayın Tasarımı Kontrol Listesi, kullanıcı geçerli içerik sayfasından ayrıldığında tüm Cast uygulamalarının mini kumanda sunmasını gerektirir. Mini kumanda, mevcut yayın oturumu için anında erişim ve görünür bir hatırlatıcı sağlar.

CastVideos uygulamasını çalıştıran, mini kumandaya odaklanan bir iPhone'un alt kısmındaki görsel

Cast SDK'sı, kalıcı kontrolleri göstermek istediğiniz sahnelere eklenebilen bir kontrol çubuğu (GCKUIMiniMediaControlsViewController) sağlar.

Örnek uygulama için başka bir görünüm denetleyicisini sarmalayan ve alta GCKUIMiniMediaControlsViewController ekleyen bir GCKUICastContainerViewController kullanacağız.

AppDelegate.swift dosyasını değiştirin ve aşağıdaki yöntemde if useCastContainerViewController koşulu için aşağıdaki kodu ekleyin:

func application(_: UIApplication,
                 didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  ...
  let appStoryboard = UIStoryboard(name: "Main", bundle: nil)
  guard let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation")
    as? UINavigationController else { return false }
  let castContainerVC = GCKCastContext.sharedInstance().createCastContainerController(for: navigationController)
    as GCKUICastContainerViewController
  castContainerVC.miniMediaControlsItemEnabled = true
  window = UIWindow(frame: UIScreen.main.bounds)
  window?.rootViewController = castContainerVC
  window?.makeKeyAndVisible()
  ...
}

Mini denetleyicinin görünürlüğünü kontrol etmek için bu özelliği ve ayarlayıcı/alıcıyı ekleyin (bunları sonraki bir bölümde kullanacağız):

var isCastControlBarsEnabled: Bool {
    get {
      if useCastContainerViewController {
        let castContainerVC = (window?.rootViewController as? GCKUICastContainerViewController)
        return castContainerVC!.miniMediaControlsItemEnabled
      } else {
        let rootContainerVC = (window?.rootViewController as? RootContainerViewController)
        return rootContainerVC!.miniMediaControlsViewEnabled
      }
    }
    set(notificationsEnabled) {
      if useCastContainerViewController {
        var castContainerVC: GCKUICastContainerViewController?
        castContainerVC = (window?.rootViewController as? GCKUICastContainerViewController)
        castContainerVC?.miniMediaControlsItemEnabled = notificationsEnabled
      } else {
        var rootContainerVC: RootContainerViewController?
        rootContainerVC = (window?.rootViewController as? RootContainerViewController)
        rootContainerVC?.miniMediaControlsViewEnabled = notificationsEnabled
      }
    }
  }

Uygulamayı çalıştırıp video yayınlayın. Alıcıda oynatma başladığında, her sahnenin alt kısmında mini kumandanın belirdiğini görürsünüz. Mini kumandayı kullanarak uzaktan oynatmayı kontrol edebilirsiniz. Göz atma etkinliği ile yerel oynatıcı etkinliği arasında gezinirseniz mini kumandanın durumu, alıcının medya oynatma durumuyla senkronize olmalıdır.

8. Tanıtım yer paylaşımı

Google Cast tasarımıyla ilgili yapılacaklar listesi, bir gönderen uygulamanın artık Yayınlama özelliğini desteklediğini ve Google Cast'i kullanmaya yeni başlayan kullanıcılara da yardımcı olduğunu bildirmek için gönderen uygulamanın mevcut kullanıcılara Yayın düğmesini tanıtmasını gerektirir.

CastVideos uygulamasını çalıştıran ve Yayın düğmesi yer paylaşımlı bir şekilde yayın düğmesi vurgulanmış ve "TV'nize ve hoparlörlerinize medya yayınlamak için dokunun" mesajının gösterildiği bir iPhone görseli.

GCKCastContext sınıfında, kullanıcılara ilk kez gösterildiğinde Yayın düğmesini vurgulamak için kullanılabilen presentCastInstructionsViewControllerOnce yöntemi bulunur. MediaViewController.swift ve MediaTableViewController.swift için şu kodu ekleyin:

override func viewDidLoad() {
  ...

  NotificationCenter.default.addObserver(self, selector: #selector(castDeviceDidChange),
                                         name: NSNotification.Name.gckCastStateDidChange,
                                         object: GCKCastContext.sharedInstance())
}

@objc func castDeviceDidChange(_: Notification) {
  if GCKCastContext.sharedInstance().castState != .noDevicesAvailable {
    // You can present the instructions on how to use Google Cast on
    // the first time the user uses you app
    GCKCastContext.sharedInstance().presentCastInstructionsViewControllerOnce(with: castButton)
  }
}

Uygulamayı mobil cihazınızda çalıştırdığınızda tanıtım amaçlı yer paylaşımını görürsünüz.

9. Genişletilmiş kumanda

Google Cast tasarım listesi, gönderen uygulamanın, yayınlanmakta olan medya için genişletilmiş denetleyici sağlamasını gerektirir. Genişletilmiş kumanda, mini kumandanın tam ekran sürümüdür.

CastVideos uygulamasını çalıştıran bir iPhone'un alt kısmında genişletilmiş kumandanın göründüğü bir video oynatan görsel.

Genişletilmiş denetleyici, uzaktan medya oynatmanın tam kontrolüne sahip bir tam ekran görünümüdür. Bu görünüm, bir yayınlama uygulamasının alıcının ses kontrolü ve oturum yaşam döngüsü (yayını bağlama/yayını durdurma) hariç olmak üzere bir yayın oturumunun her yönetilebilir yönünü yönetmesine olanak tanımalıdır. Medya oturumuyla ilgili tüm durum bilgilerini de (ör. poster, başlık, alt başlık) 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ş denetleyiciyi etkinleştirin. Varsayılan genişletilmiş denetleyiciyi etkinleştirmek için AppDelegate.swift öğesini değiştirin:

import GoogleCast

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  ...

  func application(_: UIApplication,
                   didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    ...
    // Add after the setShareInstanceWith(options) is set.
    GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true
    ...
  }
  ...
}

Kullanıcı video yayınlamaya başladığında genişletilmiş denetleyiciyi yüklemek için MediaViewController.swift öğesine aşağıdaki kodu ekleyin:

@objc func playSelectedItemRemotely() {
  ...
  appDelegate?.isCastControlBarsEnabled = false
  GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls()
}

Genişletilmiş kumanda, kullanıcı mini kumandaya dokunduğunda da otomatik olarak açılır.

Uygulamayı çalıştırıp video yayınlayın. Genişletilmiş denetleyici gösterilir. Video listesine geri dönün. Mini kumandayı tıkladığınızda genişletilmiş kumanda tekrar yüklenir.

10. Cast Connect desteği ekleyin

Cast Connect kitaplığı, mevcut gönderen uygulamalarının Cast protokolü aracılığıyla Android TV uygulamalarıyla iletişim kurmasına olanak tanır. Cast Connect, Android TV uygulamanızın alıcı görevi gördüğü Cast altyapısını temel alır.

Bağımlılıklar

Podfile içinde google-cast-sdk öğesinin aşağıda listelenen 4.4.8 veya daha üstünü işaret ettiğinden emin olun. Dosyada değişiklik yaptıysanız değişikliği projenizle senkronize etmek için konsoldan pod update komutunu çalıştırın.

pod 'google-cast-sdk', '>=4.4.8'

GCKLaunchOptions

Android Alıcı olarak da bilinen Android TV uygulamasını başlatmak için GCKLaunchOptions nesnesinde androidReceiverCompatible işaretini true olarak ayarlamamız gerekir. Bu GCKLaunchOptions nesnesi, alıcının nasıl başlatılacağını belirler ve GCKCastContext.setSharedInstanceWith kullanılarak paylaşılan örnekte ayarlanan GCKCastOptions öğesine iletilir.

Şu satırları AppDelegate.swift cihazınıza ekleyin:

let options = GCKCastOptions(discoveryCriteria:
                          GCKDiscoveryCriteria(applicationID: kReceiverAppID))
...
/** Following code enables CastConnect */
let launchOptions = GCKLaunchOptions()
launchOptions.androidReceiverCompatible = true
options.launchOptions = launchOptions

GCKCastContext.setSharedInstanceWith(options)

Başlatma Kimlik Bilgilerini Ayarla

Gönderen tarafında, oturuma kimlerin katıldığını temsil etmesi için GCKCredentialsData değerini belirtebilirsiniz. credentials, ATV uygulamanız tarafından anlaşılabildiği sürece kullanıcı tanımlı bir dizedir. GCKCredentialsData, Android TV uygulamanıza yalnızca başlatma veya katılma sırasında aktarılır. Bağlıyken tekrar ayarlarsanız Android TV uygulamanıza aktarılmaz.

Lansman Kimlik Bilgilerini ayarlamak için GCKLaunchOptions ayarlandıktan sonra GCKCredentialsData herhangi bir zamanda tanımlanmalıdır. Bunu göstermek amacıyla, oturum oluşturulduğunda iletilecek kimlik bilgilerini ayarlamak için Creds düğmesi mantığını ekleyelim. MediaTableViewController.swift cihazınıza şu kodu ekleyin:

class MediaTableViewController: UITableViewController, GCKSessionManagerListener, MediaListModelDelegate, GCKRequestDelegate {
  ...
  private var credentials: String? = nil
  ...
  override func viewDidLoad() {
    ...
    navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Creds", style: .plain,
                                                       target: self, action: #selector(toggleLaunchCreds))
    ...
    setLaunchCreds()
  }
  ...
  @objc func toggleLaunchCreds(_: Any){
    if (credentials == nil) {
        credentials = "{\"userId\":\"id123\"}"
    } else {
        credentials = nil
    }
    Toast.displayMessage("Launch Credentials: "+(credentials ?? "Null"), for: 3, in: appDelegate?.window)
    print("Credentials set: "+(credentials ?? "Null"))
    setLaunchCreds()
  }
  ...
  func setLaunchCreds() {
    GCKCastContext.sharedInstance()
        .setLaunch(GCKCredentialsData(credentials: credentials))
  }
}

Yükleme İsteğinde Kimlik Bilgilerini Belirle

credentials uygulamasını hem Web hem de Android TV Alıcısı uygulamalarınızda işlemek için MediaTableViewController.swift sınıfınızda loadSelectedItem işlevinin altına şu kodu ekleyin:

let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
...
mediaLoadRequestDataBuilder.credentials = credentials
...

Göndereninizin yayın yaptığı alıcı uygulamaya bağlı olarak SDK, yukarıdaki kimlik bilgilerini devam eden oturuma otomatik olarak uygular.

Cast Connect'i test etme

Android TV APK'sını Google TV Yüklü Chromecast'e yükleme adımları

  1. Android TV cihazınızın IP adresini bulun. Bu özellik genellikle Ayarlar > Ağ ve İnternet > (Cihazınızın bağlı olduğu ağ adı) altından bulunur. Sağ tarafta, ayrıntıları ve cihazınızın ağdaki IP'sini gösterir.
  2. Cihazınıza terminali kullanarak ADB aracılığıyla bağlanmak için IP adresini kullanın:
$ adb connect <device_ip_address>:5555
  1. Terminal pencerenizden, bu codelab'in başında indirdiğiniz codelab örneklerinin üst düzey klasörüne gidin. Örneğin:
$ cd Desktop/ios_codelab_src
  1. Aşağıdaki komutu çalıştırarak bu klasördeki .apk dosyasını Android TV'nize yükleyin:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
  1. Artık Android TV cihazınızdaki Uygulamalarınız menüsünde Video Yayınla adıyla bir uygulamayı görebilmeniz gerekir.
  2. Ardından, uygulamayı bir emülatörde veya mobil cihazda derleyip çalıştırın. Android TV cihazınızla yayın oturumu oluşturulduktan sonra, Android TV'nizde Android Alıcı uygulaması başlatılır. iOS mobil gönderenden gelen bir video oynatıldığında, video Android Alıcı'da başlatılır ve Android TV cihazınızın uzaktan kumandasını kullanarak oynatmayı kontrol edebilmenizi sağlar.

11. Yayın widget'larını özelleştirme

Başlatma

Uygulama Bitti klasörüyle başlayın. AppDelegate.swift dosyanızdaki applicationDidFinishLaunchingWithOptions yöntemine aşağıdakileri ekleyin.

func application(_: UIApplication,
                 didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  ...
  let styler = GCKUIStyle.sharedInstance()
  ...
}

Bu codelab'in geri kalanında belirtildiği gibi bir veya daha fazla özelleştirmeyi uygulamayı tamamladıktan sonra aşağıdaki kodu çağırarak stilleri kaydedin

styler.apply()

Yayın görünümlerini özelleştirme

Görünümler genelinde varsayılan stil yönergelerine sahip olarak, Cast Uygulama Çerçevesi'nin yönettiği tüm görünümleri özelleştirebilirsiniz. Örnek olarak, simge tonu rengini değiştirelim.

styler.castViews.iconTintColor = .lightGray

Gerekirse varsayılanları ekran bazında geçersiz kılabilirsiniz. Örneğin, yalnızca genişletilmiş medya denetleyicisinde simge tonu renginin açıkGrayRenk değerini geçersiz kılabilirsiniz.

styler.castViews.mediaControl.expandedController.iconTintColor = .green

Renkleri değiştirme

Arka plan rengini tüm görünümler için (veya her görünüm için ayrı ayrı) özelleştirebilirsiniz. Aşağıdaki kod, Cast Uygulama Çerçevesi tarafından sağlanan tüm görünümler için arka plan rengini mavi olarak ayarlar.

styler.castViews.backgroundColor = .blue
styler.castViews.mediaControl.miniController.backgroundColor = .yellow

Yazı tipi değiştiriliyor

Yayın görünümlerinde görünen farklı etiketler için yazı tiplerini özelleştirebilirsiniz. Örnek olması açısından, tüm yazı tiplerini "Courier-Oblique" olarak ayarlayalım.

styler.castViews.headingTextFont = UIFont.init(name: "Courier-Oblique", size: 16) ?? UIFont.systemFont(ofSize: 16)
styler.castViews.mediaControl.headingTextFont = UIFont.init(name: "Courier-Oblique", size: 6) ?? UIFont.systemFont(ofSize: 6)

Varsayılan düğme resimlerini değiştirme

Projeye kendi özel resimlerinizi ekleyin ve resimleri düğmelerinize atayarak bunların stilini belirleyin.

let muteOnImage = UIImage.init(named: "yourImage.png")
if let muteOnImage = muteOnImage {
  styler.castViews.muteOnImage = muteOnImage
}

Yayınla düğmesi temasını değiştirme

Kullanıcı Arayüzü Görünüm Protokolü'nü kullanarak Yayın Widget'larını da temalandırabilirsiniz. Gösterildiği tüm görünümlerde GCKUICastButton için aşağıdaki kod temaları yer alır:

GCKUICastButton.appearance().tintColor = UIColor.gray

12. Tebrikler

Artık iOS'te Cast SDK'sı widget'larını kullanarak bir video uygulamasını Cast için nasıl etkinleştireceğinizi biliyorsunuz.

Daha fazla ayrıntı için iOS Gönderen geliştirici kılavuzuna bakın.