1. Übersicht
In diesem Codelab erfahren Sie, wie Sie eine bestehende iOS-Video-App so anpassen, dass sie Inhalte auf ein für Google Cast optimiertes Gerät streamen kann.
Was ist Google Cast?
Mit Google Cast können Nutzer Inhalte von Mobilgeräten auf einen Fernseher streamen. Nutzer können dann ihr Mobilgerät als Fernbedienung für die Medienwiedergabe auf dem Fernseher verwenden.
Mit dem Google Cast SDK können Sie Ihre App so erweitern, dass sie Google Cast-fähige Geräte wie Fernseher oder Soundsysteme steuern kann. Mit dem Cast SDK können Sie die erforderlichen UI-Komponenten anhand der Checkliste für das Google Cast-Design hinzufügen.
Die Design-Checkliste für Google Cast soll die Nutzung von Cast auf allen unterstützten Plattformen einfach und vorhersehbar machen.
Ziele
Wenn Sie dieses Codelab abgeschlossen haben, haben Sie eine iOS-Video-App, mit der Sie Videos auf ein Google Cast-Gerät streamen können.
Lerninhalte
- Hinzufügen des Google Cast SDK zu einer Beispiel-Video-App
- Hier erfahren Sie, wie Sie das Cast-Symbol zur Auswahl eines Google Cast-Geräts hinzufügen.
- Verbindung zu einem Übertragungsgerät herstellen und einen Medienempfänger starten
- So streamen Sie ein Video.
- So fügen Sie Ihrer App einen Cast Mini-Controller hinzu.
- So fügst du einen erweiterten Controller hinzu.
- So erstellst du ein einführendes Overlay.
- Cast-Widgets anpassen
- Cast Connect einbinden
Voraussetzungen
- Die neueste Version von Xcode.
- Ein Mobilgerät mit iOS 9 oder höher oder der Xcode Simulator
- Ein USB-Datenkabel, um Ihr Mobilgerät mit dem Entwicklungscomputer zu verbinden (falls Sie ein Gerät verwenden).
- Ein Google Cast-Gerät wie Chromecast oder Android TV mit Internetverbindung
- Einen Fernseher oder Monitor mit HDMI-Eingang
- Für den Test der Cast Connect-Integration ist Chromecast mit Google TV erforderlich, für den Rest des Codelabs ist es optional. Falls Sie keines haben, überspringen Sie den Schritt Cast Connect-Unterstützung hinzufügen gegen Ende dieser Anleitung.
Erfahrung
- Sie müssen über Vorkenntnisse in der iOS-Entwicklung verfügen.
- Außerdem benötigen Sie Vorkenntnisse in Bezug auf Fernsehen. :)
Wie möchten Sie diese Anleitung nutzen?
Wie würden Sie Ihre Erfahrung mit der Entwicklung von iOS-Apps bewerten?
Wie würden Sie Ihre Erfahrungen mit Fernsehen bewerten?
2. Beispielcode abrufen
Sie können entweder den gesamten Beispielcode auf Ihren Computer herunterladen...
und entpacken Sie die heruntergeladene ZIP-Datei.
3. Beispiel-App ausführen
Sehen wir uns zunächst an, wie die fertige Beispiel-App aussieht. Die App ist ein einfacher Videoplayer. Der Nutzer kann ein Video aus einer Liste auswählen und es dann lokal auf dem Gerät wiedergeben oder auf ein Google Cast-Gerät streamen.
Nachdem Sie den Code heruntergeladen haben, können Sie die fertige Beispielanwendung in Xcode öffnen und ausführen. Gehen Sie dazu so vor:
Häufig gestellte Fragen
CocoaPods-Einrichtung
Wenn Sie CocoaPods einrichten möchten, öffnen Sie die Konsole und installieren Sie die Anwendung mit dem unter macOS verfügbaren Standard Ruby:
sudo gem install cocoapods
Wenn Probleme auftreten, finden Sie in der offiziellen Dokumentation Informationen zum Herunterladen und Installieren des Abhängigkeitsmanagers.
Projekt einrichten
- Rufen Sie auf Ihrem Terminal das Codelab-Verzeichnis auf.
- Installieren Sie die Abhängigkeiten aus der Podfile-Datei.
cd app-done pod update pod install
- Öffnen Sie Xcode und wählen Sie Open another project... (Weiteres Projekt öffnen...) aus.
- Wählen Sie im Ordner mit dem Beispielcode im Verzeichnis
app-done
die DateiCastVideos-ios.xcworkspace
aus.
Anwendung ausführen
Wählen Sie das Ziel und den Simulator aus und führen Sie dann die App aus:
Die Video-App sollte nach einigen Sekunden angezeigt werden.
Klicken Sie auf „Zulassen“, wenn die Benachrichtigung zum Akzeptieren eingehender Netzwerkverbindungen angezeigt wird. Das Symbol „Streamen“ wird nicht angezeigt, wenn diese Option nicht akzeptiert wird.
Klicken Sie auf das Cast-Symbol und wählen Sie Ihr Google Cast-Gerät aus.
Wähle ein Video aus und klicke auf die Wiedergabeschaltfläche.
Das Video wird auf Ihrem Google Cast-Gerät wiedergegeben.
Der maximierte Controller wird angezeigt. Mit der Wiedergabe-/Pausetaste kannst du die Wiedergabe steuern.
Gehe zurück zur Liste der Videos.
Unten auf dem Bildschirm wird jetzt ein Mini-Controller angezeigt.
Drücke im Mini-Controller auf die Schaltfläche „Pause“, um das Video auf dem Receiver zu pausieren. Klicke im Mini-Controller auf die Wiedergabeschaltfläche, um die Wiedergabe des Videos fortzusetzen.
Klicken Sie auf das Cast-Symbol, um das Streamen auf das Google Cast-Gerät zu beenden.
4. Startprojekt vorbereiten
Wir müssen der heruntergeladenen Start-App Unterstützung für Google Cast hinzufügen. Im Folgenden finden Sie einige Google Cast-Begriffe, die wir in diesem Codelab verwenden:
- eine Absender-App auf einem Mobilgerät oder Laptop ausgeführt wird,
- Eine Receiver-App wird auf dem Google Cast-Gerät ausgeführt.
Projekt einrichten
Jetzt können Sie mit Xcode auf dem Startprojekt aufbauen:
- Rufen Sie auf Ihrem Terminal das Codelab-Verzeichnis auf.
- Installieren Sie die Abhängigkeiten aus der Podfile-Datei.
cd app-start pod update pod install
- Öffnen Sie Xcode und wählen Sie Open another project... (Weiteres Projekt öffnen...) aus.
- Wählen Sie im Ordner mit dem Beispielcode im Verzeichnis
app-start
die DateiCastVideos-ios.xcworkspace
aus.
App-Design
Die App ruft eine Liste mit Videos von einem Remote-Webserver ab und stellt eine Liste zur Verfügung, die der Nutzer durchsuchen kann. Nutzer können ein Video auswählen, um die Details aufzurufen, oder das Video lokal auf einem Mobilgerät abspielen.
Die App besteht aus zwei Controllern für die Hauptansicht: MediaTableViewController
und MediaViewController.
.
MediaTableViewController
Dieser UITableViewController zeigt eine Liste von Videos aus einer MediaListModel
-Instanz an. Die Liste der Videos und die zugehörigen Metadaten werden auf einem Remoteserver als JSON-Datei gehostet. MediaListModel
ruft diese JSON-Datei ab und verarbeitet sie, um eine Liste mit MediaItem
-Objekten zu erstellen.
Ein MediaItem
-Objekt stellt ein Video und die zugehörigen Metadaten wie Titel, Beschreibung, URL für ein Bild und URL für den Stream dar.
MediaTableViewController
erstellt eine MediaListModel
-Instanz und registriert sich dann als MediaListModelDelegate
, um informiert zu werden, wenn die Medienmetadaten heruntergeladen wurden, damit die Tabellenansicht geladen werden kann.
Dem Nutzer wird eine Liste von Video-Thumbnails mit einer kurzen Beschreibung für jedes Video angezeigt. Wenn ein Element ausgewählt wird, wird die entsprechende MediaItem
an MediaViewController
übergeben.
MediaViewController
Dieser Ansichts-Controller zeigt die Metadaten zu einem bestimmten Video an und ermöglicht dem Nutzer, das Video lokal auf dem Mobilgerät abzuspielen.
Der Ansichts-Controller hostet ein LocalPlayerView
, einige Mediensteuerelemente und einen Textbereich für die Beschreibung des ausgewählten Videos. Der Player deckt den oberen Teil des Bildschirms ab und bietet darunter Platz für eine detaillierte Beschreibung des Videos. Der Nutzer kann das Video abspielen/pausieren oder zur lokalen Videowiedergabe springen.
Häufig gestellte Fragen
5. Cast-Symbol hinzufügen
Auf einer für Google Cast optimierten App wird das Cast-Symbol in jedem Ansicht-Controller angezeigt. Wenn der Nutzer auf das Cast-Symbol klickt, wird eine Liste der Übertragungsgeräte angezeigt, die der Nutzer auswählen kann. Wenn der Nutzer Inhalte lokal auf dem Sendergerät wiedergegeben hat, wird die Wiedergabe auf diesem Übertragungsgerät gestartet oder fortgesetzt, wenn ein Übertragungsgerät ausgewählt wird. Der Nutzer kann während der Übertragung jederzeit auf das Cast-Symbol klicken und die Übertragung Ihrer App auf das Übertragungsgerät beenden. Der Nutzer muss auf jedem Bildschirm Ihrer App eine Verbindung zum Übertragungsgerät herstellen oder trennen können. Weitere Informationen hierzu finden Sie in der Checkliste für das Google Cast-Design.
Konfiguration
Für das Startprojekt sind dieselben Abhängigkeiten und Xcode-Einrichtungen wie für die fertige Beispiel-App erforderlich. Kehren Sie zu diesem Abschnitt zurück und führen Sie dieselben Schritte aus, um das GoogleCast.framework
zum Start-App-Projekt hinzuzufügen.
Initialisierung
Das Cast-Framework hat ein globales Singleton-Objekt, das GCKCastContext
, das alle Aktivitäten des Frameworks koordiniert. Dieses Objekt muss früh im Lebenszyklus der Anwendung initialisiert werden. Dies geschieht in der Regel in der Methode application(_:didFinishLaunchingWithOptions:)
des App-Delegaten, damit die automatische Sitzungswiederaufnahme beim Neustart der Absenderanwendung korrekt ausgelöst und die Suche nach Geräten gestartet werden kann.
Bei der Initialisierung von GCKCastContext
muss ein GCKCastOptions
-Objekt angegeben werden. Diese Klasse enthält Optionen, die das Verhalten des Frameworks beeinflussen. Das Wichtigste ist die ID der Empfänger-App, die verwendet wird, um die Ergebnisse der Übertragungsgeräteerkennung zu filtern und die Empfänger-App zu starten, wenn eine Übertragung gestartet wird.
Über die Methode application(_:didFinishLaunchingWithOptions:)
können Sie auch einen Logging-Delegaten einrichten, der die Logging-Nachrichten vom Cast-Framework empfängt. Diese können bei der Fehlersuche und Fehlerbehebung hilfreich sein.
Wenn Sie eine für Google Cast optimierte App entwickeln, müssen Sie sich als Cast-Entwickler registrieren und eine App-ID für Ihre App erhalten. In diesem Codelab verwenden wir eine Beispiel-App-ID.
Füge in AppDelegate.swift
den folgenden Code ein, um GCKCastContext
mit der App-ID aus den Standardeinstellungen des Nutzers zu initialisieren, und füge einen Listener für das Google Cast-Framework hinzu:
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)")
}
}
}
Cast-Symbol
Nachdem GCKCastContext
initialisiert wurde, muss das Cast-Symbol hinzugefügt werden, damit der Nutzer ein Übertragungsgerät auswählen kann. Das Cast SDK bietet eine Komponente für das Cast-Symbol namens GCKUICastButton
als abgeleitete UIButton
-Klasse. Sie können sie der Titelleiste der Anwendung hinzufügen, indem Sie sie in UIBarButtonItem
einschließen. Wir müssen das Cast-Symbol sowohl zu MediaTableViewController
als auch zu MediaViewController
hinzufügen.
Fügen Sie MediaTableViewController.swift
und MediaViewController.swift
den folgenden Code hinzu:
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)
...
}
...
}
Fügen Sie MediaViewController.swift
dann den folgenden Code hinzu:
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)
...
}
...
}
Führen Sie nun die App aus. Sie sollten ein Cast-Symbol in der Navigationsleiste der App sehen. Wenn Sie darauf klicken, werden die Übertragungsgeräte in Ihrem lokalen Netzwerk aufgelistet. Die Geräteerkennung wird automatisch vom GCKCastContext
verwaltet. Wähle dein Übertragungsgerät aus. Die Beispiel-Empfänger-App wird auf dem Übertragungsgerät geladen. Sie können zwischen der Suchaktivität und der Aktivität im lokalen Player wechseln. Der Status des Cast-Symbols wird synchronisiert.
Wir haben noch keine Unterstützung für die Medienwiedergabe, daher kannst du noch keine Videos auf dem Übertragungsgerät wiedergeben. Klicken Sie auf das Cast-Symbol, um das Streamen zu beenden.
6. Streamen von Videoinhalten
Wir erweitern die Beispiel-App so, dass Videos auch per Fernzugriff auf Übertragungsgeräten abgespielt werden können. Dazu müssen wir auf die verschiedenen Ereignisse warten, die vom Cast-Framework generiert werden.
Medien werden gestreamt
Wenn Sie Medien auf einem Übertragungsgerät wiedergeben möchten, müssen folgende Voraussetzungen erfüllt sein:
- Erstelle ein
GCKMediaInformation
-Objekt aus dem Cast SDK, das ein Medienelement modelliert. - Der Nutzer stellt eine Verbindung zum Übertragungsgerät her, um die Receiver-App zu starten.
- Laden Sie das
GCKMediaInformation
-Objekt in den Receiver und spielen Sie den Inhalt ab. - Beobachten Sie den Medienstatus.
- Wiedergabebefehle basierend auf Nutzerinteraktionen an den Empfänger senden
Schritt 1 ist so, als würden Sie ein Objekt einem anderen zuordnen. GCKMediaInformation
versteht das Cast SDK und MediaItem
steht für die Kapselung eines Medienelements durch unsere App. können wir MediaItem
ganz einfach GCKMediaInformation
zuordnen. Schritt 2 im vorherigen Abschnitt wurde bereits ausgeführt. Schritt 3 lässt sich mit dem Cast SDK ganz einfach durchführen.
Die Beispiel-App MediaViewController
unterscheidet bereits zwischen lokaler und Remote-Wiedergabe, indem sie diese Aufzählung verwendet:
enum PlaybackMode: Int {
case none = 0
case local
case remote
}
private var playbackMode = PlaybackMode.none
In diesem Codelab ist es nicht wichtig, dass Sie genau verstehen, wie die gesamte Logik des Beispiel-Players funktioniert. Der Mediaplayer Ihrer App muss so angepasst werden, dass er die beiden Wiedergabeorte auf ähnliche Weise erkennt.
Derzeit ist der lokale Player immer im lokalen Wiedergabestatus, da er noch nichts über den Streamingstatus weiß. Wir müssen die Benutzeroberfläche basierend auf Statusübergängen im Cast-Framework aktualisieren. Wenn wir beispielsweise mit dem Streamen beginnen, müssen wir die lokale Wiedergabe beenden und einige Steuerelemente deaktivieren. Wenn wir das Streaming beenden, während wir uns in diesem Ansicht-Controller befinden, müssen wir ebenfalls zur lokalen Wiedergabe wechseln. Dazu müssen wir auf die verschiedenen Ereignisse warten, die vom Cast-Framework generiert werden.
Streamingsitzung verwalten
Beim Cast-Framework umfasst eine Cast-Sitzung die Schritte: Verbinden mit einem Gerät, Starten oder Teilnehmen, Herstellen einer Verbindung zu einer Empfänger-App und Initialisieren eines Mediensteuerungskanals, falls erforderlich. Über den Mediensteuerungskanal sendet und empfängt das Cast-Framework Nachrichten vom Empfänger-Mediaplayer.
Das Streamen wird automatisch gestartet, wenn der Nutzer ein Gerät über das Cast-Symbol auswählt, und automatisch beendet, wenn der Nutzer die Verbindung trennt. Auch die Wiederherstellung einer Verbindung zu einer Empfängersitzung aufgrund von Netzwerkproblemen erfolgt automatisch durch das Cast-Framework.
Streamingsitzungen werden vom GCKSessionManager
verwaltet, auf den über GCKCastContext.sharedInstance().sessionManager
zugegriffen werden kann. Mit den GCKSessionManagerListener
-Callbacks können Sitzungsereignisse wie Erstellung, Sperrung, Wiederaufnahme und Beendigung überwacht werden.
Zunächst müssen wir unseren Sitzungs-Listener registrieren und einige Variablen initialisieren:
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()
}
...
}
Wir möchten im MediaViewController
informiert werden, wenn eine Verbindung mit dem Übertragungsgerät hergestellt oder getrennt wird, damit wir zum oder vom lokalen Player wechseln können. Die Verbindung kann nicht nur durch die Instanz Ihrer Anwendung unterbrochen werden, die auf Ihrem Mobilgerät ausgeführt wird, sondern auch durch eine andere Instanz Ihrer (oder einer anderen) Anwendung, die auf einem anderen Mobilgerät ausgeführt wird.
Die derzeit aktive Sitzung kann als GCKCastContext.sharedInstance().sessionManager.currentCastSession
aufgerufen werden. Sitzungen werden als Reaktion auf Nutzergesten im Cast-Dialogfeld automatisch erstellt und gelöscht.
Medien werden geladen
Die GCKRemoteMediaClient
im Cast SDK bietet eine Reihe praktischer APIs für die Verwaltung der Remote-Medienwiedergabe auf dem Empfänger. Bei einem GCKCastSession
, das die Medienwiedergabe unterstützt, wird vom SDK automatisch eine GCKRemoteMediaClient
-Instanz erstellt. Sie können als Attribut remoteMediaClient
der Instanz GCKCastSession
darauf zugreifen.
Füge den folgenden Code in MediaViewController.swift
ein, um das aktuell ausgewählte Video auf dem Empfänger zu laden:
@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
}
}
}
...
}
Aktualisiere nun verschiedene vorhandene Methoden, um die Cast Session-Logik zu verwenden, um die Remote-Wiedergabe zu unterstützen:
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
}
Führen Sie nun die App auf Ihrem Mobilgerät aus. Stellen Sie eine Verbindung zu Ihrem Übertragungsgerät her und starten Sie die Wiedergabe eines Videos. Das Video sollte auf dem Receiver wiedergegeben werden.
7. Mini-Controller
Gemäß der Checkliste für das Streaming-Design müssen alle Cast-Apps einen Mini-Controller haben, der angezeigt wird, wenn der Nutzer die aktuelle Inhaltsseite verlässt. Der Mini-Controller bietet sofortigen Zugriff und eine sichtbare Erinnerung für die aktuelle Übertragungssitzung.
Das Cast SDK bietet eine Steuerleiste (GCKUIMiniMediaControlsViewController
), die den Szenen hinzugefügt werden kann, in denen die permanenten Steuerelemente eingeblendet werden sollen.
Für die Beispiel-App verwenden wir GCKUICastContainerViewController
, das einen anderen View Controller umschließt und unten ein GCKUIMiniMediaControlsViewController
hinzufügt.
Ändern Sie die Datei AppDelegate.swift
und fügen Sie in der folgenden Methode den folgenden Code für die Bedingung if useCastContainerViewController
hinzu:
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()
...
}
Fügen Sie diese Eigenschaft und einen Setter/Getter hinzu, um die Sichtbarkeit des Mini-Controllers zu steuern (diese werden in einem späteren Abschnitt verwendet):
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
}
}
}
Starte die App und streame ein Video. Wenn die Wiedergabe auf dem Receiver beginnt, sollte der Mini-Controller unten in jeder Szene angezeigt werden. Sie können die Remote-Wiedergabe mit dem Mini-Controller steuern. Wenn Sie zwischen der Suchaktivität und der Aktivität des lokalen Players wechseln, sollte der Mini-Controller-Status mit dem Medienwiedergabestatus des Empfängers synchron bleiben.
8. Einleitendes Overlay
Gemäß der Checkliste für das Google Cast-Design muss eine Absender-App bestehenden Nutzern das Cast-Symbol vorstellen, um sie darüber zu informieren, dass die Sender-App jetzt das Streamen unterstützt und auch Neulingen von Google Cast hilft.
Die Klasse GCKCastContext
hat die Methode presentCastInstructionsViewControllerOnce
, mit der das Cast-Symbol hervorgehoben werden kann, wenn es Nutzern zum ersten Mal angezeigt wird. Fügen Sie MediaViewController.swift
und MediaTableViewController.swift
den folgenden Code hinzu:
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)
}
}
Wenn Sie die App auf Ihrem Mobilgerät ausführen, sollte das Einleitungs-Overlay zu sehen sein.
9. Maximierter Controller
Gemäß der Checkliste für das Design von Google Cast muss eine Absender-App einen erweiterten Controller für die gestreamten Medien bereitstellen. Der erweiterte Controller ist eine Vollbildversion des Mini-Controllers.
Der erweiterte Controller bietet eine Vollbildansicht, mit der Sie die Remote-Medienwiedergabe steuern können. In dieser Ansicht sollte eine Streaming-App alle überschaubaren Aspekte einer Streamingsitzung verwalten können, mit Ausnahme der Lautstärkeregelung des Empfängers und des Sitzungslebenszyklus (Streaming verbinden/beenden). Sie liefert außerdem alle Statusinformationen zur Mediensitzung (Artwork, Titel, Untertitel usw.).
Die Funktionen dieser Ansicht werden von der Klasse GCKUIExpandedMediaControlsViewController
implementiert.
Zuerst musst du den standardmäßigen erweiterten Controller im Streaming-Kontext aktivieren. Ändern Sie AppDelegate.swift
, um den standardmäßigen maximierten Controller zu aktivieren:
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
...
}
...
}
Fügen Sie MediaViewController.swift
den folgenden Code hinzu, um den erweiterten Controller zu laden, wenn der Nutzer mit dem Streamen eines Videos beginnt:
@objc func playSelectedItemRemotely() {
...
appDelegate?.isCastControlBarsEnabled = false
GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls()
}
Der erweiterte Controller wird auch automatisch gestartet, wenn der Nutzer auf den Mini-Controller tippt.
Starten Sie die App und streamen Sie ein Video. Der maximierte Controller sollte angezeigt werden. Gehe zurück zur Liste der Videos. Wenn du auf den Mini-Controller klickst, wird der maximierte Controller wieder geladen.
10. Cast Connect-Unterstützung hinzufügen
Über die Cast Connect-Bibliothek können bestehende Absender-Apps über das Cast-Protokoll mit Android TV-Apps kommunizieren. Cast Connect baut auf der Cast-Infrastruktur auf, wobei deine Android TV-App als Receiver fungiert.
Abhängigkeiten
Achte in deinem Podfile
darauf, dass google-cast-sdk
auf 4.4.8
oder höher zeigt, wie unten aufgeführt. Wenn Sie eine Änderung an der Datei vorgenommen haben, führen Sie pod update
über die Console aus, um die Änderung mit Ihrem Projekt zu synchronisieren.
pod 'google-cast-sdk', '>=4.4.8'
GCKLaunchOptions
Zum Starten der Android TV App, die auch als Android-Receiver bezeichnet wird, müssen wir das androidReceiverCompatible
-Flag im GCKLaunchOptions
-Objekt auf „true“ setzen. Dieses GCKLaunchOptions
-Objekt gibt vor, wie der Empfänger gestartet wird, und wird an den GCKCastOptions
übergeben, der in der gemeinsam genutzten Instanz mit GCKCastContext.setSharedInstanceWith
festgelegt wird.
Fügen Sie Ihrem AppDelegate.swift
die folgenden Zeilen hinzu:
let options = GCKCastOptions(discoveryCriteria:
GCKDiscoveryCriteria(applicationID: kReceiverAppID))
...
/** Following code enables CastConnect */
let launchOptions = GCKLaunchOptions()
launchOptions.androidReceiverCompatible = true
options.launchOptions = launchOptions
GCKCastContext.setSharedInstanceWith(options)
Anmeldedaten für den Start festlegen
Auf der Absenderseite können Sie GCKCredentialsData
angeben, um anzugeben, wer an der Sitzung teilnimmt. credentials
ist ein String, der vom Nutzer definiert werden kann, solange er von deiner ATV-App verstanden wird. Die GCKCredentialsData
wird nur während des Starts oder der Teilnahme an deiner Android TV App übergeben. Wenn Sie die Einstellung neu festlegen, während eine Verbindung besteht, wird sie nicht an Ihre Android TV App übergeben.
Zum Festlegen von Startanmeldedaten muss GCKCredentialsData
nach dem Festlegen von GCKLaunchOptions
jederzeit definiert werden. Zur Veranschaulichung fügen wir der Schaltfläche Creds eine Logik hinzu, mit der die Anmeldedaten festgelegt werden, die beim Aufbau der Sitzung übergeben werden. Fügen Sie Ihrem MediaTableViewController.swift
den folgenden Code hinzu:
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))
}
}
Anmeldedaten bei Ladeanfrage festlegen
Um credentials
sowohl in deiner Web-App als auch in deiner Android TV-Receiver-App zu verarbeiten, füge in der Klasse MediaTableViewController.swift
unter der Funktion loadSelectedItem
den folgenden Code hinzu:
let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
...
mediaLoadRequestDataBuilder.credentials = credentials
...
Abhängig von der Empfänger-App, an die Ihr Absender etwas überträgt, wendet das SDK die oben genannten Anmeldedaten automatisch auf die laufende Sitzung an.
Cast Connect testen
Schritte zur Installation des Android TV APK auf Chromecast mit Google TV
- Ermitteln Sie die IP-Adresse Ihres Android TV-Geräts. Normalerweise befindet sich die Option unter Einstellungen > Netzwerk und Internet > (Netzwerkname, mit dem Ihr Gerät verbunden ist). Auf der rechten Seite werden die Details und die IP-Adresse Ihres Geräts im Netzwerk angezeigt.
- Verwenden Sie die IP-Adresse des Geräts, um über ADB mit dem Terminal eine Verbindung zu ihm herzustellen:
$ adb connect <device_ip_address>:5555
- Gehen Sie im Terminalfenster zum Ordner der obersten Ebene für die Codelab-Beispiele, die Sie zu Beginn dieses Codelabs heruntergeladen haben. Beispiel:
$ cd Desktop/ios_codelab_src
- Installiere die APK-Datei aus diesem Ordner auf deinem Android TV mit folgendem Befehl:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
- Sie sollten jetzt auf Ihrem Android TV-Gerät im Menü Meine Apps eine App mit dem Namen Videos streamen finden.
- Anschließend können Sie die App in einem Emulator oder auf einem Mobilgerät erstellen und ausführen. Wenn du eine Übertragungssitzung mit deinem Android TV-Gerät startest, sollte jetzt die Android-Empfängeranwendung auf deinem Android TV-Gerät gestartet werden. Wenn du ein Video von deinem mobilen iOS-Sender abspielst, sollte das Video im Android Receiver gestartet werden. Außerdem kannst du die Wiedergabe über die Fernbedienung deines Android TV-Geräts steuern.
11. Cast-Widgets anpassen
Initialisierung
Beginnen Sie mit dem Ordner „App-Done“. Fügen Sie der Methode applicationDidFinishLaunchingWithOptions
in der Datei AppDelegate.swift
Folgendes hinzu:
func application(_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
let styler = GCKUIStyle.sharedInstance()
...
}
Nachdem Sie wie im Rest dieses Codelabs eine oder mehrere Anpassungen angewendet haben, führen Sie den Commit der Stile durch Aufrufen des folgenden Codes durch.
styler.apply()
Cast-Ansichten anpassen
Sie können alle Ansichten anpassen, die vom Cast Application Framework verwaltet werden, indem Sie für alle Ansichten Standardstilrichtlinien verwenden. Ändern wir als Beispiel die Farbe der Symbolfarbe.
styler.castViews.iconTintColor = .lightGray
Bei Bedarf können Sie die Standardeinstellungen für jeden Bildschirm überschreiben. Sie können beispielsweise die Farbe lightGrayColor für die Symbolfärbung nur für den maximierten Medien-Controller überschreiben.
styler.castViews.mediaControl.expandedController.iconTintColor = .green
Farben ändern
Sie können die Hintergrundfarbe für alle Ansichten oder für jede Ansicht einzeln anpassen. Mit dem folgenden Code wird die Hintergrundfarbe für alle von Cast Application Framework bereitgestellten Ansichten auf Blau gesetzt.
styler.castViews.backgroundColor = .blue
styler.castViews.mediaControl.miniController.backgroundColor = .yellow
Schriftarten ändern
Sie können Schriftarten für verschiedene Labels anpassen, die in Cast-Ansichten zu sehen sind. Wir wählen für alle Schriftarten „Courier-Oblique“ aus. zu Illustrationszwecken.
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)
Ändern der Standardschaltflächenbilder
Füge dem Projekt deine eigenen benutzerdefinierten Bilder hinzu und weise sie deinen Schaltflächen zu, um sie zu gestalten.
let muteOnImage = UIImage.init(named: "yourImage.png")
if let muteOnImage = muteOnImage {
styler.castViews.muteOnImage = muteOnImage
}
Design der Schaltfläche „Streamen“ ändern
Sie können Cast-Widgets auch mit dem UIAppearance-Protokoll einrichten. Mit dem folgenden Code wird das GCKUICastButton in allen angezeigten Ansichten gestaltet:
GCKUICastButton.appearance().tintColor = UIColor.gray
12. Glückwunsch
Jetzt wissen Sie, wie Sie unter iOS mithilfe der Cast SDK-Widgets eine Video-App für Google Cast aktivieren.
Weitere Informationen finden Sie im Entwicklerleitfaden für iOS-Absender.