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ın nasıl değiştirileceği açıklanmaktadır.

Google Cast nedir?

Google Cast, kullanıcıların mobil cihazlardan TV'ye içerik yayınlamasına olanak tanır. Kullanıcılar daha sonra mobil cihazlarını TV'de medya oynatma 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 Listesi'ne göre gerekli kullanıcı arayüzü bileşenlerini eklemenize olanak tanır.

Google Cast Tasarım Listesi, Cast kullanıcı deneyimini desteklenen tüm platformlarda basit ve tahmin edilebilir hale getirmek amacıyla hazırlanmıştır.

Ne tür bir kampanya oluşturacağız?

Bu codelab'i tamamladığınızda bir Google Cast cihazında video yayınlayabilecek bir iOS video uygulamanız olacak.

Neler öğreneceksiniz?

  • Google Cast SDK'sı örnek bir video uygulamasına nasıl eklenir?
  • 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 denetleyici ekleme.
  • Genişletilmiş kumanda ekleme.
  • 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 veri kablosu (cihaz kullanıyorsanız).
  • İnternet erişimiyle yapılandırılmış 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'li Chromecast gereklidir ancak Codelab'in geri kalanında isteğe bağlıdır. Böyle bir cihazınız yoksa bu eğiticinin sonuna doğru Cast Connect Desteği adımını atlayabilirsiniz.

Deneyim

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

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

Yalnızca 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ın paketini açı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çebilir, ardından videoyu cihazda yerel olarak oynatabilir veya Google Cast cihazına yayınlayabilir.

Kodun indirilmesiyle birlikte aşağıdaki talimatlar, tamamlanmış örnek uygulamanın Xcode'da nasıl açılacağını ve çalıştırılacağını açıklar:

Sık sorulan sorular

CocoaPods kurulumu

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

sudo gem install cocoapods

Herhangi bir sorun yaşarsanız bağımlı yöneticisini indirip yüklemek için resmi dokümanları inceleyin.

Proje ayarlama

  1. Terminalinize ve codelab dizinine gidin.
  2. Kapsülleri Podfile'dan 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ırma

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

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

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

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 izin isteyen onay iletişim kutusu

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

Bir video seçin, 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 bir mini kumanda görünür.

CastVideos uygulamasını çalıştıran ve alt tarafta mini kumanda görünen iPhone çizimi

Alıcı üzerinde videoyu duraklatmak için mini kumandadaki duraklat düğmesini tıklayın. Videoyu tekrar oynatmaya devam etmek için mini kumandada 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 iPhone'u gösteren görsel

İndirdiğiniz başlangıç uygulamasına, Google Cast için destek 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ı
  • Google Cast cihazında çalışan bir alıcı uygulaması

Proje ayarlama

Artık Xcode'u kullanarak başlangıç projesinin üzerine inşa edilmeye hazırsınız.

  1. Terminalinize ve codelab dizinine gidin.
  2. Kapsülleri Podfile'dan 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 atabilmesi için bir liste sağlar. Kullanıcılar bir videoyu seçerek ayrıntılarını görebilir veya mobil cihazda videoyu 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 sunucuda JSON dosyası olarak barındırılır. MediaListModel, bu JSON'yi getirir ve MediaItem nesnelerinin bir listesini oluşturmak için işler.

MediaItem nesnesi, bir videoyu ve ilişkili meta verilerini (ör. başlık, açıklama, resim URL'si ve yayının URL'si) modeller.

MediaTableViewController, bir MediaListModel örneği oluşturur. Ardından, tablo görünümünü yükleyebilmesi için medya meta verileri indirildiğinde haberdar olmak amacıyla kendisini bir MediaListModelDelegate olarak kaydeder.

Kullanıcıya her video için kısa bir açıklama içeren video küçük resimleri listesi sunulur. Bir öğe seçildiğinde karşılık gelen MediaItem, MediaViewController öğesine 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ü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 ayrıntılı açıklaması için kullanıcıya yer açılır. Kullanıcı bu videoyu oynatabilir/duraklatabilir veya yerel video oynatmayı seçebilir.

Sık sorulan sorular

5. Yayınla düğmesi ekleniyor

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

Yayın özelliği etkin bir uygulama, Yayınla düğmesini her görünüm denetleyicisinde gösterir. 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ı, gönderen cihazda yerel olarak içerik oynatıyorsa, yayın cihazı seçildiğinde o yayın cihazında oynatma işlemi başlar veya devam eder. Kullanıcı, Yayın oturumu sırasında istediği zaman Yayınla düğmesini tıklayıp uygulamanızı Yayın cihazına yayınlamayı durdurabilir. Kullanıcının, Google Cast Tasarım Kontrol Listesi'nde açıklandığı şekilde, uygulamanızın herhangi bir ekranında Yayın cihazına bağlanabilmesi veya yayın bağlantısını kesebilmesi gerekir.

Yapılandırma

Başlangıç projesi, tamamlanmış örnek uygulamadakiyle aynı bağımlılıkları ve Xcode kurulumunu gerektirir. Bu bölüme dönün ve GoogleCast.framework hizmetini 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 GCKCastContext adlı genel bir tekil nesneye sahiptir. Gönderen uygulamayı yeniden başlatırken otomatik oturum devam ettirmenin düzgün şekilde tetiklenebilmesi ve cihaz taraması başlayabilmesi için bu nesne, uygulamanın yaşam döngüsünde, genellikle uygulamanın yetki verilmiş kullanıcının application(_:didFinishLaunchingWithOptions:) yönteminde erken başlatılmalıdır.

GCKCastContext başlatılırken bir GCKCastOptions nesnesi sağlanmalıdır. Bu sınıf, çerçevenin davranışını etkileyen seçenekler içerir. En önemlisi, yayın cihazı keşif 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çevesindeki günlük iletilerini almak üzere bir günlük kaydı yetkilisi oluşturmak için de iyi bir yerdir. Bunlar, hata ayıklama ve sorun giderme için yararlı olabilir.

Kendi Cast özellikli uygulamanızı geliştirdiğinizde, bir Cast geliştiricisi olarak kaydolmanız ve ardından uygulamanız için bir uygulama kimliği edinmeniz gerekir. Bu codelab'de örnek bir uygulama kimliği kullanacağız.

GCKCastContext öğesini kullanıcı varsayılanları ile uygulama kimliğinde başlatmak için AppDelegate.swift uygulamasına 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üğmesini 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 uygulamanın başlık çubuğuna eklenebilir. Yayınla düğmesini hem MediaTableViewController hem de MediaViewController öğesine eklememiz gerekiyor.

MediaTableViewController.swift ve MediaViewController.swift konumlarına ş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)

    ...
  }
  ...
}

Ardından MediaViewController.swift kodunuza şu kodu 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ö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çtiğinizde örnek alıcı uygulama, 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 edilir.

Henüz medya oynatma desteği sağlamadığımız için 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

Belirli bir videoyla ilgili ayrıntıları ('Çelik Gözyaşları') gösteren CastVideos uygulamasını çalıştıran bir iPhone'u gösteren görsel. Alttaki mini oynatıcı

Örnek uygulamayı, Cast cihazında uzaktan video oynatacak şekilde genişleteceğiz. Bunun için Yayın çerçevesinin oluşturduğu çeşitli etkinlikleri dinlememiz gerekir.

Medya yayınlanıyor

Genel olarak, Yayın cihazında medya oynatmak isterseniz aşağıdakilerin yapılması gerekir:

  1. Cast SDK'sından bir medya öğesini modelleyen 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 takip edin.
  5. Kullanıcı etkileşimlerini temel alan oynatma komutlarını alıcıya gönderin.

1. adım, bir nesneyi başka bir nesneyle eşlemeye karşılık gelir. GCKMediaInformation, Cast SDK'sının anladığı bir şeydir ve MediaItem, uygulamamızın bir medya öğesine ilişkin kapsülüdür; bir MediaItem öğesini kolayca GCKMediaInformation ile eşleyebiliriz. Önceki bölümde 2. adımı tamamladık. 3. adım, Cast SDK'sıyla kolayca uygulanabilir.

MediaViewController örnek uygulaması, bu sıralamayı kullanarak yerel ve uzaktan oynatma arasında zaten ayrım yapar:

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 şekilde algılayacak şekilde değiştirilmesi gerektiğini anlamak önemlidir.

Şu anda yerel oynatıcı, yerel yayınlama durumuyla ilgili hiçbir bilgiye sahip olmadığı için her zaman yerel oynatma durumundadır. Cast çerçevesinde gerçekleşen durum geçişlerine göre kullanıcı arayüzünü 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çmemiz gerekir. Bu sorunu çözmek için Cast çerçevesinin oluşturduğu çeşitli etkinlikleri dinlememiz gerekir.

Yayınlama oturumu yönetimi

Yayın çerçevesi için Yayın oturumu, bir cihaza bağlanma, başlama (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 kontrol kanalı, Yayın çerçevesinin alıcı medya oynatıcıdan mesaj gönderip almasını sağlar.

Kullanıcı, Yayınla düğmesini kullanarak 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ınlama oturumları GCKSessionManager tarafından yönetilir. Bu uygulamaya GCKCastContext.sharedInstance().sessionManager üzerinden erişilebilir. GCKSessionManagerListener geri çağırmaları; oluşturma, askıya alma, devam ettirme ve fesih gibi oturum etkinliklerini izlemek için kullanılabilir.

Öncelikle oturum işleyicimizi kaydetmemiz ve bazı değişkenler 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 olarak, Cast cihazına bağlanıldığında veya bağlantı kesildiğinde yerel oynatıcıya geçebilmemiz için bilgilendirilmek isteriz. Bağlantının kesintiye uğramasının nedeni yalnızca mobil cihazınızda çalışan uygulamanızın örneği değil, farklı bir mobil cihazda çalışan başka bir uygulamanızın (veya başka bir) örneği tarafından da kesintiye uğratabileceğidir.

Şu anda etkin olan oturuma GCKCastContext.sharedInstance().sessionManager.currentCastSession olarak erişilebilir. Oturumlar, Yayın iletişim kutularındaki kullanıcı hareketlerine yanıt olarak otomatik olarak oluşturulur ve silinir.

Medya yükleniyor

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.

Şu anda seçili videoyu alıcıya yüklemek için MediaViewController.swift koduna 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, uzaktan oynatmayı desteklemek üzere Yayın Oturumu mantığını kullanmak için çeşitli mevcut 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 video oynatmaya başlayın. Video, alıcıda oynatılıyor.

7. Mini kumanda

Yayın Tasarımı Denetim Listesi, kullanıcı geçerli içerik sayfasından ayrıldığında tüm Yayın uygulamalarının görünmesi için mini denetleyici sağlamasını gerektirir. Mini kumanda, geçerli 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 ve mini kumandaya odaklanan bir iPhone'un alt kısmını gösteren 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 denetleyiciyi sarmalayan ve alt kısmına GCKUIMiniMediaControlsViewController ekleyen GCKUICastContainerViewController aracını kullanacağız.

AppDelegate.swift dosyasını değiştirin ve if useCastContainerViewController koşulu için aşağıdaki kodu aşağıdaki yönteme 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 set/getter özelliğini 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. Göz atma etkinliği ve 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 amaçlı yer paylaşımı

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

CastVideos uygulamasını çalıştıran, Yayınla düğmesinin yer aldığı, Yayınla düğmesinin vurgulandığı ve "Medyayı TV'nize ve Hoparlörlerinize yayınlamak için dokunun" mesajının gösterildiği bir iPhone görseli

GCKCastContext sınıfında, presentCastInstructionsViewControllerOnce düğmesi, kullanıcılara ilk kez gösterilirken Yayınla düğmesini vurgulamak için kullanılabilecek bir yöntem vardır. MediaViewController.swift ve MediaTableViewController.swift konumlarına ş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 yer paylaşımlı tanıtım gösterilir.

9. Genişletilmiş kumanda

Google Cast tasarım kontrol listesi, bir gönderen uygulamasını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 ve alt tarafta genişletilmiş kumandanın bulunduğu bir iPhone'u gösteren görsel.

Genişletilmiş kumanda, uzaktan medya oynatımı üzerinde tam kontrol sunan bir tam ekran görünümüdür. Bu görünüm, alıcı ses denetimi ve oturum yaşam döngüsü (bağlantıyı bağlama/yayınlamayı durdurma) hariç olmak üzere, bir yayın uygulamasının bir yayın oturumunun her yönetilebilir özelliğini yönetmesine izin vermelidir. 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şlevleri GCKUIExpandedMediaControlsViewController sınıfı tarafından uygulanır.

Yapmanız gereken ilk şey, yayınlama bağlamında varsayılan genişletilmiş kumandayı etkinleştirmektir. Varsayılan genişletilmiş denetleyiciyi etkinleştirmek için AppDelegate.swift anahtarını 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 şu kodu ekleyin:

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

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

Uygulamayı çalıştırın ve video yayınlayın. Genişletilmiş kumandayı göreceksiniz. 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ına olanak tanır. Cast Connect, Android yayın alıcınız gibi davranan Cast altyapısına dayanır.

Bağımlılıklar

Podfile cihazınızdan, google-cast-sdk özelliğinin aşağıda belirtilen 4.4.8 veya daha yüksek bir sürüme 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ısı 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ı belirler ve GCKCastContext.setSharedInstanceWith kullanılarak paylaşılan örnekte ayarlanan GCKCastOptions öğesine iletilir.

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 Bilgileri

Gönderen tarafta, oturuma kimlerin katılacağını temsil etmek için GCKCredentialsData değerini belirtebilirsiniz. credentials, ATV uygulamanız tarafından anlaşılabildiği sürece kullanıcı tarafından tanımlanabilen bir dizedir. GCKCredentialsData yalnızca Android TV uygulamanıza lansman veya katılma sırasında iletilir. Bağlıyken bu ayarı tekrar yaparsanız Android TV uygulamanıza iletilmez.

Lansman Kimlik Bilgilerinin ayarlanabilmesi için GCKCredentialsData, GCKLaunchOptions ayarlandıktan sonra her zaman tanımlanmalıdır. Bunu göstermek için, oturum kurulduğunda iletilecek 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
...

SDK'nız, gönderenin yayınladığı alıcı uygulamasına bağlı olarak yukarıdaki kimlik bilgilerini devam eden oturuma otomatik olarak uygular.

Cast Connect testi

Google TV'li Chromecast'e Android TV APK'sını 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ı) bölümünde kullanılabilir. Sağ tarafta ayrıntıları ve cihazınızın ağdaki IP'sini gösterir.
  2. Terminali 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 uygulama görebilirsiniz.
  2. İşlem tamamlandığında uygulamayı bir emülatörde veya mobil cihazda derleyip çalıştırın. Android TV cihazınızla bir yayın oturumu oluşturduğunuzda, Android TV'nizde Android Receiver uygulamasını başlatır. iOS mobil göndereninizden bir video oynatırken, videoyu Android Alıcı'da 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ğıdaki kısmı 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. Örnek olarak, simge ton rengini değiştirelim.

styler.castViews.iconTintColor = .lightGray

Gerekirse varsayılan olarak her ekran için geçersiz kılabilirsiniz. Örneğin, simge ton rengi için LightGrayColor değerini yalnızca genişletilmiş medya denetleyicisinde geçersiz kılmak için.

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

Renkler değiştiriliyor

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, tüm Cast Uygulama Çerçevesi tarafından sağlanan görünümler için arka plan rengini maviye 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 bunları şekillendirmek 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ı değiştiriliyor

Kullanıcı Arayüzü Görüntüleme Protokolü'nü kullanarak Yayın Widget'larını da tema haline getirebilirsiniz. GCKUICastButton, gösterildiği tüm görünümlerde aşağıdaki kodla açıklanmaktadır:

GCKUICastButton.appearance().tintColor = UIColor.gray

12. Tebrikler

Artık iOS'te Yayın SDK widget'larını kullanarak video uygulamalarını nasıl etkinleştireceğinizi biliyorsunuz.

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