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 erweitern, um Google Cast-kompatible Geräte wie Fernseher oder Soundsysteme zu steuern. Mit dem Cast SDK können Sie die erforderlichen UI-Komponenten anhand der Checkliste für das Google Cast-Design hinzufügen.
Die Checkliste für das Google Cast-Design wurde bereitgestellt, um die Nutzung von Cast auf allen unterstützten Plattformen einfach und vorhersehbar zu 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
- So fügen Sie die Schaltfläche „Streamen“ zum Auswählen eines Google Cast-Geräts hinzu.
- So verbindest du dich mit einem Übertragungsgerät und startest einen Media-Receiver.
- So streamen Sie ein Video.
- So fügen Sie Ihrer App einen Cast-Mini-Controller hinzu.
- So fügen Sie einen erweiterten Controller hinzu.
- So fügst du ein Einführungs-Overlay hinzu.
- So passen Sie Cast-Widgets an.
- Cast Connect integrieren
Voraussetzungen
- Den aktuellen 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
- Zum Testen der Cast Connect-Integration ist Chromecast mit Google TV erforderlich, für den Rest des Codelabs ist sie jedoch optional. Wenn Sie keinen haben, können Sie den Schritt Unterstützung für Cast Connect hinzufügen am Ende dieser Anleitung überspringen.
Erfahrung
- Sie benötigen Vorkenntnisse in der iOS-Entwicklung.
- Außerdem benötigen Sie Vorkenntnisse in Bezug auf Fernsehen. :)
Wie möchten Sie diese Anleitung verwenden?
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
Rufe die Konsole auf und installiere CocoaPods mit der standardmäßigen Ruby-Version, die unter macOS verfügbar ist:
sudo gem install cocoapods
Wenn Probleme auftreten, finden Sie in der offiziellen Dokumentation Informationen zum Herunterladen und Installieren des Abhängigkeitsmanagers.
Projekt einrichten
- Öffnen Sie das Terminal und wechseln Sie zum Codelab-Verzeichnis.
- Installieren Sie die Abhängigkeiten aus dem Podfile.
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 die Datei
CastVideos-ios.xcworkspace
aus dem Verzeichnisapp-done
aus.
Anwendung ausführen
Wählen Sie das Ziel und den Simulator aus und führen Sie die App aus:
Nach einigen Sekunden sollte die Video-App angezeigt werden.
Klicken Sie auf „Zulassen“, , wenn die Benachrichtigung über die Annahme eingehender Netzwerkverbindungen angezeigt wird. Das Symbol „Streamen“ wird nicht angezeigt, wenn diese Option nicht akzeptiert wird.
Klicken Sie auf die Schaltfläche „Streamen“ 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 erweiterte 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.
Klicke auf die Pause-Schaltfläche auf der Minifernbedienung, um das Video auf dem Receiver anzuhalten. Klicke im Mini-Controller auf die Wiedergabeschaltfläche, um die Wiedergabe des Videos fortzusetzen.
Klicken Sie auf die Schaltfläche „Streamen“, um das Streaming auf dem Google Cast-Gerät zu beenden.
4. Startprojekt vorbereiten
Wir müssen der heruntergeladenen Start-App Unterstützung für Google Cast hinzufügen. Hier sind einige Google Cast-Begriffe, die wir in diesem Codelab verwenden werden:
- eine Absender-App auf einem Mobilgerät oder Laptop ausgeführt wird,
- eine Empfänger-App auf dem Google Cast-Gerät ausgeführt wird.
Projekt einrichten
Jetzt können Sie mit Xcode auf dem Starterprojekt aufbauen:
- Rufen Sie auf Ihrem Terminal das Codelab-Verzeichnis auf.
- Installieren Sie die Abhängigkeiten aus dem Podfile.
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 dieses JSON ab und verarbeitet es, um eine Liste von 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 benachrichtigt zu werden, wenn die Medienmetadaten heruntergeladen wurden, damit die Tabellenansicht geladen werden kann.
Der Nutzer sieht eine Liste mit Video-Thumbnails und einer kurzen Beschreibung für jedes Video. 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 View Controller enthält einen LocalPlayerView
, einige Mediensteuerelemente und ein Textfeld, in dem die Beschreibung des ausgewählten Videos angezeigt wird. Der Player deckt den oberen Teil des Bildschirms ab und lässt darunter Platz für die detaillierte Beschreibung des Videos. Der Nutzer kann die lokale Videowiedergabe abspielen/pausieren oder vor-/rückspringen.
Häufig gestellte Fragen
5. Schaltfläche „Streamen“ hinzufügen
In einer für Google Cast optimierten Anwendung wird die Schaltfläche „Streamen“ in jedem Viewcontroller angezeigt. Wenn du auf die Schaltfläche „Streamen“ klickst, wird eine Liste der Übertragungsgeräte angezeigt, die du auswählen kannst. Wenn der Nutzer Inhalte lokal auf dem Sendergerät abspielte, wird durch die Auswahl eines Übertragungsgeräts die Wiedergabe auf diesem Gerät gestartet oder fortgesetzt. 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 die gleiche Xcode-Einrichtung erforderlich wie für die fertige Beispiel-App. Kehren Sie zu diesem Abschnitt zurück und führen Sie dieselben Schritte aus, um GoogleCast.framework
dem 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, normalerweise in der application(_:didFinishLaunchingWithOptions:)
-Methode des App-Delegates, damit die automatische Sitzungswiederaufnahme beim Neustart der Senderanwendung ordnungsgemäß ausgelöst und das Scannen nach Geräten gestartet werden kann.
Bei der Initialisierung von GCKCastContext
muss ein GCKCastOptions
-Objekt angegeben werden. Diese Klasse enthält Optionen, die sich auf das Verhalten des Frameworks auswirken. 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 für die Fehlerbehebung und Fehlersuche nützlich sein.
Wenn Sie Ihre eigene für Google Cast optimierte App entwickeln, müssen Sie sich als Cast-Entwickler registrieren und dann eine Anwendungs-ID für Ihre App abrufen. 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 die GCKCastContext
initialisiert wurde, müssen wir die Schaltfläche „Streamen“ hinzufügen, damit der Nutzer ein Streaminggerät auswählen kann. Das Cast SDK bietet eine Schaltfläche für die Übertragung namens GCKUICastButton
als UIButton
-Unterklasse. Er kann der Titelleiste der App hinzugefügt werden, indem er in ein UIBarButtonItem
-Element eingebunden wird. 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 als Nächstes den folgenden Code in Ihr MediaViewController.swift
ein:
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 jetzt die App aus. In der Navigationsleiste der App sollte das Cast-Symbol angezeigt werden. Wenn Sie darauf klicken, werden die Cast-Geräte in Ihrem lokalen Netzwerk aufgelistet. Die Geräteerkennung wird automatisch vom GCKCastContext
verwaltet. Wählen Sie Ihr Ü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 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. Videoinhalte streamen
Wir erweitern die Beispiel-App so, dass Videos auch per Fernzugriff auf Übertragungsgeräten abgespielt werden können. Dazu müssen wir die verschiedenen vom Cast-Framework generierten Ereignisse überwachen.
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
In Schritt 1 wird ein Objekt einem anderen zugeordnet. GCKMediaInformation
ist ein Objekt, das vom Cast SDK verstanden wird, und MediaItem
ist die Kapselung eines Medienelements in unserer App. Wir können MediaItem
ganz einfach einem GCKMediaInformation
zuordnen. Schritt 2 haben wir bereits im vorherigen Abschnitt 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 befindet sich der lokale Player immer im Status der lokalen Wiedergabe, da er noch nichts über die 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. Die automatische Wiederverbindung mit einer Empfängersitzung aufgrund von Netzwerkproblemen wird ebenfalls vom Cast-Framework verwaltet.
Übertragungssitzungen werden über die GCKSessionManager
verwaltet, auf die über GCKCastContext.sharedInstance().sessionManager
zugegriffen werden kann. Mit den GCKSessionManagerListener
-Callbacks können Sitzungsereignisse wie Erstellung, Sperrung, Wiederaufnahme und Beendigung überwacht werden.
Zuerst 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()
}
...
}
In MediaViewController
möchten wir wissen, wenn eine Verbindung zum Cast-Gerät hergestellt oder getrennt wird, damit wir zum 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.
Auf die derzeit aktive Sitzung kann als GCKCastContext.sharedInstance().sessionManager.currentCastSession
zugegriffen werden. Sitzungen werden als Reaktion auf Nutzergesten im Cast-Dialogfeld automatisch erstellt und gelöscht.
Medien werden geladen
Im Cast SDK bietet die GCKRemoteMediaClient
eine Reihe praktischer APIs zur Verwaltung der Remote-Medienwiedergabe auf dem Empfänger. Für eine GCKCastSession
, die die Medienwiedergabe unterstützt, wird vom SDK automatisch eine Instanz von GCKRemoteMediaClient
erstellt. Sie können über die Eigenschaft remoteMediaClient
der GCKCastSession
-Instanz darauf zugreifen.
Füge MediaViewController.swift
den folgenden Code hinzu, um das aktuell ausgewählte Video auf dem Receiver 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 jetzt verschiedene vorhandene Methoden, um die Logik der Übertragungssitzung zur Unterstützung der Remote-Wiedergabe zu verwenden:
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 jetzt auf dem Receiver wiedergegeben werden.
7. Mini-Controller
Gemäß der Checkliste für das Google Cast-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 an 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
}
}
}
Starten Sie die App und streamen Sie 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 du zwischen der Suchaktivität und der Aktivität des lokalen Players wechselst, sollte der Status des Mini-Controllers mit dem Status der Medienwiedergabe des Receivers synchronisiert bleiben.
8. Einleitendes Overlay
Gemäß der Google Cast-Design-Checkliste muss eine Sender-App bestehenden Nutzern die Cast-Schaltfläche präsentieren, um sie darüber zu informieren, dass die Sender-App jetzt das Streaming unterstützt. Außerdem sollte die Schaltfläche für Nutzer, die Google Cast noch nicht kennen, gut sichtbar sein.
Die Klasse GCKCastContext
hat eine Methode namens presentCastInstructionsViewControllerOnce
, mit der die Schaltfläche „Streamen“ hervorgehoben werden kann, wenn sie 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 Sender-App einen erweiterten Controller für die gestreamten Medien bereitstellen. Der erweiterte Controller ist eine Vollbildversion des Mini-Controllers.
Die erweiterte Steueroberfläche ist eine Vollbildansicht, die die vollständige Kontrolle über die Remote-Medienwiedergabe bietet. Über diese Ansicht sollte eine Streaming-App alle verwaltebaren Aspekte einer Streamingsitzung verwalten können, mit Ausnahme der Lautstärkeregelung des Empfängers und des Sitzungslebenszyklus (Verbinden/Streaming 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.
Starte die App und streame 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. Unterstützung für Cast Connect hinzufügen
Mit der Cast Connect-Mediathek können vorhandene Sender-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
Achten Sie darauf, dass in Ihrer Podfile
die google-cast-sdk
auf 4.4.8
oder höher verweist, wie unten aufgeführt. Wenn Sie die Datei geändert haben, führen Sie pod update
in der 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, sofern die ATV-App ihn lesen kann. Die GCKCredentialsData
wird nur beim Starten oder Beitreten an deine Android TV-App übergeben. Wenn du sie während einer Verbindung noch einmal festlegst, wird sie nicht an deine 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 für 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
Android TV-APK auf Chromecast mit Google TV installieren
- Ermitteln Sie die IP-Adresse Ihres Android TV-Geräts. Normalerweise finden Sie sie unter Einstellungen > Netzwerk und Internet > (Name des Netzwerks, 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
- Installieren Sie die APK-Datei in diesem Ordner auf Ihrem Android TV-Gerät:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
- Auf Ihrem Android TV-Gerät sollte jetzt im Menü Meine Apps eine App mit dem Namen Videos streamen angezeigt werden.
- Anschließend können Sie die App in einem Emulator oder auf einem Mobilgerät erstellen und ausführen. Sobald Sie mit Ihrem Android TV-Gerät streamen, sollte die Android Receiver App auf Ihrem 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 applicationDidFinishLaunchingWithOptions
-Methode in der Datei AppDelegate.swift
Folgendes hinzu:
func application(_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
let styler = GCKUIStyle.sharedInstance()
...
}
Wenn Sie eine oder mehrere Anpassungen wie im Rest dieses Codelabs beschrieben vorgenommen haben, können Sie die Stile committen, indem Sie den folgenden Code aufrufen:
styler.apply()
Wiedergabeansichten 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. So können Sie beispielsweise die Farbe „lightGrayColor“ für die Symbolfarbe nur für den erweiterten Mediacontroller ü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. Im folgenden Code wird die Hintergrundfarbe für alle vom Cast Application Framework bereitgestellten Ansichten auf „blau“ festgelegt.
styler.castViews.backgroundColor = .blue
styler.castViews.mediaControl.miniController.backgroundColor = .yellow
Schriftarten ändern
Sie können Schriftarten für verschiedene Labels anpassen, die in Wiedergabeansichten angezeigt werden. 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)
Standardschaltflächenbilder ändern
Füge dem Projekt deine eigenen 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 des Cast-Symbols ändern
Mit dem UIAppearance-Protokoll kannst du Cast Widgets auch entwerfen. 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 findest du im Entwicklerhandbuch für iOS-Sender.