Cast in iOS-App einbinden

In diesem Entwicklerleitfaden wird beschrieben, wie Sie die Google Cast-Unterstützung auf Ihrem iOS-Gerät einrichten. die das iOS Sender SDK verwendet.

Das Mobilgerät oder der Laptop ist der Sender, der die Wiedergabe steuert. Das Google Cast-Gerät ist der Empfänger, mit dem die Inhalte auf dem Fernseher wiedergegeben werden.

Das Absender-Framework bezieht sich auf das Binärprogramm der Cast-Klassenbibliothek und die zugehörigen Ressourcen, die zur Laufzeit auf dem Absender vorhanden sind. Die Absender-App oder die Cast App bezieht sich auf eine App, die auch auf dem Absender ausgeführt wird. Web Receiver App bezieht sich auf die HTML-Anwendung, die auf Web Receiver ausgeführt wird.

Das Absender-Framework nutzt ein asynchrones Callback-Design, um den Absender zu informieren. App für Ereignisse und den Wechsel zwischen verschiedenen Stadien der Cast App. Zyklus.

Anwendungsfluss

In den folgenden Schritten wird der typische allgemeine Ausführungsablauf für einen Absender beschrieben iOS-App:

  • Das Cast-Framework beginnt, GCKDiscoveryManager basierend auf den Eigenschaften in GCKCastOptions bis mit der Suche nach Geräten beginnen.
  • Wenn der Nutzer auf das Cast-Symbol klickt, zeigt das Framework das Cast-Symbol mit der Liste der gefundenen Übertragungsgeräte.
  • Wenn der Nutzer ein Übertragungsgerät auswählt, versucht das Framework, die Web Receiver auf dem Übertragungsgerät.
  • Das Framework ruft Callbacks in der Absender-App auf, um zu bestätigen, dass der Web Receiver-App wurde gestartet.
  • Das Framework schafft einen Kommunikationskanal zwischen Sender und Web Receiver-Apps.
  • Das Framework nutzt den Kommunikationskanal, um Medien zu laden und zu steuern auf dem Web Receiver wiedergegeben werden.
  • Das Framework synchronisiert den Status der Medienwiedergabe zwischen Absender und Web Receiver: Wenn der Nutzer UI-Aktionen für Absender durchführt, wird das Framework übergeben. Mediensteuerungsanfragen an den Web Receiver gesendet werden, Medienstatusaktualisierungen sendet, aktualisiert das Framework den Status der Absender-UI.
  • Wenn der Nutzer auf das Cast-Symbol klickt, um die Verbindung zum Übertragungsgerät zu trennen, trennt das Framework die Absender-App vom Web Receiver.

Um Fehler beim Absender zu beheben, müssen Sie die Protokollierung aktivieren.

Für eine umfassende Liste aller Klassen, Methoden und Ereignisse in Google Cast iOS-Framework, siehe Google Cast iOS API Referenz. In den folgenden Abschnitten werden die einzelnen Schritte zur Integration von Cast in Ihre iOS-App.

Aufrufmethoden aus dem Hauptthread

Cast-Kontext initialisieren

Das Cast-Framework hat ein globales Singleton-Objekt, das GCKCastContext, die koordiniert alle Aktivitäten des Frameworks. Dieses Objekt muss initialisiert werden im Lebenszyklus der Anwendung, in der Regel -[application:didFinishLaunchingWithOptions:] des App-Delegaten, sodass dass die automatische Wiederaufnahme der Sitzung beim Neustart der App des Absenders korrekt ausgelöst werden kann.

GCKCastOptions -Objekt muss beim Initialisieren von GCKCastContext angegeben werden. Diese Klasse enthält Optionen, die das Verhalten des Frameworks beeinflussen. Die meisten wichtig ist die Web Receiver-Anwendungs-ID, die zum Filtern und die Web Receiver App zu starten, wenn ein Stream läuft begonnen.

Auch die Methode -[application:didFinishLaunchingWithOptions:] eignet sich gut. um einen Logging-Delegaten einzurichten, der die Logging-Nachrichten vom Framework empfangen soll. Diese können bei der Fehlersuche und Fehlerbehebung hilfreich sein.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate {
  let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID
  let kDebugLoggingEnabled = true

  var window: UIWindow?

  func applicationDidFinishLaunching(_ application: UIApplication) {
    let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID)
    let options = GCKCastOptions(discoveryCriteria: criteria)
    GCKCastContext.setSharedInstanceWith(options)

    // Enable logger.
    GCKLogger.sharedInstance().delegate = self

    ...
  }

  // MARK: - GCKLoggerDelegate

  func logMessage(_ message: String,
                  at level: GCKLoggerLevel,
                  fromFunction function: String,
                  location: String) {
    if (kDebugLoggingEnabled) {
      print(function + " - " + message)
    }
  }
}
<ph type="x-smartling-placeholder">
</ph>
Objective-C

AppDelegate.h

@interface AppDelegate () <GCKLoggerDelegate>
@end

AppDelegate.m

@implementation AppDelegate

static NSString *const kReceiverAppID = @"AABBCCDD";
static const BOOL kDebugLoggingEnabled = YES;

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc]
                                    initWithApplicationID:kReceiverAppID];
  GCKCastOptions *options = [[GCKCastOptions alloc] initWithDiscoveryCriteria:criteria];
  [GCKCastContext setSharedInstanceWithOptions:options];

  // Enable logger.
  [GCKLogger sharedInstance].delegate = self;

  ...

  return YES;
}

...

#pragma mark - GCKLoggerDelegate

- (void)logMessage:(NSString *)message
           atLevel:(GCKLoggerLevel)level
      fromFunction:(NSString *)function
          location:(NSString *)location {
  if (kDebugLoggingEnabled) {
    NSLog(@"%@ - %@, %@", function, message, location);
  }
}

@end

Die Cast UX-Widgets

Das Cast iOS SDK stellt diese Widgets bereit, die dem Cast-Design entsprechen. Checkliste:

  • Einführendes Overlay: Die Klasse GCKCastContext hat eine Methode, presentCastInstructionsViewControllerOnceWithCastButton Damit wird das Cast-Symbol beim ersten Webempfänger hervorgehoben. verfügbar ist. Die Absender-App kann den Text und die Position des Titels anpassen und die Schaltfläche „Schließen“.

  • Cast-Symbol: Ab Version 4.6.0 des Cast iOS Sender SDK ist das Cast-Symbol immer sichtbar wenn das Absendergerät mit dem WLAN verbunden ist. Wenn die Nutzenden zum ersten Mal Nach dem ersten Start der App erscheint auf dem Cast-Symbol ein Berechtigungsdialogfeld. damit der Nutzer der App lokalen Netzwerkzugriff auf Geräte auf Netzwerk. Wenn der Nutzer anschließend auf das Cast-Symbol tippt, wird eine Übertragung wird angezeigt, in dem die erkannten Geräte aufgeführt sind. Wenn Nutzende auf über das Cast-Symbol, während das Gerät verbunden ist, wird die aktuelle Medienmetadaten (z. B. Titel, Name des Tonstudios und ein Thumbnail) Bild) oder ermöglicht dem Nutzer, die Verbindung zum Übertragungsgerät zu trennen. Wenn Nutzende auf das Cast-Symbol tippt, während keine Geräte verfügbar sind, oder ein Bildschirm wird angezeigt und der Nutzer wird darüber informiert, warum Geräte nicht gefunden wurden. und zur Fehlerbehebung.

  • Mini-Controller: Wenn der Nutzer Inhalte streamt und die aktuelle Seite verlassen hat Inhaltsseite oder maximierter Controller auf einen anderen Bildschirm in der Sender-App, wird unten auf dem Bildschirm angezeigt, die gerade gestreamten Medienmetadaten abrufen und die Wiedergabe steuern können.

  • Erweiterter Controller: Wenn der Nutzer Inhalte streamt, klickt er auf die Medienbenachrichtigung oder wird der erweiterte Controller gestartet, der die die gerade Medienmetadaten wiedergeben, und bietet mehrere Schaltflächen zum Steuern der Medienwiedergabe.

Cast-Symbol hinzufügen

Das Framework stellt eine Komponente für das Cast-Symbol als abgeleitete UIButton-Klasse bereit. Es kann kann der Titelleiste der App hinzugefügt werden, indem er sie in ein UIBarButtonItem setzt. Ein typisches So kann die abgeleitete UIViewController-Klasse ein Cast-Symbol installieren:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
let castButton = GCKUICastButton(frame: CGRect(x: 0, y: 0, width: 24, height: 24))
castButton.tintColor = UIColor.gray
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: castButton)
<ph type="x-smartling-placeholder">
</ph>
Objective-C
GCKUICastButton *castButton = [[GCKUICastButton alloc] initWithFrame:CGRectMake(0, 0, 24, 24)];
castButton.tintColor = [UIColor grayColor];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:castButton];

Wenn Sie auf die Schaltfläche tippen, wird standardmäßig das Cast-Dialogfeld geöffnet, das vom Framework.

GCKUICastButton können auch direkt zum Storyboard hinzugefügt werden.

Geräteerkennung konfigurieren

Im Framework erfolgt die Geräteerkennung automatisch. Es ist nicht nötig, den Erkennungsprozess explizit starten oder anhalten, es sei denn, Sie implementieren eine benutzerdefinierte UI.

Die Erkennung im Framework wird von der Klasse verwaltet GCKDiscoveryManager, das eine Eigenschaft des GCKCastContext Die bietet eine standardmäßige Cast-Dialogkomponente für die Geräteauswahl und Steuerung. Die Geräteliste ist lexikografisch nach dem für das Gerät angezeigten Namen geordnet.

Funktionsweise der Sitzungsverwaltung

Mit dem Cast SDK wird das Konzept einer Cast-Sitzung eingeführt. Einrichtung, die die Schritte zum Herstellen einer Verbindung mit einem Gerät, dem Starten (oder dem Beitritt) zu einem Web umfasst Receiver-App, die eine Verbindung zu dieser App herstellt und ein Mediensteuerungskanal initialisiert wird. Web Receiver anzeigen Leitfaden zum Lebenszyklus von Anwendungen finden Sie weitere Informationen zu Übertragungssitzungen und zum Lebenszyklus des Web-Receivers.

Sitzungen werden vom Kurs verwaltet GCKSessionManager, das eine Eigenschaft des GCKCastContext Einzelne Sitzungen werden durch Unterklassen der Klasse dargestellt. GCKSession: z. B. GCKCastSession Sitzungen mit Übertragungsgeräten. Du kannst auf das derzeit aktive Streaming zugreifen Sitzung (falls vorhanden) als currentCastSession-Property von GCKSessionManager.

Die GCKSessionManagerListener können Sie Sitzungsereignisse überwachen, z. B. Sitzungserstellung, Sperrung, Wiederaufnahme und Kündigung. Das Framework sperrt automatisch Sitzungen, bei denen die Sender-App in den Hintergrund wechselt und versucht, sie fortzusetzen wenn die App in den Vordergrund zurückkehrt (oder erneut gestartet wird, nachdem abnormale/abrupte Beendigung einer App während einer aktiven Sitzung).

Wenn das Dialogfeld „Streamen“ verwendet wird, werden Sitzungen erstellt und gelöscht. automatisch auf Gesten reagieren. Andernfalls kann die App Sitzungen explizit über Methoden auf GCKSessionManager

Ob die Anwendung als Reaktion auf den Sitzungslebenszyklus eine spezielle Verarbeitung durchführen muss kann es eine oder mehrere GCKSessionManagerListener-Instanzen mit GCKSessionManager. GCKSessionManagerListener ist ein Protokoll, mit dem Callbacks für Ereignisse wie Sitzungsbeginn und ‐ende an.

Stream-Übertragung

Die Beibehaltung des Sitzungsstatus ist die Grundlage der Streamübertragung. können Nutzer vorhandene Audio- und Videostreams per Sprachbefehl, über Google Home eine App oder ein Smart Display verwenden. Die Medienwiedergabe wird auf einem Gerät (Quelle) gestoppt und auf einem anderen fortgesetzt (das Ziel). Jedes Übertragungsgerät mit der neuesten Firmware kann als Quelle oder Ziel in einem Streamübertragung.

Um während der Stream-Übertragung das neue Zielgerät abzurufen, verwende die GCKCastSession#device Property während des [sessionManager:didResumeCastSession:] Callback des Nutzers an.

Weitere Informationen finden Sie unter Stream-Übertragung mit Web Receiver .

Automatische Wiederherstellung der Verbindung

Das Cast-Framework fügt Logik zum erneuten Verbindungsaufbau hinzu, um die erneute Verbindung automatisch zu verarbeiten. in vielen subtilen Sonderfällen, wie z. B.:

  • Wiederherstellung nach einem vorübergehenden WLAN-Ausfall
  • Aus Geräte-Ruhemodus wiederherstellen
  • Nach Hintergrundwiedergabe wiederherstellen
  • Wiederherstellung nach einem Absturz der App

So funktioniert die Mediensteuerung

Wenn das Streamen mit einer Web Receiver-App eingerichtet wird, die diese Medien unterstützt Namespace, eine Instanz von GCKRemoteMediaClient werden automatisch vom Framework erstellt. ist der Zugriff als remoteMediaClient-Eigenschaft des GCKCastSession Instanz.

Alle Methoden unter GCKRemoteMediaClient, die Anfragen an den Web Receiver senden wird ein Objekt GCKRequest, das kann verwendet werden, um diese Anfrage zu verfolgen. A GCKRequestDelegate kann diesem Objekt zugewiesen werden, um Benachrichtigungen Ergebnis des Vorgangs.

Es wird erwartet, dass die Instanz von GCKRemoteMediaClient kann von mehreren Teilen der App und einigen internen Komponenten gemeinsam genutzt werden. des Frameworks wie dem Cast-Dialogfeld und der Mini-Mediensteuerung teilen sich Instanz. Aus diesem Grund GCKRemoteMediaClient unterstützt die Registrierung mehrerer GCKRemoteMediaClientListener.

Medienmetadaten festlegen

Die GCKMediaMetadata stellt Informationen zu einem Medienelement dar, das Sie streamen möchten. Die folgenden erstellt eine neue GCKMediaMetadata-Instanz eines Films und legt den Titel fest, Untertitel, den Namen des Aufnahmestudios und zwei Bilder.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
let metadata = GCKMediaMetadata()
metadata.setString("Big Buck Bunny (2008)", forKey: kGCKMetadataKeyTitle)
metadata.setString("Big Buck Bunny tells the story of a giant rabbit with a heart bigger than " +
  "himself. When one sunny day three rodents rudely harass him, something " +
  "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon " +
  "tradition he prepares the nasty rodents a comical revenge.",
                   forKey: kGCKMetadataKeySubtitle)
metadata.addImage(GCKImage(url: URL(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg")!,
                           width: 480,
                           height: 360))
<ph type="x-smartling-placeholder">
</ph>
Objective-C
GCKMediaMetadata *metadata = [[GCKMediaMetadata alloc]
                                initWithMetadataType:GCKMediaMetadataTypeMovie];
[metadata setString:@"Big Buck Bunny (2008)" forKey:kGCKMetadataKeyTitle];
[metadata setString:@"Big Buck Bunny tells the story of a giant rabbit with a heart bigger than "
 "himself. When one sunny day three rodents rudely harass him, something "
 "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon "
 "tradition he prepares the nasty rodents a comical revenge."
             forKey:kGCKMetadataKeySubtitle];
[metadata addImage:[[GCKImage alloc]
                    initWithURL:[[NSURL alloc] initWithString:@"https://commondatastorage.googleapis.com/"
                                 "gtv-videos-bucket/sample/images/BigBuckBunny.jpg"]
                    width:480
                    height:360]];

Weitere Informationen finden Sie im Abschnitt zur Bildauswahl und Caching zur Verwendung von Bildern mit Medienmetadaten.

Medien laden

Um ein Medienelement zu laden, erstellen Sie ein GCKMediaInformation -Instanz mithilfe der Metadaten der Medien. Rufen Sie dann den aktuellen GCKCastSession und verwenden Sie GCKRemoteMediaClient um die Medien in die Empfänger-App zu laden. Sie können dann GCKRemoteMediaClient verwenden. zur Steuerung einer auf dem Empfänger ausgeführten Mediaplayer-App, anhalten und stoppen.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
let url = URL.init(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
guard let mediaURL = url else {
  print("invalid mediaURL")
  return
}

let mediaInfoBuilder = GCKMediaInformationBuilder.init(contentURL: mediaURL)
mediaInfoBuilder.streamType = GCKMediaStreamType.none;
mediaInfoBuilder.contentType = "video/mp4"
mediaInfoBuilder.metadata = metadata;
mediaInformation = mediaInfoBuilder.build()

guard let mediaInfo = mediaInformation else {
  print("invalid mediaInformation")
  return
}

if let request = sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInfo) {
  request.delegate = self
}
<ph type="x-smartling-placeholder">
</ph>
Objective-C
GCKMediaInformationBuilder *mediaInfoBuilder =
  [[GCKMediaInformationBuilder alloc] initWithContentURL:
   [NSURL URLWithString:@"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"]];
mediaInfoBuilder.streamType = GCKMediaStreamTypeNone;
mediaInfoBuilder.contentType = @"video/mp4";
mediaInfoBuilder.metadata = metadata;
self.mediaInformation = [mediaInfoBuilder build];

GCKRequest *request = [self.sessionManager.currentSession.remoteMediaClient loadMedia:self.mediaInformation];
if (request != nil) {
  request.delegate = self;
}

Weitere Informationen finden Sie im Abschnitt mit Media-Tracks.

4K-Videoformat

Um das Videoformat deiner Medien zu bestimmen, verwende das Attribut videoInfo von GCKMediaStatus um die aktuelle Instanz von GCKVideoInfo Diese Instanz enthält den Typ des HDR TV-Formats sowie die Höhe und Breite in Pixel. Varianten des 4K-Formats sind im Attribut hdrType durch enum angegeben Werte GCKVideoInfoHDRType.

Mini-Controller hinzufügen

Gemäß dem Cast-Design Checkliste, sollte eine Absender-App eine dauerhafte Steuerung bieten, die sogenannte Miniversion. Controller die angezeigt werden sollte, wenn der Nutzer die aktuelle Inhaltsseite verlässt. Der Mini-Controller ermöglicht sofortigen Zugriff und eine sichtbare Erinnerung für den aktuelle Streamsitzung.

Das Cast-Framework bietet eine Steuerleiste, GCKUIMiniMediaControlsViewController, das zu den Szenen hinzugefügt werden kann, in denen du den Mini-Controller zeigen möchtest.

Wenn die Sender-App einen Video- oder Audio-Livestream wiedergibt, gibt das SDK zeigt automatisch eine Wiedergabe-/Stopp-Schaltfläche anstelle der Wiedergabe-/Pause-Schaltfläche an. im Mini-Controller.

Unter iOS-Sender-UI anpassen finden Sie Informationen zur Absender-App die Darstellung der Cast-Widgets konfigurieren kann.

Es gibt zwei Möglichkeiten, den Mini-Controller einer Sender-App hinzuzufügen:

  • Das Layout des Mini-Controllers lässt sich mit dem Cast Framework verwalten, mit einem eigenen Ansichts-Controller.
  • Sie können das Layout des Mini-Controller-Widgets selbst verwalten, indem Sie es Ihrer vorhandenen View-Controller erstellen, indem Sie im Storyboard eine Unteransicht bereitstellen.

Wrapping mit GCKUICastContainerViewController

Die erste Möglichkeit besteht darin, GCKUICastContainerViewController das einen weiteren Ansichts-Controller umschließt und ein GCKUIMiniMediaControlsViewController . Dieser Ansatz ist insofern eingeschränkt, als Sie das Attribut Animation und kann das Verhalten des Containeransicht-Controllers nicht konfigurieren.

Diese erste Methode wird in der Regel -[application:didFinishLaunchingWithOptions:]-Methode des Anwendungsdelegats:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
func applicationDidFinishLaunching(_ application: UIApplication) {
  ...

  // Wrap main view in the GCKUICastContainerViewController and display the mini controller.
  let appStoryboard = UIStoryboard(name: "Main", bundle: nil)
  let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation")
  let castContainerVC =
          GCKCastContext.sharedInstance().createCastContainerController(for: navigationController)
  castContainerVC.miniMediaControlsItemEnabled = true
  window = UIWindow(frame: UIScreen.main.bounds)
  window!.rootViewController = castContainerVC
  window!.makeKeyAndVisible()

  ...
}
<ph type="x-smartling-placeholder">
</ph>
Objective-C
- (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  ...

  // Wrap main view in the GCKUICastContainerViewController and display the mini controller.
  UIStoryboard *appStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
  UINavigationController *navigationController =
          [appStoryboard instantiateViewControllerWithIdentifier:@"MainNavigation"];
  GCKUICastContainerViewController *castContainerVC =
          [[GCKCastContext sharedInstance] createCastContainerControllerForViewController:navigationController];
  castContainerVC.miniMediaControlsItemEnabled = YES;
  self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
  self.window.rootViewController = castContainerVC;
  [self.window makeKeyAndVisible];
  ...

}
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
var castControlBarsEnabled: Bool {
  set(enabled) {
    if let castContainerVC = self.window?.rootViewController as? GCKUICastContainerViewController {
      castContainerVC.miniMediaControlsItemEnabled = enabled
    } else {
      print("GCKUICastContainerViewController is not correctly configured")
    }
  }
  get {
    if let castContainerVC = self.window?.rootViewController as? GCKUICastContainerViewController {
      return castContainerVC.miniMediaControlsItemEnabled
    } else {
      print("GCKUICastContainerViewController is not correctly configured")
      return false
    }
  }
}
<ph type="x-smartling-placeholder">
</ph>
Objective-C

AppDelegate.h

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, assign) BOOL castControlBarsEnabled;

@end

AppDelegate.m

@implementation AppDelegate

...

- (void)setCastControlBarsEnabled:(BOOL)notificationsEnabled {
  GCKUICastContainerViewController *castContainerVC;
  castContainerVC =
      (GCKUICastContainerViewController *)self.window.rootViewController;
  castContainerVC.miniMediaControlsItemEnabled = notificationsEnabled;
}

- (BOOL)castControlBarsEnabled {
  GCKUICastContainerViewController *castContainerVC;
  castContainerVC =
      (GCKUICastContainerViewController *)self.window.rootViewController;
  return castContainerVC.miniMediaControlsItemEnabled;
}

...

@end

In vorhandenen Ansichts-Controller einbetten

Die zweite Möglichkeit besteht darin, den Mini-Controller direkt zu Ihrer vorhandenen Ansicht hinzuzufügen. für die Steuerung durch createMiniMediaControlsViewController zum Erstellen eines GCKUIMiniMediaControlsViewController und fügen sie dann als untergeordnete Ansicht zum Controller der Containeransicht hinzu.

Richten Sie den Ansichts-Controller im App-Delegaten ein:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  ...

  GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true
  window?.clipsToBounds = true

  let rootContainerVC = (window?.rootViewController as? RootContainerViewController)
  rootContainerVC?.miniMediaControlsViewEnabled = true

  ...

  return true
}
<ph type="x-smartling-placeholder">
</ph>
Objective-C
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  ...

  [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES;

  self.window.clipsToBounds = YES;

  RootContainerViewController *rootContainerVC;
  rootContainerVC =
      (RootContainerViewController *)self.window.rootViewController;
  rootContainerVC.miniMediaControlsViewEnabled = YES;

  ...

  return YES;
}

Erstellen Sie in Ihrem Root View Controller einen GCKUIMiniMediaControlsViewController. und fügen Sie sie dem Container View Controller als untergeordnete Ansicht hinzu:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
let kCastControlBarsAnimationDuration: TimeInterval = 0.20

@objc(RootContainerViewController)
class RootContainerViewController: UIViewController, GCKUIMiniMediaControlsViewControllerDelegate {
  @IBOutlet weak private var _miniMediaControlsContainerView: UIView!
  @IBOutlet weak private var _miniMediaControlsHeightConstraint: NSLayoutConstraint!
  private var miniMediaControlsViewController: GCKUIMiniMediaControlsViewController!
  var miniMediaControlsViewEnabled = false {
    didSet {
      if self.isViewLoaded {
        self.updateControlBarsVisibility()
      }
    }
  }

  var overriddenNavigationController: UINavigationController?

  override var navigationController: UINavigationController? {

    get {
      return overriddenNavigationController
    }

    set {
      overriddenNavigationController = newValue
    }
  }
  var miniMediaControlsItemEnabled = false

  override func viewDidLoad() {
    super.viewDidLoad()
    let castContext = GCKCastContext.sharedInstance()
    self.miniMediaControlsViewController = castContext.createMiniMediaControlsViewController()
    self.miniMediaControlsViewController.delegate = self
    self.updateControlBarsVisibility()
    self.installViewController(self.miniMediaControlsViewController,
                               inContainerView: self._miniMediaControlsContainerView)
  }

  func updateControlBarsVisibility() {
    if self.miniMediaControlsViewEnabled && self.miniMediaControlsViewController.active {
      self._miniMediaControlsHeightConstraint.constant = self.miniMediaControlsViewController.minHeight
      self.view.bringSubview(toFront: self._miniMediaControlsContainerView)
    } else {
      self._miniMediaControlsHeightConstraint.constant = 0
    }
    UIView.animate(withDuration: kCastControlBarsAnimationDuration, animations: {() -> Void in
      self.view.layoutIfNeeded()
    })
    self.view.setNeedsLayout()
  }

  func installViewController(_ viewController: UIViewController?, inContainerView containerView: UIView) {
    if let viewController = viewController {
      self.addChildViewController(viewController)
      viewController.view.frame = containerView.bounds
      containerView.addSubview(viewController.view)
      viewController.didMove(toParentViewController: self)
    }
  }

  func uninstallViewController(_ viewController: UIViewController) {
    viewController.willMove(toParentViewController: nil)
    viewController.view.removeFromSuperview()
    viewController.removeFromParentViewController()
  }

  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "NavigationVCEmbedSegue" {
      self.navigationController = (segue.destination as? UINavigationController)
    }
  }

...
<ph type="x-smartling-placeholder">
</ph>
Objective-C

RootContainerViewController.h

static const NSTimeInterval kCastControlBarsAnimationDuration = 0.20;

@interface RootContainerViewController () <GCKUIMiniMediaControlsViewControllerDelegate> {
  __weak IBOutlet UIView *_miniMediaControlsContainerView;
  __weak IBOutlet NSLayoutConstraint *_miniMediaControlsHeightConstraint;
  GCKUIMiniMediaControlsViewController *_miniMediaControlsViewController;
}

@property(nonatomic, weak, readwrite) UINavigationController *navigationController;

@property(nonatomic, assign, readwrite) BOOL miniMediaControlsViewEnabled;
@property(nonatomic, assign, readwrite) BOOL miniMediaControlsItemEnabled;

@end

RootContainerViewController.m

@implementation RootContainerViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  GCKCastContext *castContext = [GCKCastContext sharedInstance];
  _miniMediaControlsViewController =
      [castContext createMiniMediaControlsViewController];
  _miniMediaControlsViewController.delegate = self;

  [self updateControlBarsVisibility];
  [self installViewController:_miniMediaControlsViewController
              inContainerView:_miniMediaControlsContainerView];
}

- (void)setMiniMediaControlsViewEnabled:(BOOL)miniMediaControlsViewEnabled {
  _miniMediaControlsViewEnabled = miniMediaControlsViewEnabled;
  if (self.isViewLoaded) {
    [self updateControlBarsVisibility];
  }
}

- (void)updateControlBarsVisibility {
  if (self.miniMediaControlsViewEnabled &&
      _miniMediaControlsViewController.active) {
    _miniMediaControlsHeightConstraint.constant =
        _miniMediaControlsViewController.minHeight;
    [self.view bringSubviewToFront:_miniMediaControlsContainerView];
  } else {
    _miniMediaControlsHeightConstraint.constant = 0;
  }
  [UIView animateWithDuration:kCastControlBarsAnimationDuration
                   animations:^{
                     [self.view layoutIfNeeded];
                   }];
  [self.view setNeedsLayout];
}

- (void)installViewController:(UIViewController *)viewController
              inContainerView:(UIView *)containerView {
  if (viewController) {
    [self addChildViewController:viewController];
    viewController.view.frame = containerView.bounds;
    [containerView addSubview:viewController.view];
    [viewController didMoveToParentViewController:self];
  }
}

- (void)uninstallViewController:(UIViewController *)viewController {
  [viewController willMoveToParentViewController:nil];
  [viewController.view removeFromSuperview];
  [viewController removeFromParentViewController];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  if ([segue.identifier isEqualToString:@"NavigationVCEmbedSegue"]) {
    self.navigationController =
        (UINavigationController *)segue.destinationViewController;
  }
}

...

@end

Die GCKUIMiniMediaControlsViewControllerDelegate teilt dem Host View Controller mit, wann der Mini-Controller sichtbar sein soll:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
  func miniMediaControlsViewController(_: GCKUIMiniMediaControlsViewController,
                                       shouldAppear _: Bool) {
    updateControlBarsVisibility()
  }
<ph type="x-smartling-placeholder">
</ph>
Objective-C
- (void)miniMediaControlsViewController:
            (GCKUIMiniMediaControlsViewController *)miniMediaControlsViewController
                           shouldAppear:(BOOL)shouldAppear {
  [self updateControlBarsVisibility];
}

Maximierten Controller hinzufügen

Die Checkliste für das Google Cast-Design setzt voraus, dass eine Absender-App eine maximierte Controller für die gestreamten Medien. Der erweiterte Controller ist eine Vollbildversion von den Mini-Controller.

Der erweiterte Controller ermöglicht eine Vollbildansicht mit vollständiger Steuerung des für die Remote-Medienwiedergabe. Diese Ansicht sollte es einer Streaming-App ermöglichen, alle überschaubarer Aspekt einer Übertragungssitzung, mit Ausnahme der Web Receiver-Lautstärke und den Sitzungslebenszyklus (Verbindung verbinden/beenden). Außerdem bietet es alle Statusinformationen zur Mediensitzung (Artwork, Titel, Untertitel usw.) weiter).

Die Funktionalität dieser Ansicht wird durch den GCKUIExpandedMediaControlsViewController .

Zunächst musst du den erweiterten Standard-Controller in der Kontext zu streamen. Ändern Sie den App-Delegaten, um den standardmäßigen erweiterten Controller zu aktivieren:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
func applicationDidFinishLaunching(_ application: UIApplication) {
  ..

  GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true

  ...
}
<ph type="x-smartling-placeholder">
</ph>
Objective-C
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  ...

  [GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES;

  ..
}

Fügen Sie dem Ansichts-Controller den folgenden Code hinzu, um den erweiterten Controller zu laden Der Nutzer beginnt mit dem Streamen eines Videos:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
func playSelectedItemRemotely() {
  GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls()

  ...

  // Load your media
  sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInformation)
}
<ph type="x-smartling-placeholder">
</ph>
Objective-C
- (void)playSelectedItemRemotely {
  [[GCKCastContext sharedInstance] presentDefaultExpandedMediaControls];

  ...

  // Load your media
  [self.sessionManager.currentSession.remoteMediaClient loadMedia:mediaInformation];
}

Der erweiterte Controller wird auch automatisch gestartet, wenn der Nutzer tippt auf den Mini-Controller.

Wenn die Sender-App einen Video- oder Audio-Livestream wiedergibt, gibt das SDK zeigt automatisch eine Wiedergabe-/Stopp-Schaltfläche anstelle der Wiedergabe-/Pause-Schaltfläche an. im maximierten Controller.

Siehe Benutzerdefinierte Stile auf Ihr iOS-Gerät anwenden App , wie Ihre Absender-App das Aussehen der Cast-Widgets konfigurieren kann.

Lautstärkeregelung

Das Cast-Framework verwaltet automatisch das Volume für die Absender-App. Die wird das Framework automatisch mit dem Web Receiver-Volume für die UI-Widgets bereitstellen. Um einen von der App bereitgestellten Schieberegler zu synchronisieren, verwenden Sie GCKUIDeviceVolumeController

Lautstärkeregelung mit physischer Taste

Mit den Lautstärketasten am Sendergerät kann die Lautstärke der Übertragungssitzung auf dem Web Receiver über die physicalVolumeButtonsWillControlDeviceVolume-Flag im GCKCastOptions, die auf der GCKCastContext

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID)
let options = GCKCastOptions(discoveryCriteria: criteria)
options.physicalVolumeButtonsWillControlDeviceVolume = true
GCKCastContext.setSharedInstanceWith(options)
<ph type="x-smartling-placeholder">
</ph>
Objective-C
GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc]
                                          initWithApplicationID:kReceiverAppID];
GCKCastOptions *options = [[GCKCastOptions alloc]
                                          initWithDiscoveryCriteria :criteria];
options.physicalVolumeButtonsWillControlDeviceVolume = YES;
[GCKCastContext setSharedInstanceWithOptions:options];

Fehler verarbeiten

Absender-Apps müssen alle Fehlerrückrufe verarbeiten und entscheiden, die beste Reaktion für jede Phase des Cast-Lebenszyklus. Die App kann Folgendes anzeigen: wird dem Nutzer eine Fehlermeldung angezeigt. Andernfalls kann er das Streaming beenden.

Logging

GCKLogger ist ein Singleton-Element, das vom Framework für das Logging verwendet wird. Verwenden Sie die Methode GCKLoggerDelegate um die Verarbeitung von Logeinträgen anzupassen.

Mit dem GCKLogger erzeugt das SDK eine Logging-Ausgabe in Form von „Debug“. Meldungen, Fehler und Warnungen. Diese Logeinträge unterstützen Sie bei der Fehlerbehebung und sind nützlich zur Fehlerbehebung und Identifizierung von Problemen. Die Logausgabe ist standardmäßig aber durch Zuweisen einer GCKLoggerDelegate kann die Absender-App vom SDK aus und protokolliert sie in der Systemkonsole.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate {
  let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID
  let kDebugLoggingEnabled = true

  var window: UIWindow?

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

    // Enable logger.
    GCKLogger.sharedInstance().delegate = self

    ...
  }

  // MARK: - GCKLoggerDelegate

  func logMessage(_ message: String,
                  at level: GCKLoggerLevel,
                  fromFunction function: String,
                  location: String) {
    if (kDebugLoggingEnabled) {
      print(function + " - " + message)
    }
  }
}
<ph type="x-smartling-placeholder">
</ph>
Objective-C

AppDelegate.h

@interface AppDelegate () <GCKLoggerDelegate>
@end

AppDelegate.m

@implementation AppDelegate

static NSString *const kReceiverAppID = @"AABBCCDD";
static const BOOL kDebugLoggingEnabled = YES;

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

  // Enable logger.
  [GCKLogger sharedInstance].delegate = self;

  ...

  return YES;
}

...

#pragma mark - GCKLoggerDelegate

- (void)logMessage:(NSString *)message
           atLevel:(GCKLoggerLevel)level
      fromFunction:(NSString *)function
          location:(NSString *)location {
  if (kDebugLoggingEnabled) {
    NSLog(@"%@ - %@, %@", function, message, location);
  }
}

@end

Um auch Debug- und ausführliche Meldungen zu aktivieren, fügen Sie diese Zeile in den Code ein, Festlegen des Bevollmächtigten (siehe oben):

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
let filter = GCKLoggerFilter.init()
filter.minimumLevel = GCKLoggerLevel.verbose
GCKLogger.sharedInstance().filter = filter
<ph type="x-smartling-placeholder">
</ph>
Objective-C
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init];
[filter setMinimumLevel:GCKLoggerLevelVerbose];
[GCKLogger sharedInstance].filter = filter;

Sie können auch die von GCKLogger Legen Sie die minimale Logging-Ebene pro Klasse fest. Beispiel:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph>
Swift
let filter = GCKLoggerFilter.init()
filter.setLoggingLevel(GCKLoggerLevel.verbose, forClasses: ["GCKUICastButton",
                                                            "GCKUIImageCache",
                                                            "NSMutableDictionary"])
GCKLogger.sharedInstance().filter = filter
<ph type="x-smartling-placeholder">
</ph>
Objective-C
GCKLoggerFilter *filter = [[GCKLoggerFilter alloc] init];
[filter setLoggingLevel:GCKLoggerLevelVerbose
             forClasses:@[@"GCKUICastButton",
                          @"GCKUIImageCache",
                          @"NSMutableDictionary"
                          ]];
[GCKLogger sharedInstance].filter = filter;

Die Klassennamen können entweder Literalnamen oder glob-Muster sein, z. B. GCKUI\* und GCK\*Session.