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ğiniz açıklanmaktadır.

Google Cast nedir?

Google Cast, kullanıcıların mobil cihazdan TV'ye içerik yayınlamasına olanak tanır. Böylece kullanıcılar TV'de medya oynatmak için uzaktan kumanda olarak mobil cihazlarını kullanabilirler.

Google Cast SDK'sı, Google Cast uyumlu cihazları (TV veya ses sistemi gibi) kontrol etmek için uygulamanızı genişletmenize olanak sağlar. 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, Cast kullanıcı deneyimini tüm desteklenen platformlarda basit ve tahmin edilebilir hale getirmek için sağlanmıştır.

Ne 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?

  • Google Cast SDK'sını örnek bir video uygulamasına ekleme.
  • Google Cast cihazı seçmek için Yayınla düğmesini ekleme.
  • Yayın cihazına bağlanma ve medya alıcısı başlatma.
  • 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ı sağlama.
  • Yayın widget'larını özelleştirme.
  • Cast Connect'i entegre etme

Gerekenler

  • En son Xcode.
  • iOS 9 veya sonraki sürümleri çalıştıran bir mobil cihaz (veya Xcode Simülatörü).
  • Mobil cihazınızı geliştirme bilgisayarınıza bağlamak için USB cihaz kablosu (cihaz kullanılıyorsa).
  • İnternet erişimiyle yapılandırılmış Chromecast veya Android TV gibi bir Google Cast cihazı.
  • HDMI girişli bir TV veya monitör.
  • Cast Connect entegrasyonunu test etmek için Google TV'li Chromecast gereklidir ancak Codelab'in geri kalanı için isteğe bağlıdır. Böyle bir aboneliğiniz yoksa, bu eğiticinin sonuna doğru Cast Connect Desteği adımını atlayabilirsiniz.

Deneyim

  • Daha önce iOS geliştirme bilgisine sahip olmanız gerekir.
  • Ayrıca, TV izleme konusunda da önceden bilgi sahibi olmanız gerekir :)

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

Sadece okuyun Okuyun ve alıştırmaları tamamlayın

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

Acemi Orta Yeterli

TV izleme deneyiminizi nasıl değerlendirirsiniz?

Acemi Orta Yeterli

2. Örnek kodu alın

Tüm örnek kodu bilgisayarınıza indirebilirsiniz...

ve indirilen zip dosyasını paketten çıkarın.

3. Örnek uygulamayı çalıştırın

Apple iOS logosu

Öncelikle, 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çip videoyu cihazda yerel olarak oynatabilir veya bir Google Cast cihazında yayınlayabilir.

Kod indirildiğinde, tamamlanmış örnek uygulamayı Xcode'da nasıl açıp çalıştıracağınız açıklanmaktadır:

Sık sorulan sorular

CocoaPods kurulumu

CocoaPods'u kurmak için konsolunuza gidin ve macOS'ta varsayılan olarak bulunan Roku'yu kullanarak yükleyin:

sudo gem install cocoapods

Herhangi bir sorun yaşarsanız bağımlılık yöneticisini indirip yüklemek için resmi dokümanlara 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çeneğini belirleyin.
  2. Örnek kod klasöründe klasör simgesiapp-done dizininden CastVideos-ios.xcworkspace dosyasını seçin.

Uygulamayı çalıştırın

Hedefi ve simülasyon aracını seçip uygulamayı çalıştırın:

XCode uygulama simülasyon aracı araç çubuğu

Video uygulaması birkaç saniye sonra görünecektir.

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

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

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

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

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

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

Video listesine geri dönün.

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

CastVideos uygulamasını çalıştıran ve alt kısmında mini kumanda bulunan bir iPhone görseli

Alıcıda videoyu 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ırlayın

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

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

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

Proje ayarlama

Artık Xcode'u kullanarak başlangıç projesinin üzerine derlemeye 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çeneğini belirleyin.
  2. Örnek kod klasöründe 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 atması için bir liste sağlar. Kullanıcılar, ayrıntıları görmek için bir video seçebilir veya videoyu mobil cihazda yerel olarak oynatabilir.

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

MediaTableViewController

Bu UITableViewController, bir MediaListModel örneğindeki videoların listesini gösterir. Video listesi ve bunlarla ilişkili meta veriler uzak bir sunucuda JSON dosyası olarak barındırılır. MediaListModel bu JSON dosyasını getirir ve MediaItem nesne listesi oluşturmak için işler.

MediaItem nesnesi, bir videonun yanı sıra başlık, açıklama, resmin URL'si ve akışın URL'si gibi meta verileri modeller.

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

Kullanıcıya her video için kısa bir açıklama içeren video küçük resimlerinin listesi sunulur. Bir öğe seçildiğinde, ilgili MediaItem öğesi MediaViewController etiketine aktarılır.

MediaViewController

Bu görünüm denetleyicisi, belirli bir videoyla ilgili meta verileri gösterir ve kullanıcının videoyu mobil cihazda yerel olarak oynatmasına olanak tanır.

Görünüm denetleyicisi, seçili videonun açıklamasını gösteren bir LocalPlayerView, bazı medya denetimleri ve bir metin alanı barındırır. Oynatıcı, ekranın üst bölümünü kaplar ve videonun ayrıntılı açıklaması için kullanıcıya yer verebilir. Kullanıcılar videoyu oynatabilir/duraklatabilir veya yerel video oynatmayı arayabilir.

Sık sorulan sorular

5. Yayınla düğmesini ekleme

CastVideos uygulamasını çalıştıran ve sağ üst köşede Yayınla düğmesini gösteren bir iPhone'un üst üçte birlik kısmını gösteren görsel

Yayın özellikli bir uygulama, görünüm denetleyicilerinin her birinde Yayınla düğmesini görüntüler. Yayınla düğmesi tıklandığında, kullanıcının seçebileceği Yayın cihazlarının listesi gösterilir. Kullanıcı, gönderen cihazda yerel olarak içerik oynatıyorsa yayın cihazı seçmek, ilgili yayın cihazında oynatmayı başlatır veya devam ettirir. Kullanıcı, Yayın oturumu sırasında herhangi bir zamanda Yayın düğmesini tıklayabilir ve uygulamanızı Yayın cihazına yayınlamayı durdurabilir. Kullanıcının, Google Cast Tasarım Listesi'nde açıklandığı gibi, uygulamanızın herhangi bir ekranındayken Yayın cihazına bağlanabilmesi veya yayın cihazının bağlantısını kesebilmesi gerekir.

Yapılandırma

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

Başlatma

Yayın çerçevesi, çerçevenin tüm etkinliklerini koordine eden global bir tekil nesneye sahiptir: GCKCastContext. Gönderen uygulamanın yeniden başlatılması sırasında otomatik oturum devam ettirmenin düzgün şekilde tetiklenebilmesi ve cihazların taranması başlatılabilmesi için bu nesne, uygulamanın yaşam döngüsünün başlarında, genellikle de uygulama yetkisinin application(_:didFinishLaunchingWithOptions:) yönteminde başlatılmalıdır.

GCKCastContext başlatılırken GCKCastOptions nesnesi sağlanmalıdır. Bu sınıf, çerçevenin davranışını etkileyen seçenekler içerir. En önemlisi, yayın cihazı keşfi sonuçlarını filtrelemek ve bir yayın oturumu başlatıldığında alıcı uygulamasını başlatmak için kullanılan alıcı uygulama kimliğidir.

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

Kendi Cast uyumlu 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 öğesini kullanıcı varsayılanları ile uygulama kimliği ile başlatmak için AppDelegate.swift adresine aşağıdaki kodu ekleyin ve Google Cast çerçevesi için bir günlük kaydı 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çmesine izin vermek için Yayınla düğmesi eklememiz gerekiyor. Cast SDK'sı, UIButton alt sınıf olarak GCKUICastButton adlı bir Cast düğmesi bileşeni sağlar. Uygulamanın UIBarButtonItem çubuğuna sarmalanarak başlık çubuğuna eklenebilir. Yayınla düğmesini hem MediaTableViewController hem de MediaViewController öğesine eklememiz gerekiyor.

MediaTableViewController.swift ve MediaViewController.swift için aşağıdaki 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)

    ...
  }
  ...
}

Ardından, 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 Yayın düğmesi göreceksiniz. 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. Örnek alıcı uygulaması, Yayın cihazında yüklenir. Göz atma etkinliği ve yerel oynatıcı etkinliği arasında gezinebilirsiniz. Yayınla düğmesi durumu senkronize durumda kalır.

Medya oynatma desteğimiz yok. Bu nedenle henüz Cast cihazında video oynatamazsınız. 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 ve belirli bir videoyla ilgili ayrıntıları gösteren "Tears of Steel" adlı iPhone'un resmi. Alt kısımda mini oynatıcı bulunur

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

Medya yayınlanıyor

Genel olarak, bir yayın cihazında medya oynatmak isterseniz aşağıdaki işlemlerin yapılması gerekir:

  1. Medya öğesini modelleyen Cast SDK'sından bir 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 göre oynatma komutlarını alıcıya gönderin.

1. adım, bir nesnenin başka bir özellikle eşlenmesine denk gelir. GCKMediaInformation, SDK'nın anladığı şeydir ve MediaItem, uygulamamızın bir medya öğesidir. MediaItem özelliğini kolayca GCKMediaInformation ile eşleyebiliriz. Önceki bölümde zaten 2. adımı gerçekleştirmiştik. Cast SDK ile 3. adımı kolayca uygulayabilirsiniz.

Örnek uygulama MediaViewController, bu sıralamayı kullanarak yerel ve uzaktan oynatma arasında zaten ayrım yapıyor:

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

private var playbackMode = PlaybackMode.none

Bu codelab'de örnek oynatıcı mantığının nasıl çalıştığını tam olarak anlamanız önemli değildir. İki medya konumunun da aynı şekilde bilinmesi için uygulamanızın medya oynatıcısının değiştirilmesi gerekir.

Yerel oynatıcı, Yayınlama durumları hakkında henüz hiçbir bilgiye sahip olmadığı için şu anda 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 gerekiyor. Örneğin, yayınlamaya başladığımızda yerel oynatmayı durdurmamız ve bazı kontrolleri devre dışı bırakmamız gerekir. Benzer şekilde, bu görünüm denetleyicisindeyken içerik yayınlamayı durdurursak yerel oynatmaya geçmemiz gerekir. Bu sorunu çözmek için Yayın çerçevesi tarafından oluşturulan çeşitli etkinlikleri dinlememiz gerekir.

Yayınlama oturumu yönetimi

Yayın çerçevesi için Yayınlama oturumu, bir cihaza bağlanma, başlatma (veya katılma), bir alıcı uygulamasına bağlanma ve uygun durumlarda bir medya kontrol kanalı başlatma adımlarını birleştirir. Medya denetim kanalı, Yayın çerçevesinin alıcı medya oynatıcıdan mesaj gönderme ve alma yöntemidir.

Kullanıcı, Yayın düğmesinden bir cihaz seçtiğinde Yayınla oturumu 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 işlemi de Cast çerçevesi tarafından otomatik olarak gerçekleştirilir.

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

Önce oturum dinleyicimizi 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 içinde, yerel bir oynatıcıya geçiş veya bu oyuncudan geçebilmemiz için yayın cihazına bağlanıldığında veya cihazın bağlantısı kesildiğinde sizi bilgilendirmeyi amaçlıyoruz. Bağlantının, yalnızca mobil cihazınızda çalışan uygulamanızın örneği tarafından değil, farklı bir mobil cihazda çalışan başka bir (veya) başka örneği tarafından da kesintiye uğrayabileceğini unutmayın.

Şu anda etkin olan oturuma GCKCastContext.sharedInstance().sessionManager.currentCastSession olarak erişilebilir. Oturumlar, Yayın iletişim kutularından kullanıcı hareketlerine göre otomatik olarak oluşturulur ve kaldırılır.

Medya yükleniyor

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

Alıcıda seçili olan videoyu yüklemek için aşağıdaki kodu MediaViewController.swift ürününe 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 için 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ıp bir video oynatmaya başlayın. Videonun alıcı tarafından oynatıldığını görürsünüz.

7. Mini kumanda

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

Mini video kumandasına odaklanan, CastVideos uygulamasını çalıştıran bir iPhone'un alt kısmını gösteren görsel

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

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

AppDelegate.swift dosyasını değiştirin ve if useCastContainerViewController koşulu için aşağıdaki kodu aşağıdaki şekilde 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 kumandanın görünürlüğünü kontrol etmek için bu özelliği ve setter/alıcıyı ekleyin (bunları daha 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ın ve video yayınlayın. Alıcıda oynatma başladığında her sahnenin alt kısmında mini kumanda görünür. Mini kumandayı kullanarak uzaktan oynatmayı kontrol edebilirsiniz. Tarama etkinliği ile yerel oynatıcı etkinliği arasında gezinirseniz mini kumanda durumu, alıcı medya oynatma durumuyla senkronize olmalıdır.

8. Tanıtım amaçlı yer paylaşımı

Google Cast tasarım kontrol listesi, gönderenlerin uygulamasının artık Yayınla özelliğini desteklediğini ve ayrıca Google Cast'i kullanmaya yeni başlayanlara yardımcı olacağını bildirmek için mevcut bir uygulamanın Yayınla düğmesini tanıtmasını gerektirir.

Yayın düğmesi yer paylaşımıyla Yayınla düğmesini vurgulayan ve "TV'nize ve Hoparlörlerinize medya yayınlamak için dokunun" mesajını gösteren, CastVideos uygulamasını çalıştıran bir iPhone'un resmi

GCKCastContext sınıfında, yayınlama düğmesi kullanıcılara ilk kez gösterildiğinde vurgulamak için kullanılabilen presentCastInstructionsViewControllerOnce yöntemi bulunur. MediaViewController.swift ve MediaTableViewController.swift için aşağıdaki 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 giriş yer paylaşımını görürsünüz.

9. Genişletilmiş kumanda

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

CastVideos uygulamasını çalıştıran ve genişletilmiş kumandanın altında göründüğü bir videoyu oynatan iPhone'un resmi

Genişletilmiş kumanda, uzaktan medya oynatımı üzerinde tam kontrol sunan tam ekran görünümüdür. Bu görünüm, alıcı ses kontrolü ve oturum yaşam döngüsü (bağlama/yayınlamayı durdurma) hariç, bir yayınlama uygulamasının yayın oturumunun tüm yönetilebilir özelliklerini yönetebilmesini sağlamalıdır. Ayrıca, medya oturumuyla ilgili tüm durum bilgilerini (poster, başlık, alt başlık 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ş kumandayı etkinleştirmektir. Varsayılan genişletilmiş kumandayı 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ş kumandayı yüklemek için aşağıdaki kodu MediaViewController.swift öğesine ekleyin:

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

Genişletilmiş kumanda, kullanıcı mini kumandaya dokunduğunda otomatik olarak başlatılır.

Uygulamayı çalıştırın ve video yayınlayın. Genişletilmiş kumandayı görürsünüz. Video listesine geri dönün ve mini kumandayı tıkladığınızda genişletilmiş kumanda tekrar yüklenir.

10. Cast Connect desteği ekleme

Cast Connect kitaplığı, mevcut gönderen uygulamalarının Yayın protokolü aracılığıyla Android TV uygulamalarıyla iletişim kurmasını sağlar. Cast Connect, yayın altyapısını temel alır ve Android TV uygulamanız alıcı işlevi görür.

Bağımlılıklar

Podfile cihazınızda, aşağıda belirtilen google-cast-sdk öğesinin 4.4.8 veya daha yüksek bir noktaya yönlendirdiğ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 adlandırılan 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ı ve paylaşılan örnekte GCKCastContext.setSharedInstanceWith kullanılarak ayarlanan GCKCastOptions öğesine nasıl iletileceğini belirtir.

AppDelegate.swift cihazınıza aşağıdaki satırları 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 Belirle

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

Lansman Kimlik Bilgilerini ayarlamak için GCKLaunchOptions özelliği ayarlandıktan sonra GCKCredentialsData herhangi bir zamanda tanımlanmalıdır. Bunu göstermek için, oturum kurulduğunda iletilen kimlik bilgilerini ayarlamak üzere Creds düğmesiyle ilgili bir mantık ekleyelim. MediaTableViewController.swift kodunuza aşağıdaki 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 Ayarlama

credentials uygulamasını hem Web hem de Android TV Alıcı uygulamalarınızda işleyebilmek için aşağıdaki kodu loadSelectedItem işlevinizin MediaTableViewController.swift sınıfına ekleyin:

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

Göndereninizin yayın yaptığı alıcıya 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'li 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ında kullanılabilir. Sağ tarafta, ayrıntılar ve cihazınızın ağdaki IP adresi gösterilir.
  2. Terminal kullanarak ADB üzerinden bağlanmak için cihazınızın 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 kodu ç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 Yayın Videoları adıyla bir uygulamayı görebilirsiniz.
  2. İşlemi tamamladıktan sonra uygulamayı bir emülatörde veya mobil cihazda oluşturup çalıştırın. Android TV cihazınızla bir yayınlama oturumu oluşturulduğunda, Android Android cihazınızda Android Buyer uygulamasını başlatmalıdır. iOS mobil cihazınızdaki bir videoyu oynatırken, videoyu Android Alıcısı'nda başlatmanız ve Android TV cihazınızın uzaktan kumandasını kullanarak oynatmayı kontrol etmenize olanak tanır.

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

Başlatma

App-Done klasörüyle başlayın. Aşağıdakileri AppDelegate.swift dosyanızdaki applicationDidFinishLaunchingWithOptions yöntemine 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 tamamladıktan sonra, aşağıdaki kodu çağırarak stilleri uygulayın

styler.apply()

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

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

styler.castViews.iconTintColor = .lightGray

Gerekirse varsayılan olarak ekran bazında geçersiz kılabilirsiniz. Örneğin, simge ton renginin açıkGrayColor değerini yalnızca genişletilmiş medya denetleyicisi için geçersiz kılmak istediğinizde kullanılabilir.

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

Renk 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, yayın uygulamanızın çerçevesinin sağladığı 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ı tiplerini değiştirme

Yayın görünümlerinde görülen farklı etiketler için yazı tiplerini özelleştirebilirsiniz. Açıklama amaçlı olarak 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 atamak için düğmelerinize atayın.

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

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

Kullanıcı Arayüzü Görünüm Protokolü'nü kullanarak Yayın Widget'larını da temalandırabilirsiniz. Aşağıdaki kod, GCKUICastButton'ın göründüğü tüm görünümlerde temasını oluşturuyor:

GCKUICastButton.appearance().tintColor = UIColor.gray

12. Tebrikler

Artık iOS'te Cast SDK widget'larını kullanarak video uygulaması yayınlamaya nasıl başlayacağınızı biliyorsunuz.

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