1. Ringkasan
Codelab ini akan mengajarkan cara memodifikasi aplikasi video iOS yang ada untuk mentransmisikan konten di perangkat yang kompatibel untuk Google Cast.
Apa itu Google Cast?
Google Cast memungkinkan pengguna mentransmisikan konten dari perangkat seluler ke TV. Pengguna kemudian dapat menggunakan perangkat seluler sebagai remote control untuk pemutaran media di TV.
SDK Google Cast memungkinkan Anda memperluas aplikasi untuk mengontrol perangkat yang kompatibel dengan Google Cast (seperti TV atau sistem suara). Cast SDK memungkinkan Anda menambahkan komponen UI yang diperlukan berdasarkan Checklist Desain Google Cast.
Checklist Desain Google Cast disediakan untuk menyederhanakan pengalaman pengguna Cast dan membuatnya dapat diprediksi di semua platform yang didukung.
Apa yang akan kita buat?
Setelah menyelesaikan codelab ini, Anda akan memiliki aplikasi video iOS yang dapat mentransmisikan video ke perangkat Google Cast.
Yang akan Anda pelajari
- Cara menambahkan Google Cast SDK ke aplikasi video sampel.
- Cara menambahkan tombol Cast untuk memilih perangkat Google Cast.
- Cara menghubungkan ke perangkat Cast dan meluncurkan penerima media.
- Cara mentransmisikan video.
- Cara menambahkan pengontrol mini Cast ke aplikasi Anda.
- Cara menambahkan pengontrol yang diperluas.
- Cara menyediakan overlay perkenalan.
- Cara menyesuaikan widget Cast.
- Cara mengintegrasikan Cast Connect
Yang Anda butuhkan
- Xcode terbaru.
- Satu perangkat seluler dengan iOS 9 atau yang lebih baru (atau Simulator Xcode).
- Kabel data USB untuk menghubungkan perangkat seluler ke komputer pengembangan (jika menggunakan perangkat).
- Perangkat Google Cast seperti Chromecast atau Android TV yang dikonfigurasi dengan akses internet.
- TV atau monitor dengan input HDMI.
- Chromecast dengan Google TV diperlukan untuk menguji integrasi Cast Connect, tetapi bersifat opsional untuk Codelab lainnya. Jika Anda tidak memilikinya, lewati langkah Menambahkan Dukungan Cast Connect di akhir tutorial ini.
Pengalaman
- Sebelumnya, Anda harus memiliki pengetahuan pengembangan iOS.
- Anda juga perlu memiliki pengetahuan tentang menonton TV :)
Bagaimana Anda akan menggunakan tutorial ini?
Bagaimana Anda menilai pengalaman Anda membuat aplikasi iOS?
Bagaimana Anda menilai pengalaman menonton TV Anda?
2. Mendapatkan kode contoh
Anda bisa mendownload semua kode contoh ke komputer Anda...
dan mengekstrak file zip yang didownload.
3. Menjalankan aplikasi contoh
Pertama, mari kita lihat bagaimana tampilan contoh aplikasi yang sudah selesai. Aplikasi ini adalah pemutar video dasar. Pengguna dapat memilih video dari daftar dan kemudian dapat memutar video secara lokal di perangkat atau mentransmisikannya ke perangkat Google Cast.
Setelah kode didownload, petunjuk berikut menjelaskan cara membuka dan menjalankan aplikasi contoh yang telah selesai di Xcode:
Pertanyaan umum (FAQ)
Penyiapan CocoaPods
Untuk menyiapkan CocoaPods, buka konsol Anda dan instal menggunakan Ruby default yang tersedia di macOS:
sudo gem install cocoapods
Jika Anda mengalami masalah, lihat dokumentasi resmi untuk mendownload dan menginstal pengelola dependensi.
Penyiapan project
- Buka terminal Anda dan buka direktori codelab.
- Instal dependensi dari Podfile.
cd app-done pod update pod install
- Buka Xcode dan pilih Open another project...
- Pilih file
CastVideos-ios.xcworkspace
dari direktoriapp-done
di folder kode contoh.
Menjalankan aplikasi
Pilih target dan simulator, lalu jalankan aplikasi:
Anda akan melihat aplikasi video muncul setelah beberapa detik.
Pastikan untuk mengklik ‘Izinkan' saat muncul notifikasi tentang cara menerima koneksi jaringan masuk. Ikon Cast tidak akan muncul jika opsi ini tidak diterima.
Klik tombol Cast, lalu pilih perangkat Google Cast.
Pilih video, klik tombol putar.
Video akan mulai diputar di perangkat Google Cast.
Pengontrol yang diperluas akan ditampilkan. Anda dapat menggunakan tombol putar/jeda untuk mengontrol pemutaran.
Kembali ke daftar video.
Pengontrol mini kini terlihat di bagian bawah layar.
Klik tombol jeda di pengontrol mini untuk menjeda video pada penerima. Klik tombol putar di pengontrol mini untuk melanjutkan pemutaran video lagi.
Klik tombol Cast untuk menghentikan transmisi ke perangkat Google Cast.
4. Menyiapkan project awal
Kita perlu menambahkan dukungan untuk Google Cast ke aplikasi awal yang Anda download. Berikut adalah beberapa terminologi Google Cast yang akan kita gunakan dalam codelab ini:
- aplikasi pengirim berjalan di perangkat seluler atau laptop,
- aplikasi penerima berjalan di perangkat Google Cast.
Penyiapan project
Sekarang Anda siap membangun di atas project awal menggunakan Xcode:
- Buka terminal Anda dan buka direktori codelab.
- Instal dependensi dari Podfile.
cd app-start pod update pod install
- Buka Xcode dan pilih Open another project...
- Pilih file
CastVideos-ios.xcworkspace
dari direktoriapp-start
di folder kode contoh.
Desain aplikasi
Aplikasi ini mengambil daftar video dari server web jarak jauh dan menyediakan daftar untuk dijelajahi pengguna. Pengguna dapat memilih video untuk melihat detailnya atau memutar video secara lokal di perangkat seluler.
Aplikasi ini terdiri dari dua pengontrol tampilan utama: MediaTableViewController
dan MediaViewController.
MediaTableViewController
UITableViewController ini menampilkan daftar video dari instance MediaListModel
. Daftar video dan metadata terkait dihosting di server jarak jauh sebagai file JSON. MediaListModel
mengambil JSON ini dan memprosesnya untuk membuat daftar objek MediaItem
.
Objek MediaItem
memodelkan video dan metadatanya yang terkait, seperti judul, deskripsi, URL untuk gambar, dan URL untuk streaming.
MediaTableViewController
membuat instance MediaListModel
, lalu mendaftarkan dirinya sebagai MediaListModelDelegate
untuk diberi tahu saat metadata media telah didownload sehingga dapat memuat tampilan tabel.
Pengguna akan diberikan daftar thumbnail video dengan deskripsi singkat untuk setiap video. Saat item dipilih, MediaItem
yang sesuai akan diteruskan ke MediaViewController
.
MediaViewController
Pengontrol tampilan ini menampilkan metadata tentang video tertentu dan memungkinkan pengguna memutar video secara lokal di perangkat seluler.
Pengontrol tampilan menghosting LocalPlayerView
, beberapa kontrol media, dan area teks untuk menampilkan deskripsi video yang dipilih. Pemutar menutupi bagian atas layar, memberikan ruang untuk deskripsi mendetail video di bagian bawah. Pengguna dapat memutar/menjeda atau mencari pemutaran video lokal.
Pertanyaan umum (FAQ)
5. Menambahkan tombol Cast
Aplikasi yang kompatibel untuk Cast menampilkan tombol Cast di setiap pengontrol tampilannya. Mengklik tombol Cast akan menampilkan daftar perangkat Cast yang dapat dipilih pengguna. Jika pengguna memutar konten secara lokal di perangkat pengirim, memilih perangkat Cast akan memulai atau melanjutkan pemutaran di perangkat Cast tersebut. Kapan saja selama sesi Cast, pengguna dapat mengklik tombol Cast dan menghentikan transmisi aplikasi ke perangkat Cast. Pengguna harus dapat menghubungkan ke atau memutuskan sambungan dari perangkat Cast saat berada di layar mana pun pada aplikasi Anda, seperti yang dijelaskan dalam Checklist Desain Google Cast.
Konfigurasi
Project awal memerlukan dependensi dan penyiapan Xcode yang sama seperti yang Anda lakukan untuk aplikasi contoh yang sudah selesai. Kembali ke bagian tersebut dan ikuti langkah yang sama untuk menambahkan GoogleCast.framework
ke project aplikasi awal.
Inisialisasi
Framework Cast memiliki objek singleton global, GCKCastContext
, yang mengoordinasikan semua aktivitas framework. Objek ini harus diinisialisasi di awal siklus proses aplikasi, biasanya dalam metode application(_:didFinishLaunchingWithOptions:)
delegasi aplikasi, agar dimulainya kembali sesi otomatis saat aplikasi pengirim dimulai ulang dapat dipicu dengan benar dan pemindaian perangkat dapat dimulai.
Objek GCKCastOptions
harus disediakan saat melakukan inisialisasi GCKCastContext
. Class ini berisi opsi yang memengaruhi perilaku framework. Yang paling penting adalah ID aplikasi penerima, yang digunakan untuk memfilter hasil penemuan perangkat Cast dan meluncurkan aplikasi penerima saat sesi Cast dimulai.
Metode application(_:didFinishLaunchingWithOptions:)
juga merupakan tempat yang baik untuk menyiapkan delegasi logging guna menerima pesan logging dari framework Cast. Ini dapat berguna untuk proses debug dan pemecahan masalah.
Saat mengembangkan aplikasi yang kompatibel untuk Cast, Anda harus mendaftar sebagai developer Cast, lalu mendapatkan ID aplikasi untuk aplikasi tersebut. Untuk codelab ini, kita akan menggunakan contoh ID aplikasi.
Tambahkan kode berikut ke AppDelegate.swift
untuk melakukan inisialisasi GCKCastContext
dengan ID aplikasi dari default pengguna, dan tambahkan logger untuk framework Google Cast:
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)")
}
}
}
Tombol Cast
Setelah GCKCastContext
diinisialisasi, kita perlu menambahkan tombol Cast untuk memungkinkan pengguna memilih perangkat Cast. SDK Cast menyediakan komponen tombol Cast yang disebut GCKUICastButton
sebagai subclass UIButton
. Judul ini dapat ditambahkan ke kolom judul aplikasi dengan menggabungkannya dalam UIBarButtonItem
. Kita perlu menambahkan tombol Cast ke MediaTableViewController
dan MediaViewController
.
Tambahkan kode berikut ke MediaTableViewController.swift
dan MediaViewController.swift
:
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)
...
}
...
}
Selanjutnya, tambahkan kode berikut ke MediaViewController.swift
Anda:
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)
...
}
...
}
Sekarang jalankan aplikasi. Anda akan melihat tombol Cast di menu navigasi aplikasi dan saat mengkliknya, tombol ini akan membuat daftar perangkat Cast di jaringan lokal Anda. Penemuan perangkat dikelola secara otomatis oleh GCKCastContext
. Pilih perangkat Cast dan contoh aplikasi penerima yang akan dimuat di perangkat Cast. Anda dapat menavigasi antara aktivitas penjelajahan dan aktivitas pemutar lokal, dan status tombol Cast akan tetap sinkron.
Kami belum menyediakan dukungan untuk pemutaran media, jadi Anda belum dapat memutar video di perangkat Cast. Klik tombol Cast untuk menghentikan transmisi.
6. Mentransmisikan konten video
Kami akan memperluas contoh aplikasi untuk memutar video dari jarak jauh di perangkat Cast juga. Untuk melakukannya, kita harus memantau berbagai peristiwa yang dihasilkan oleh framework Cast.
Mentransmisikan media
Pada level tinggi, jika Anda ingin memutar media di perangkat Transmisi, hal berikut harus terjadi:
- Buat objek
GCKMediaInformation
dari SDK Cast yang memodelkan item media. - Pengguna terhubung ke perangkat Cast untuk meluncurkan aplikasi penerima Anda.
- Muat objek
GCKMediaInformation
ke penerima Anda dan putar kontennya. - Lacak status media.
- Kirim perintah pemutaran ke penerima berdasarkan interaksi pengguna.
Langkah 1 sama dengan memetakan satu objek ke objek lainnya; GCKMediaInformation
adalah sesuatu yang dipahami oleh Cast SDK dan MediaItem
adalah enkapsulasi aplikasi untuk item media; kita dapat dengan mudah memetakan MediaItem
ke GCKMediaInformation
. Kita telah menyelesaikan Langkah 2 di bagian sebelumnya. Langkah 3 mudah dilakukan dengan SDK Cast.
Aplikasi contoh MediaViewController
sudah membedakan antara pemutaran lokal vs jarak jauh dengan menggunakan enum ini:
enum PlaybackMode: Int {
case none = 0
case local
case remote
}
private var playbackMode = PlaybackMode.none
Dalam codelab ini Anda tidak perlu memahami keseluruhan cara kerja semua logika pemutar contoh. Tetapi Anda perlu memahami bahwa pemutar media aplikasi harus dimodifikasi agar mengetahui dua lokasi pemutaran dengan cara yang serupa.
Saat ini pemutar lokal selalu dalam status pemutaran lokal karena belum mengetahui apa pun tentang status Transmisi. Kita perlu mengupdate UI berdasarkan transisi status yang terjadi dalam framework Cast. Misalnya, jika mulai melakukan transmisi, kita perlu menghentikan pemutaran lokal dan menonaktifkan beberapa kontrol. Demikian pula, jika menghentikan transmisi saat berada di pengontrol tampilan ini, kita perlu beralih ke pemutaran lokal. Untuk menanganinya, kita perlu memantau berbagai peristiwa yang dihasilkan oleh framework Cast.
Pengelolaan sesi transmisi
Untuk framework Cast, sesi Cast menggabungkan langkah-langkah untuk menghubungkan ke perangkat, meluncurkan (atau bergabung), menghubungkan ke aplikasi penerima, dan menginisialisasi saluran kontrol media jika sesuai. Saluran kontrol media adalah cara framework Cast mengirim dan menerima pesan dari pemutar media penerima.
Sesi Transmisi akan dimulai secara otomatis saat pengguna memilih perangkat dari tombol Cast, dan akan dihentikan secara otomatis saat pengguna memutuskan sambungan. Menghubungkan kembali ke sesi penerima karena masalah jaringan juga otomatis ditangani oleh framework Cast.
Sesi transmisi dikelola oleh GCKSessionManager
, yang dapat diakses melalui GCKCastContext.sharedInstance().sessionManager
. Callback GCKSessionManagerListener
dapat digunakan untuk memantau peristiwa sesi, seperti pembuatan, penangguhan, dimulainya kembali, dan penghentian.
Pertama, kita harus mendaftarkan pemroses sesi dan melakukan inisialisasi beberapa variabel:
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()
}
...
}
Di MediaViewController
, kita ingin diberi tahu saat terhubung atau terputus dari perangkat Cast sehingga dapat beralih ke atau dari pemutar lokal. Perhatikan, konektivitas dapat terganggu bukan hanya oleh instance aplikasi Anda yang berjalan pada perangkat seluler, tetapi juga bisa terganggu oleh instance aplikasi lainnya (atau hal lainnya) yang berjalan pada perangkat seluler berbeda.
Sesi yang saat ini aktif dapat diakses sebagai GCKCastContext.sharedInstance().sessionManager.currentCastSession
. Sesi dibuat dan dihapus secara otomatis sebagai respons terhadap gestur pengguna dari dialog Transmisi.
Memuat media
Di SDK Cast, GCKRemoteMediaClient
menyediakan kumpulan API yang mudah digunakan untuk mengelola pemutaran media jarak jauh pada penerima. Untuk GCKCastSession
yang mendukung pemutaran media, instance GCKRemoteMediaClient
akan dibuat secara otomatis oleh SDK. Ini dapat diakses sebagai properti remoteMediaClient
dari instance GCKCastSession
.
Tambahkan kode berikut ke MediaViewController.swift
untuk memuat video yang saat ini dipilih di penerima:
@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
}
}
}
...
}
Sekarang perbarui berbagai metode yang ada untuk menggunakan logika Sesi Transmisi guna mendukung pemutaran jarak jauh:
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
}
Sekarang, jalankan aplikasi di perangkat seluler Anda. Sambungkan ke perangkat Cast dan mulai putar video. Anda akan melihat video yang diputar pada penerima.
7. Pengontrol mini
Checklist Desain Cast mengharuskan semua aplikasi Cast menyediakan pengontrol mini agar muncul saat pengguna keluar dari halaman konten saat ini. Pengontrol mini menyediakan akses instan dan pengingat yang terlihat untuk sesi Cast saat ini.
SDK Cast menyediakan panel kontrol, GCKUIMiniMediaControlsViewController
, yang dapat ditambahkan ke scene tempat Anda ingin menampilkan kontrol persisten.
Untuk aplikasi contoh, kita akan menggunakan GCKUICastContainerViewController
yang menggabungkan pengontrol tampilan lain dan menambahkan GCKUIMiniMediaControlsViewController
di bagian bawah.
Ubah file AppDelegate.swift
dan tambahkan kode berikut untuk kondisi if useCastContainerViewController
dalam metode berikut:
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()
...
}
Tambahkan properti ini dan penyetel/pengambil untuk mengontrol visibilitas pengontrol mini (kita akan menggunakannya di bagian selanjutnya):
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
}
}
}
Jalankan aplikasi dan transmisikan video. Saat pemutaran dimulai di penerima, Anda akan melihat pengontrol mini muncul di bagian bawah setiap adegan. Anda dapat mengontrol pemutaran jarak jauh menggunakan pengontrol mini. Jika Anda bernavigasi antara aktivitas penjelajahan dan aktivitas pemutar lokal, status pengontrol mini harus tetap sinkron dengan status pemutaran media penerima.
8. Overlay perkenalan
Checklist desain Google Cast memerlukan aplikasi pengirim untuk memperkenalkan tombol Cast kepada pengguna yang ada guna memberi tahu bahwa aplikasi pengirim kini mendukung Transmisi dan juga membantu pengguna yang baru menggunakan Google Cast.
Class GCKCastContext
memiliki metode, presentCastInstructionsViewControllerOnce
, yang dapat digunakan untuk menandai tombol Cast saat pertama kali ditampilkan kepada pengguna. Tambahkan kode berikut ke MediaViewController.swift
dan MediaTableViewController.swift
:
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)
}
}
Jalankan aplikasi di perangkat seluler dan Anda akan melihat overlay pengantar.
9. Pengontrol yang diperluas
Checklist desain Google Cast memerlukan aplikasi pengirim untuk menyediakan pengontrol yang diperluas untuk media yang ditransmisikan. Pengontrol yang diperluas adalah versi layar penuh dari pengontrol mini.
Pengontrol yang diperluas adalah tampilan layar penuh yang menawarkan kontrol penuh atas pemutaran media jarak jauh. Tampilan ini akan memungkinkan aplikasi transmisi mengelola setiap aspek sesi transmisi yang dapat dikelola, kecuali kontrol volume penerima dan siklus proses sesi (menghubungkan/menghentikan transmisi). Panel ini juga memberikan semua informasi status tentang sesi media (karya seni, judul, subtitel, dan sebagainya).
Fungsi tampilan ini diimplementasikan oleh class GCKUIExpandedMediaControlsViewController
.
Hal pertama yang harus Anda lakukan adalah mengaktifkan pengontrol yang diperluas default dalam konteks transmisi. Ubah AppDelegate.swift
untuk mengaktifkan pengontrol default yang diperluas:
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
...
}
...
}
Tambahkan kode berikut ke MediaViewController.swift
untuk memuat pengontrol yang diperluas saat pengguna mulai mentransmisikan video:
@objc func playSelectedItemRemotely() {
...
appDelegate?.isCastControlBarsEnabled = false
GCKCastContext.sharedInstance().presentDefaultExpandedMediaControls()
}
Pengontrol yang diperluas juga akan diluncurkan secara otomatis saat pengguna mengetuk pengontrol mini.
Jalankan aplikasi dan transmisikan video. Anda akan melihat pengontrol yang diperluas. Kembali ke daftar video dan saat Anda mengklik pengontrol mini, pengontrol yang diperluas akan dimuat lagi.
10. Menambahkan dukungan Cast Connect
Library Cast Connect memungkinkan aplikasi pengirim yang ada untuk berkomunikasi dengan aplikasi Android TV melalui protokol Cast. Cast Connect dibuat di atas infrastruktur Cast, dengan aplikasi Android TV yang bertindak sebagai penerima.
Dependensi
Di Podfile
, pastikan google-cast-sdk
mengarah ke 4.4.8
atau yang lebih tinggi seperti yang tercantum di bawah. Jika Anda membuat perubahan pada file, jalankan pod update
dari konsol untuk menyinkronkan perubahan dengan project Anda.
pod 'google-cast-sdk', '>=4.4.8'
GCKLaunchOptions
Untuk meluncurkan aplikasi Android TV, yang juga disebut sebagai Penerima Android, kita perlu menyetel tanda androidReceiverCompatible
ke benar (true) di objek GCKLaunchOptions
. Objek GCKLaunchOptions
ini menentukan cara penerima diluncurkan dan diteruskan ke GCKCastOptions
yang ditetapkan dalam instance bersama menggunakan GCKCastContext.setSharedInstanceWith
.
Tambahkan baris berikut ke AppDelegate.swift
Anda:
let options = GCKCastOptions(discoveryCriteria:
GCKDiscoveryCriteria(applicationID: kReceiverAppID))
...
/** Following code enables CastConnect */
let launchOptions = GCKLaunchOptions()
launchOptions.androidReceiverCompatible = true
options.launchOptions = launchOptions
GCKCastContext.setSharedInstanceWith(options)
Tetapkan Kredensial Peluncuran
Di sisi pengirim, Anda dapat menentukan GCKCredentialsData
untuk mewakili siapa yang bergabung ke sesi. credentials
adalah string yang dapat ditentukan oleh pengguna, selama aplikasi ATV Anda dapat memahaminya. GCKCredentialsData
hanya diteruskan ke aplikasi Android TV selama waktu peluncuran atau bergabung. Jika Anda menyetelnya lagi saat terhubung, kartu tidak akan diteruskan ke aplikasi Android TV.
Untuk menetapkan Kredensial Peluncuran, GCKCredentialsData
harus ditentukan kapan saja setelah GCKLaunchOptions
ditetapkan. Untuk mendemonstrasikan ini, mari kita tambahkan logika untuk tombol Creds guna menyetel kredensial yang akan diteruskan saat sesi dibuat. Tambahkan kode berikut ke MediaTableViewController.swift
Anda:
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))
}
}
Tetapkan Kredensial saat Pemuatan Permintaan
Untuk menangani credentials
di aplikasi Penerima Web dan Android TV, tambahkan kode berikut di class MediaTableViewController.swift
pada fungsi loadSelectedItem
:
let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
...
mediaLoadRequestDataBuilder.credentials = credentials
...
Bergantung pada aplikasi penerima yang menjadi tujuan transmisi pengirim, SDK akan secara otomatis menerapkan kredensial di atas ke sesi yang sedang berlangsung.
Menguji Cast Connect
Langkah-langkah untuk menginstal APK Android TV di Chromecast dengan Google TV
- Temukan Alamat IP perangkat Android TV Anda. Biasanya, ini tersedia di bagian Setelan > Jaringan & Internet > (Nama jaringan yang terhubung ke perangkat Anda). Di sebelah kanan, Anda akan melihat detail dan IP perangkat Anda di jaringan.
- Gunakan alamat IP untuk perangkat Anda agar terhubung melalui ADB menggunakan terminal:
$ adb connect <device_ip_address>:5555
- Dari jendela terminal, buka folder tingkat atas untuk mendapatkan contoh codelab yang Anda download di awal codelab ini. Contoh:
$ cd Desktop/ios_codelab_src
- Instal file .apk dalam folder ini ke Android TV Anda dengan menjalankan:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
- Sekarang Anda seharusnya bisa melihat aplikasi bernama Transmisikan Video di menu Aplikasi Anda di perangkat Android TV.
- Setelah selesai, bangun dan jalankan aplikasi di emulator atau perangkat seluler. Saat membuat sesi transmisi dengan perangkat Android TV, aplikasi Penerima Android kini akan diluncurkan di Android TV Anda. Memutar video dari pengirim seluler iOS akan meluncurkan video di Penerima Android dan memungkinkan Anda mengontrol pemutaran menggunakan remote untuk perangkat Android TV.
11. Menyesuaikan widget Cast
Inisialisasi
Mulailah dengan folder App-Done. Tambahkan kode berikut ke metode applicationDidFinishLaunchingWithOptions
di file AppDelegate.swift
Anda.
func application(_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
let styler = GCKUIStyle.sharedInstance()
...
}
Setelah selesai menerapkan satu atau beberapa penyesuaian seperti yang disebutkan di bagian lain codelab ini, commit gaya dengan memanggil kode di bawah ini
styler.apply()
Menyesuaikan tampilan Transmisi
Anda dapat menyesuaikan semua tampilan yang dikelola Framework Aplikasi Cast dengan memiliki panduan gaya default di seluruh tampilan. Sebagai contoh, mari kita ubah warna tint ikon.
styler.castViews.iconTintColor = .lightGray
Anda dapat mengganti default per layar jika diperlukan. Misalnya, untuk mengganti lightGrayColor untuk warna tint ikon hanya untuk pengontrol media yang diperluas.
styler.castViews.mediaControl.expandedController.iconTintColor = .green
Mengubah warna
Anda dapat menyesuaikan warna latar belakang untuk semua tampilan (atau satu per satu untuk setiap tampilan). Kode berikut menyetel warna latar belakang ke biru untuk semua tampilan yang disediakan Framework Aplikasi Cast.
styler.castViews.backgroundColor = .blue
styler.castViews.mediaControl.miniController.backgroundColor = .yellow
Mengubah font
Anda dapat menyesuaikan font untuk berbagai label yang terlihat dalam tampilan transmisi. Mari kita setel semua font menjadi ‘Courier-Oblique' untuk tujuan ilustrasi.
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)
Mengubah gambar tombol default
Tambahkan gambar kustom Anda sendiri ke project, dan tetapkan gambar ke tombol Anda untuk menata gayanya.
let muteOnImage = UIImage.init(named: "yourImage.png")
if let muteOnImage = muteOnImage {
styler.castViews.muteOnImage = muteOnImage
}
Mengubah tema tombol Cast
Anda juga dapat menerapkan tema Widget Cast menggunakan Protokol UIAppearance. Kode berikut memberikan tema GCKUICastButton pada semua tampilan yang muncul:
GCKUICastButton.appearance().tintColor = UIColor.gray
12. Selamat
Kini Anda telah mengetahui cara agar aplikasi video kompatibel untuk Cast menggunakan widget SDK Cast di iOS.
Untuk mengetahui detail selengkapnya, lihat panduan developer Pengirim iOS.