เปิดใช้แอป iOS แคสต์

1. ภาพรวม

โลโก้ Google Cast

Codelab นี้จะสอนวิธีแก้ไขแอปวิดีโอ iOS ที่มีอยู่เพื่อแคสต์เนื้อหาในอุปกรณ์ที่พร้อมใช้งาน Google Cast

Google Cast คืออะไร

Google Cast ช่วยให้ผู้ใช้แคสต์เนื้อหาจากอุปกรณ์เคลื่อนที่ไปยังทีวีได้ จากนั้นผู้ใช้จะใช้อุปกรณ์เคลื่อนที่เป็นรีโมตคอนโทรลสำหรับการเล่นสื่อบนทีวีได้

Google Cast SDK ช่วยให้คุณขยายแอปเพื่อควบคุมอุปกรณ์ที่พร้อมใช้งาน Google Cast (เช่น ทีวีหรือระบบเสียง) ได้ Cast SDK ช่วยให้คุณเพิ่มคอมโพเนนต์ UI ที่จำเป็นตามรายการตรวจสอบการออกแบบ Google Cast ได้

รายการตรวจสอบการออกแบบ Google Cast มีไว้เพื่อให้ประสบการณ์ของผู้ใช้ Cast นั้นเรียบง่ายและคาดการณ์ได้ในทุกแพลตฟอร์มที่รองรับ

เราจะสร้างอะไร

เมื่อทำ Codelab นี้เสร็จแล้ว คุณจะมีแอปวิดีโอบน iOS ที่สามารถแคสต์วิดีโอไปยังอุปกรณ์ Google Cast ได้

สิ่งที่คุณจะได้เรียนรู้

  • วิธีเพิ่ม Google Cast SDK ลงในแอปวิดีโอตัวอย่าง
  • วิธีเพิ่มปุ่มแคสต์เพื่อเลือกอุปกรณ์ Google Cast
  • วิธีเชื่อมต่อกับอุปกรณ์แคสต์และเปิดตัวรับสื่อ
  • วิธีแคสต์วิดีโอ
  • วิธีเพิ่มมินิคอนโทรลเลอร์แคสต์ลงในแอป
  • วิธีเพิ่มตัวควบคุมที่ขยาย
  • วิธีใส่โอเวอร์เลย์แนะนำ
  • วิธีปรับแต่งวิดเจ็ตแคสต์
  • วิธีผสานรวม Cast Connect

สิ่งที่คุณต้องมี

  • Xcode เวอร์ชันล่าสุด
  • อุปกรณ์เคลื่อนที่ 1 เครื่องที่ใช้ iOS 9 ขึ้นไป (หรือ Xcode Simulator)
  • สาย USB สำหรับรับส่งข้อมูลเพื่อเชื่อมต่ออุปกรณ์เคลื่อนที่กับคอมพิวเตอร์ที่ใช้พัฒนา (หากใช้อุปกรณ์)
  • อุปกรณ์ Google Cast เช่น Chromecast หรือ Android TV ที่กำหนดค่าให้เข้าถึงอินเทอร์เน็ตได้
  • ทีวีหรือจอภาพที่มีอินพุต HDMI
  • คุณต้องมี Chromecast พร้อม Google TV เพื่อทดสอบการผสานรวม Cast Connect แต่จะใช้หรือไม่ก็ได้สำหรับ Codelab ที่เหลือ หากไม่มี ให้ข้ามขั้นตอนเพิ่มการรองรับ Cast Connect ที่อยู่ท้ายบทแนะนำนี้

ประสบการณ์

  • คุณจะต้องมีความรู้ด้านการพัฒนา iOS มาก่อน
  • นอกจากนี้ คุณยังต้องมีความรู้พื้นฐานเกี่ยวกับการดูทีวีด้วย :)

คุณจะใช้บทแนะนำนี้อย่างไร

อ่านอย่างเดียว อ่านและทำแบบฝึกหัด

คุณจะให้คะแนนประสบการณ์ในการสร้างแอป iOS เท่าไร

ผู้ฝึกหัด ขั้นกลาง ผู้ชำนาญ

คุณจะให้คะแนนประสบการณ์การดูทีวีเท่าใด

ผู้ฝึกหัด ขั้นกลาง ผู้ชำนาญ

2. รับโค้ดตัวอย่าง

คุณจะดาวน์โหลดโค้ดตัวอย่างทั้งหมดลงในคอมพิวเตอร์...

และแตกไฟล์ ZIP ที่ดาวน์โหลด

3. เรียกใช้แอปตัวอย่าง

โลโก้ Apple iOS

ก่อนอื่น มาดูตัวอย่างแอปที่เสร็จสมบูรณ์กัน แอปนี้เป็นวิดีโอเพลเยอร์พื้นฐาน ผู้ใช้สามารถเลือกวิดีโอจากรายการ แล้วเล่นวิดีโอบนอุปกรณ์แบบออฟไลน์หรือแคสต์ไปยังอุปกรณ์ Google Cast ได้

เมื่อดาวน์โหลดโค้ดแล้ว คำสั่งต่อไปนี้จะอธิบายวิธีเปิดและเรียกใช้แอปตัวอย่างที่เสร็จสมบูรณ์ใน Xcode

คำถามที่พบบ่อย

การตั้งค่า CocoaPods

หากต้องการตั้งค่า CocoaPods ให้ไปที่คอนโซลแล้วติดตั้งโดยใช้ Ruby เริ่มต้นที่มีใน macOS

sudo gem install cocoapods

หากพบปัญหา โปรดดูเอกสารประกอบอย่างเป็นทางการเพื่อดาวน์โหลดและติดตั้งเครื่องมือจัดการการขึ้นต่อกัน

การตั้งค่าโปรเจ็กต์

  1. ไปที่เทอร์มินัลและไปยังไดเรกทอรีของ Codelab
  2. ติดตั้งการอ้างอิงจาก Podfile
cd app-done
pod update
pod install
  1. เปิด Xcode แล้วเลือกเปิดโปรเจ็กต์อื่น...
  2. เลือกCastVideos-ios.xcworkspaceไฟล์จากไดเรกทอรี ไอคอนโฟลเดอร์app-done ในโฟลเดอร์โค้ดตัวอย่าง

เรียกใช้แอป

เลือกเป้าหมายและเครื่องมือจำลอง แล้วเรียกใช้แอปโดยทำดังนี้

แถบเครื่องมือจำลองแอป XCode

คุณจะเห็นแอปวิดีโอปรากฏขึ้นหลังจากผ่านไป 2-3 วินาที

โปรดคลิก "อนุญาต" เมื่อมีการแจ้งเตือนเกี่ยวกับการยอมรับการเชื่อมต่อเครือข่ายขาเข้า ไอคอนแคสต์จะไม่ปรากฏหากไม่ยอมรับตัวเลือกนี้

กล่องโต้ตอบการยืนยันที่ขอสิทธิ์ยอมรับการเชื่อมต่อเครือข่ายขาเข้า

คลิกปุ่มแคสต์ แล้วเลือกอุปกรณ์ Google Cast

เลือกวิดีโอ แล้วคลิกปุ่มเล่น

วิดีโอจะเริ่มเล่นในอุปกรณ์ Google Cast

ตัวควบคุมแบบขยายจะปรากฏขึ้น คุณใช้ปุ่มเล่น/หยุดชั่วคราวเพื่อควบคุมการเล่นได้

กลับไปที่รายการวิดีโอ

ตอนนี้คุณจะเห็นมินิคอนโทรลเลอร์ที่ด้านล่างของหน้าจอ

ภาพ iPhone ที่เรียกใช้แอป CastVideos โดยมีมินิคอนโทรลเลอร์ปรากฏที่ด้านล่าง

คลิกปุ่มหยุดชั่วคราวในมินิคอนโทรลเลอร์เพื่อหยุดวิดีโอชั่วคราวบนเครื่องรับ คลิกปุ่มเล่นในมินิคอนโทรลเลอร์เพื่อเล่นวิดีโอต่อ

คลิกปุ่มแคสต์เพื่อหยุดแคสต์ไปยังอุปกรณ์ Google Cast

4. เตรียมโปรเจ็กต์เริ่มต้น

ภาพ iPhone ที่เรียกใช้แอป CastVideos

เราต้องเพิ่มการรองรับ Google Cast ลงในแอปเริ่มต้นที่คุณดาวน์โหลด คำศัพท์บางคำที่เกี่ยวข้องกับ Google Cast ซึ่งเราจะใช้ใน Codelab นี้มีดังนี้

  • แอปผู้ส่งทำงานบนอุปกรณ์เคลื่อนที่หรือแล็ปท็อป
  • แอปตัวรับจะทำงานบนอุปกรณ์ Google Cast

การตั้งค่าโปรเจ็กต์

ตอนนี้คุณพร้อมที่จะสร้างต่อจากโปรเจ็กต์เริ่มต้นโดยใช้ Xcode แล้ว

  1. ไปที่เทอร์มินัลและไปยังไดเรกทอรีของ Codelab
  2. ติดตั้งการอ้างอิงจาก Podfile
cd app-start
pod update
pod install
  1. เปิด Xcode แล้วเลือกเปิดโปรเจ็กต์อื่น...
  2. เลือกCastVideos-ios.xcworkspaceไฟล์จากไดเรกทอรี ไอคอนโฟลเดอร์app-start ในโฟลเดอร์โค้ดตัวอย่าง

การออกแบบแอป

แอปจะดึงรายการวิดีโอจากเว็บเซิร์ฟเวอร์ระยะไกลและแสดงรายการให้ผู้ใช้เรียกดู ผู้ใช้สามารถเลือกวิดีโอเพื่อดูรายละเอียดหรือเล่นวิดีโอในอุปกรณ์เคลื่อนที่ได้

แอปประกอบด้วยตัวควบคุมมุมมองหลัก 2 รายการ ได้แก่ MediaTableViewController และ MediaViewController.

MediaTableViewController

UITableViewController นี้จะแสดงรายการวิดีโอจากอินสแตนซ์ MediaListModel ระบบจะโฮสต์รายการวิดีโอและข้อมูลเมตาที่เกี่ยวข้องในเซิร์ฟเวอร์ระยะไกลเป็นไฟล์ JSON MediaListModel จะดึงข้อมูล JSON นี้และประมวลผลเพื่อสร้างรายการออบเจ็กต์ MediaItem

ออบเจ็กต์ MediaItem จะจำลองวิดีโอและข้อมูลเมตาที่เกี่ยวข้อง เช่น ชื่อ คำอธิบาย URL ของรูปภาพ และ URL ของสตรีม

MediaTableViewController สร้างอินสแตนซ์ MediaListModel แล้วลงทะเบียนตัวเองเป็น MediaListModelDelegate เพื่อรับการแจ้งเตือนเมื่อดาวน์โหลดข้อมูลเมตาของสื่อแล้ว เพื่อให้โหลดมุมมองตารางได้

ผู้ใช้จะเห็นรายการภาพปกวิดีโอพร้อมคำอธิบายสั้นๆ ของวิดีโอแต่ละรายการ เมื่อเลือกรายการ ระบบจะส่ง MediaItem ที่เกี่ยวข้องไปยัง MediaViewController

MediaViewController

ตัวควบคุมมุมมองนี้จะแสดงข้อมูลเมตาเกี่ยวกับวิดีโอที่เฉพาะเจาะจงและอนุญาตให้ผู้ใช้เล่นวิดีโอบนอุปกรณ์เคลื่อนที่ได้

ตัวควบคุมมุมมองจะโฮสต์ LocalPlayerView ตัวควบคุมสื่อบางส่วน และพื้นที่ข้อความเพื่อแสดงคำอธิบายของวิดีโอที่เลือก โดยเพลเยอร์จะครอบคลุมส่วนบนของหน้าจอ ทำให้มีพื้นที่สำหรับคำอธิบายโดยละเอียดของวิดีโอที่อยู่ด้านล่าง ผู้ใช้สามารถเล่น/หยุดชั่วคราวหรือกรอวิดีโอที่เล่นในเครื่องได้

คำถามที่พบบ่อย

5. การเพิ่มปุ่มแคสต์

ภาพวาดส่วนบนสุดของ iPhone ที่เรียกใช้แอป CastVideos ซึ่งแสดงปุ่มแคสต์ที่มุมขวาบน

แอปพลิเคชันที่พร้อมใช้งาน Cast จะแสดงปุ่ม "แคสต์" ในตัวควบคุมมุมมองแต่ละรายการ การคลิกปุ่มแคสต์จะแสดงรายการอุปกรณ์แคสต์ที่ผู้ใช้เลือกได้ หากผู้ใช้เล่นเนื้อหาในอุปกรณ์ที่ส่งแบบโลคัล การเลือกอุปกรณ์แคสต์จะเริ่มหรือเล่นต่อในอุปกรณ์แคสต์นั้น ผู้ใช้สามารถคลิกปุ่มแคสต์และหยุดแคสต์แอปพลิเคชันไปยังอุปกรณ์แคสต์ได้ทุกเมื่อในระหว่างเซสชัน Cast ผู้ใช้ต้องสามารถเชื่อมต่อหรือยกเลิกการเชื่อมต่อกับอุปกรณ์ Cast ขณะอยู่ในหน้าจอใดก็ได้ของแอปพลิเคชันตามที่อธิบายไว้ในรายการตรวจสอบการออกแบบ Google Cast

การกำหนดค่า

โปรเจ็กต์เริ่มต้นต้องมีทรัพยากร Dependency และการตั้งค่า Xcode เหมือนกับที่คุณทำสำหรับแอปตัวอย่างที่เสร็จสมบูรณ์แล้ว ให้กลับไปที่ส่วนนั้นและทำตามขั้นตอนเดียวกันเพื่อเพิ่ม GoogleCast.framework ลงในโปรเจ็กต์แอปเริ่มต้น

การเริ่มต้น

เฟรมเวิร์ก Cast มีออบเจ็กต์ Singleton ส่วนกลาง ซึ่งก็คือ GCKCastContext ที่ประสานงานกิจกรรมทั้งหมดของเฟรมเวิร์ก ต้องเริ่มต้นออบเจ็กต์นี้ตั้งแต่เนิ่นๆ ในวงจรของแอปพลิเคชัน ซึ่งโดยปกติจะอยู่ในเมธอด application(_:didFinishLaunchingWithOptions:) ของตัวแทนแอป เพื่อให้การกลับมาใช้เซสชันต่อโดยอัตโนมัติเมื่อแอปพลิเคชันผู้ส่งรีสตาร์ททำงานได้อย่างถูกต้องและเริ่มสแกนหาอุปกรณ์ได้

ต้องระบุออบเจ็กต์ GCKCastOptions เมื่อเริ่มต้น GCKCastContext คลาสนี้มีตัวเลือกที่ส่งผลต่อลักษณะการทำงานของเฟรมเวิร์ก ข้อมูลที่สำคัญที่สุดคือรหัสแอปพลิเคชันตัวรับ ซึ่งใช้เพื่อกรองผลการค้นหาอุปกรณ์แคสต์และเพื่อเปิดใช้แอปพลิเคชันตัวรับเมื่อเริ่มเซสชันการแคสต์

application(_:didFinishLaunchingWithOptions:) ยังเป็นตำแหน่งที่ดีในการตั้งค่าผู้มอบสิทธิ์การบันทึกเพื่อรับข้อความการบันทึกจากเฟรมเวิร์ก Cast ซึ่งอาจมีประโยชน์ในการแก้ไขข้อบกพร่องและแก้ปัญหา

เมื่อพัฒนาแอปที่พร้อมใช้งาน Cast ของคุณเอง คุณต้องลงทะเบียนเป็นนักพัฒนาแอป Cast แล้วขอรหัสแอปพลิเคชันสำหรับแอปของคุณ สำหรับ Codelab นี้ เราจะใช้รหัสแอปตัวอย่าง

เพิ่มโค้ดต่อไปนี้ลงใน AppDelegate.swift เพื่อเริ่มต้น GCKCastContext ด้วยรหัสแอปพลิเคชันจากค่าเริ่มต้นของผู้ใช้ และเพิ่มเครื่องบันทึกสำหรับเฟรมเวิร์ก 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)")
    }
  }
}

ปุ่ม "แคสต์"

ตอนนี้เมื่อเริ่มต้น GCKCastContext แล้ว เราต้องเพิ่มปุ่มแคสต์เพื่อให้ผู้ใช้เลือกอุปกรณ์แคสต์ได้ Cast SDK มีคอมโพเนนต์ปุ่มแคสต์ที่เรียกว่า GCKUICastButton เป็นคลาสย่อยของ UIButton คุณเพิ่มได้ในแถบชื่อของแอปพลิเคชันโดยการใส่ไว้ใน UIBarButtonItem เราต้องเพิ่มปุ่มแคสต์ลงในทั้ง MediaTableViewController และ MediaViewController

เพิ่มโค้ดต่อไปนี้ลงใน MediaTableViewController.swift และ 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)

    ...
  }
  ...
}

จากนั้นเพิ่มโค้ดต่อไปนี้ลงใน MediaViewController.swift

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)

    ...
  }
  ...
}

ตอนนี้ให้เรียกใช้แอป คุณจะเห็นปุ่มแคสต์ในแถบนำทางของแอป และเมื่อคลิกปุ่มนี้ ระบบจะแสดงรายการอุปกรณ์แคสต์ในเครือข่ายภายใน GCKCastContext จะจัดการการค้นพบอุปกรณ์โดยอัตโนมัติ เลือกอุปกรณ์แคสต์ แล้วแอปตัวอย่างตัวรับจะโหลดในอุปกรณ์แคสต์ คุณสามารถไปยังส่วนต่างๆ ระหว่างกิจกรรมการเรียกดูและกิจกรรมของโปรแกรมเล่นในเครื่องได้ และระบบจะซิงค์สถานะปุ่มแคสต์ไว้

เรายังไม่ได้เชื่อมต่อการรองรับการเล่นสื่อ คุณจึงยังเล่นวิดีโอบนอุปกรณ์ Cast ไม่ได้ คลิกปุ่มแคสต์เพื่อหยุดแคสต์

6. การแคสต์เนื้อหาวิดีโอ

ภาพ iPhone ที่เรียกใช้แอป CastVideos ซึ่งแสดงรายละเอียดของวิดีโอหนึ่งๆ ("Tears of Steel") ที่ด้านล่างคือมินิเพลเยอร์

เราจะขยายแอปตัวอย่างให้เล่นวิดีโอจากระยะไกลบนอุปกรณ์ Cast ได้ด้วย โดยเราต้องฟังเหตุการณ์ต่างๆ ที่เฟรมเวิร์ก Cast สร้างขึ้น

การแคสต์สื่อ

ในระดับสูง หากต้องการเล่นสื่อบนอุปกรณ์แคสต์ จะต้องมีสิ่งต่อไปนี้

  1. สร้างออบเจ็กต์ GCKMediaInformation จาก Cast SDK ที่จำลองรายการสื่อ
  2. ผู้ใช้เชื่อมต่อกับอุปกรณ์แคสต์เพื่อเปิดแอปพลิเคชันตัวรับ
  3. โหลดGCKMediaInformationออบเจ็กต์ลงในตัวรับและเล่นเนื้อหา
  4. ติดตามสถานะสื่อ
  5. ส่งคำสั่งการเล่นไปยังตัวรับสัญญาณตามการโต้ตอบของผู้ใช้

ขั้นตอนที่ 1 คือการแมปออบเจ็กต์หนึ่งกับอีกออบเจ็กต์หนึ่ง GCKMediaInformation คือสิ่งที่ Cast SDK เข้าใจ และ MediaItem คือการแคปซูลรายการสื่อของแอป เราสามารถแมป MediaItem กับ GCKMediaInformation ได้อย่างง่ายดาย เราได้ทำขั้นตอนที่ 2 ในส่วนก่อนหน้าแล้ว ขั้นตอนที่ 3 ทำได้ง่ายๆ ด้วย Cast SDK

แอปตัวอย่าง MediaViewController แยกความแตกต่างระหว่างการเล่นในเครื่องกับการเล่นจากระยะไกลโดยใช้การแจงนับนี้อยู่แล้ว

enum PlaybackMode: Int {
  case none = 0
  case local
  case remote
}

private var playbackMode = PlaybackMode.none

คุณไม่จำเป็นต้องเข้าใจวิธีการทำงานของตรรกะผู้เล่นตัวอย่างทั้งหมดอย่างละเอียดใน Codelab นี้ โปรดทราบว่าคุณจะต้องแก้ไขโปรแกรมเล่นสื่อของแอปเพื่อให้รับรู้ถึงตำแหน่งการเล่นทั้ง 2 ตำแหน่งในลักษณะเดียวกัน

ปัจจุบันเพลเยอร์ในเครื่องจะอยู่ในสถานะการเล่นในเครื่องเสมอ เนื่องจากยังไม่ทราบสถานะการแคสต์ เราต้องอัปเดต UI ตามการเปลี่ยนสถานะที่เกิดขึ้นในเฟรมเวิร์ก Cast เช่น หากเริ่มแคสต์ เราจะต้องหยุดการเล่นในเครื่องและปิดใช้การควบคุมบางอย่าง ในทำนองเดียวกัน หากเราหยุดแคสต์เมื่ออยู่ในตัวควบคุมมุมมองนี้ เราต้องเปลี่ยนไปเล่นในเครื่อง หากต้องการจัดการกับเหตุการณ์ดังกล่าว เราต้องรับฟังเหตุการณ์ต่างๆ ที่เฟรมเวิร์ก Cast สร้างขึ้น

การจัดการเซสชันการแคสต์

สำหรับเฟรมเวิร์ก Cast เซสชัน Cast จะรวมขั้นตอนการเชื่อมต่อกับอุปกรณ์ การเปิด (หรือเข้าร่วม) การเชื่อมต่อกับแอปพลิเคชันตัวรับ และการเริ่มต้นช่องควบคุมสื่อหากเหมาะสม ช่องควบคุมสื่อคือวิธีที่เฟรมเวิร์ก Cast ใช้ส่งและรับข้อความจากเครื่องเล่นสื่อตัวรับ

ระบบจะเริ่มเซสชันการแคสต์โดยอัตโนมัติเมื่อผู้ใช้เลือกอุปกรณ์จากปุ่มแคสต์ และจะหยุดเซสชันโดยอัตโนมัติเมื่อผู้ใช้ยกเลิกการเชื่อมต่อ นอกจากนี้ เฟรมเวิร์ก Cast ยังจัดการการเชื่อมต่อเซสชันตัวรับสัญญาณอีกครั้งโดยอัตโนมัติเนื่องจากปัญหาเกี่ยวกับเครือข่าย

GCKSessionManager เป็นผู้จัดการเซสชันการแคสต์ ซึ่งเข้าถึงได้ผ่าน GCKCastContext.sharedInstance().sessionManager GCKSessionManagerListener Callback สามารถใช้เพื่อตรวจสอบเหตุการณ์เซสชัน เช่น การสร้าง การระงับ การกลับมาทำงานต่อ และการสิ้นสุด

ก่อนอื่นเราต้องลงทะเบียนเครื่องมือฟังเซสชันและเริ่มต้นตัวแปรบางรายการ

class MediaViewController: UIViewController, GCKSessionManagerListener,
  GCKRemoteMediaClientListener, LocalPlayerViewDelegate, GCKRequestDelegate {

  ...
  private var sessionManager: GCKSessionManager!
  ...

  required init?(coder: NSCoder) {
    super.init(coder: coder)

    sessionManager = GCKCastContext.sharedInstance().sessionManager

    ...
  }

  override func viewWillAppear(_ animated: Bool) {
    ...

    let hasConnectedSession: Bool = (sessionManager.hasConnectedSession())
    if hasConnectedSession, (playbackMode != .remote) {
      populateMediaInfo(false, playPosition: 0)
      switchToRemotePlayback()
    } else if sessionManager.currentSession == nil, (playbackMode != .local) {
      switchToLocalPlayback()
    }

    sessionManager.add(self)

    ...
  }

  override func viewWillDisappear(_ animated: Bool) {
    ...

    sessionManager.remove(self)
    sessionManager.currentCastSession?.remoteMediaClient?.remove(self)
    ...
    super.viewWillDisappear(animated)
  }

  func switchToLocalPlayback() {
    ...

    sessionManager.currentCastSession?.remoteMediaClient?.remove(self)

    ...
  }

  func switchToRemotePlayback() {
    ...

    sessionManager.currentCastSession?.remoteMediaClient?.add(self)

    ...
  }


  // MARK: - GCKSessionManagerListener

  func sessionManager(_: GCKSessionManager, didStart session: GCKSession) {
    print("MediaViewController: sessionManager didStartSession \(session)")
    setQueueButtonVisible(true)
    switchToRemotePlayback()
  }

  func sessionManager(_: GCKSessionManager, didResumeSession session: GCKSession) {
    print("MediaViewController: sessionManager didResumeSession \(session)")
    setQueueButtonVisible(true)
    switchToRemotePlayback()
  }

  func sessionManager(_: GCKSessionManager, didEnd _: GCKSession, withError error: Error?) {
    print("session ended with error: \(String(describing: error))")
    let message = "The Casting session has ended.\n\(String(describing: error))"
    if let window = appDelegate?.window {
      Toast.displayMessage(message, for: 3, in: window)
    }
    setQueueButtonVisible(false)
    switchToLocalPlayback()
  }

  func sessionManager(_: GCKSessionManager, didFailToStartSessionWithError error: Error?) {
    if let error = error {
      showAlert(withTitle: "Failed to start a session", message: error.localizedDescription)
    }
    setQueueButtonVisible(false)
  }

  func sessionManager(_: GCKSessionManager,
                      didFailToResumeSession _: GCKSession, withError _: Error?) {
    if let window = UIApplication.shared.delegate?.window {
      Toast.displayMessage("The Casting session could not be resumed.",
                           for: 3, in: window)
    }
    setQueueButtonVisible(false)
    switchToLocalPlayback()
  }

  ...
}

ใน MediaViewController เราต้องการทราบเมื่อมีการเชื่อมต่อหรือยกเลิกการเชื่อมต่อกับอุปกรณ์ Cast เพื่อให้เราสามารถเปลี่ยนไปใช้หรือออกจากเครื่องเล่นในเครื่องได้ โปรดทราบว่าการเชื่อมต่ออาจถูกขัดขวางไม่เพียงแต่โดยอินสแตนซ์ของแอปพลิเคชันที่ทำงานบนอุปกรณ์เคลื่อนที่ของคุณเท่านั้น แต่อาจถูกขัดขวางโดยอินสแตนซ์อื่นของแอปพลิเคชันของคุณ (หรือแอปพลิเคชันอื่น) ที่ทำงานบนอุปกรณ์เคลื่อนที่อื่นด้วย

คุณเข้าถึงเซสชันที่ใช้งานอยู่ในปัจจุบันได้ในชื่อ GCKCastContext.sharedInstance().sessionManager.currentCastSession ระบบจะสร้างและปิดเซสชันโดยอัตโนมัติเพื่อตอบสนองต่อท่าทางของผู้ใช้จากกล่องโต้ตอบการแคสต์

กำลังโหลดสื่อ

ใน Cast SDK GCKRemoteMediaClient มีชุด API ที่สะดวกสำหรับการจัดการการเล่นสื่อจากระยะไกลบนตัวรับ สำหรับ GCKCastSession ที่รองรับการเล่นสื่อ SDK จะสร้างอินสแตนซ์ของ GCKRemoteMediaClient โดยอัตโนมัติ โดยเข้าถึงได้ในฐานะพร็อพเพอร์ตี้ remoteMediaClient ของอินสแตนซ์ GCKCastSession

เพิ่มโค้ดต่อไปนี้ลงใน MediaViewController.swift เพื่อโหลดวิดีโอที่เลือกอยู่ในปัจจุบันบนตัวรับ

@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
      }
    }
  }
  ...
}

ตอนนี้ให้อัปเดตวิธีการที่มีอยู่ต่างๆ เพื่อใช้ตรรกะเซสชันการแคสต์เพื่อรองรับการเล่นจากระยะไกล

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
}

ตอนนี้ให้เรียกใช้แอปบนอุปกรณ์เคลื่อนที่ เชื่อมต่อกับอุปกรณ์แคสต์แล้วเริ่มเล่นวิดีโอ คุณควรเห็นวิดีโอเล่นบนอุปกรณ์รับสัญญาณ

7. มินิคอนโทรลเลอร์

รายการตรวจสอบการออกแบบ Cast กำหนดให้แอป Cast ทั้งหมดต้องมีมินิคอนโทรลเลอร์ปรากฏขึ้นเมื่อผู้ใช้ออกจากหน้าเนื้อหาปัจจุบัน ตัวควบคุมขนาดเล็กช่วยให้เข้าถึงได้ทันทีและมีการช่วยเตือนที่มองเห็นได้สำหรับเซสชันการแคสต์ปัจจุบัน

ภาพส่วนล่างของ iPhone ที่เรียกใช้แอป CastVideos โดยเน้นที่มินิคอนโทรลเลอร์

Cast SDK มีแถบควบคุม GCKUIMiniMediaControlsViewController ซึ่งเพิ่มลงในฉากที่คุณต้องการแสดงตัวควบคุมแบบถาวรได้

สำหรับแอปตัวอย่าง เราจะใช้ GCKUICastContainerViewController ซึ่งจะรวม View Controller อื่นและเพิ่ม GCKUIMiniMediaControlsViewController ที่ด้านล่าง

แก้ไขไฟล์ AppDelegate.swift แล้วเพิ่มโค้ดต่อไปนี้สำหรับเงื่อนไข if useCastContainerViewController ในวิธีต่อไปนี้

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()
  ...
}

เพิ่มพร็อพเพอร์ตี้และตัวตั้งค่า/ตัวรับค่านี้เพื่อควบคุมระดับการมองเห็นของมินิคอนโทรลเลอร์ (เราจะใช้พร็อพเพอร์ตี้เหล่านี้ในส่วนถัดไป)

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
      }
    }
  }

เรียกใช้แอปและแคสต์วิดีโอ เมื่อการเล่นเริ่มขึ้นบนเครื่องรับ คุณควรเห็นมินิคอนโทรลเลอร์ปรากฏที่ด้านล่างของแต่ละฉาก คุณควบคุมการเล่นจากระยะไกลได้โดยใช้มินิคอนโทรลเลอร์ หากคุณไปยังส่วนต่างๆ ระหว่างกิจกรรมการเรียกดูและกิจกรรมเพลเยอร์ในเครื่อง สถานะของมินิคอนโทรลเลอร์ควรซิงค์กับสถานะการเล่นสื่อของตัวรับสัญญาณ

8. การซ้อนทับช่วงแนะนำ

รายการตรวจสอบการออกแบบ Google Cast กำหนดให้แอปที่ส่งแนะนำปุ่มแคสต์แก่ผู้ใช้เดิมเพื่อแจ้งให้ทราบว่าตอนนี้แอปที่ส่งรองรับการแคสต์แล้ว และยังช่วยผู้ใช้ที่เพิ่งเริ่มใช้ Google Cast ด้วย

ภาพ iPhone ที่เรียกใช้แอป CastVideos พร้อมปุ่มแคสต์ที่ซ้อนทับ โดยไฮไลต์ปุ่มแคสต์และแสดงข้อความ "แตะเพื่อแคสต์สื่อไปยังทีวีและลำโพง"

คลาส GCKCastContext มีเมธอด presentCastInstructionsViewControllerOnce ที่ใช้ไฮไลต์ปุ่มแคสต์เมื่อแสดงต่อผู้ใช้เป็นครั้งแรกได้ เพิ่มโค้ดต่อไปนี้ลงใน MediaViewController.swift และ 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)
  }
}

เรียกใช้แอปในอุปกรณ์เคลื่อนที่ แล้วคุณจะเห็นภาพซ้อนทับแนะนำ

9. ตัวควบคุมที่ขยายแล้ว

รายการตรวจสอบการออกแบบ Google Cast กำหนดให้แอปตัวส่งต้องมีตัวควบคุมแบบขยายสำหรับสื่อที่กำลังแคสต์ ตัวควบคุมแบบขยายคือตัวควบคุมขนาดเล็กเวอร์ชันเต็มหน้าจอ

ภาพ iPhone ที่เรียกใช้แอป CastVideos ซึ่งเล่นวิดีโอโดยมีตัวควบคุมแบบขยายปรากฏที่ด้านล่าง

ตัวควบคุมแบบขยายคือมุมมองแบบเต็มหน้าจอที่ให้คุณควบคุมการเล่นสื่อจากระยะไกลได้อย่างเต็มที่ มุมมองนี้ควรอนุญาตให้แอปแคสต์จัดการทุกด้านของเซสชันการแคสต์ที่จัดการได้ ยกเว้นการควบคุมระดับเสียงของตัวรับและวงจรเซสชัน (เชื่อมต่อ/หยุดแคสต์) นอกจากนี้ ยังให้ข้อมูลสถานะทั้งหมดเกี่ยวกับเซสชันสื่อ (อาร์ตเวิร์ก ชื่อ คำบรรยายแทนเสียง และอื่นๆ)

ฟังก์ชันการทำงานของมุมมองนี้ได้รับการติดตั้งใช้งานโดยคลาส GCKUIExpandedMediaControlsViewController

สิ่งแรกที่คุณต้องทำคือเปิดใช้ตัวควบคุมที่ขยายเริ่มต้นในบริบทการแคสต์ แก้ไข AppDelegate.swift เพื่อเปิดใช้ตัวควบคุมที่ขยายเริ่มต้น

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
    ...
  }
  ...
}

เพิ่มโค้ดต่อไปนี้ลงใน MediaViewController.swift เพื่อโหลดตัวควบคุมแบบขยายเมื่อผู้ใช้เริ่มแคสต์วิดีโอ

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

นอกจากนี้ ระบบจะเปิดตัวควบคุมแบบขยายโดยอัตโนมัติเมื่อผู้ใช้แตะตัวควบคุมขนาดเล็ก

เรียกใช้แอปและแคสต์วิดีโอ คุณควรเห็นตัวควบคุมแบบขยาย กลับไปที่รายการวิดีโอ แล้วคลิกตัวควบคุมขนาดเล็ก ระบบจะโหลดตัวควบคุมแบบขยายอีกครั้ง

10. เพิ่มการรองรับ Cast Connect

คลัง Cast Connect ช่วยให้แอปพลิเคชันตัวส่งที่มีอยู่สื่อสารกับแอปพลิเคชัน Android TV ผ่านโปรโตคอล Cast ได้ Cast Connect สร้างขึ้นบนโครงสร้างพื้นฐานของ Cast โดยแอป Android TV จะทำหน้าที่เป็นตัวรับ

แท็กเริ่มการทำงาน

ใน Podfile ให้ตรวจสอบว่า google-cast-sdk ชี้ไปที่ 4.4.8 ขึ้นไปตามที่ระบุไว้ด้านล่าง หากคุณแก้ไขไฟล์ ให้เรียกใช้ pod update จากคอนโซลเพื่อซิงค์การเปลี่ยนแปลงกับโปรเจ็กต์

pod 'google-cast-sdk', '>=4.4.8'

GCKLaunchOptions

หากต้องการเปิดตัวแอปพลิเคชัน Android TV หรือที่เรียกว่า Android Receiver เราต้องตั้งค่าแฟล็ก androidReceiverCompatible เป็น true ในออบเจ็กต์ GCKLaunchOptions ออบเจ็กต์ GCKLaunchOptions นี้จะกำหนดวิธีเปิดตัวเครื่องรับและส่งไปยัง GCKCastOptions ซึ่งตั้งค่าไว้ในอินสแตนซ์ที่ใช้ร่วมกันโดยใช้ GCKCastContext.setSharedInstanceWith

เพิ่มบรรทัดต่อไปนี้ลงใน AppDelegate.swift

let options = GCKCastOptions(discoveryCriteria:
                          GCKDiscoveryCriteria(applicationID: kReceiverAppID))
...
/** Following code enables CastConnect */
let launchOptions = GCKLaunchOptions()
launchOptions.androidReceiverCompatible = true
options.launchOptions = launchOptions

GCKCastContext.setSharedInstanceWith(options)

ตั้งค่าข้อมูลเข้าสู่ระบบการเปิดตัว

ในฝั่งผู้ส่ง คุณสามารถระบุ GCKCredentialsData เพื่อแสดงถึงผู้ที่เข้าร่วมเซสชันได้ credentials คือสตริงที่ผู้ใช้กำหนดได้ ตราบใดที่แอป ATV เข้าใจสตริงนั้น ระบบจะส่ง GCKCredentialsData ไปยังแอป Android TV ของคุณในระหว่างการเปิดตัวหรือเวลาเข้าร่วมเท่านั้น หากคุณตั้งค่าอีกครั้งขณะที่เชื่อมต่ออยู่ ระบบจะไม่ส่งค่าดังกล่าวไปยังแอป Android TV

หากต้องการตั้งค่าข้อมูลเข้าสู่ระบบเพื่อเปิดตัว คุณต้องกำหนด GCKCredentialsData ทุกเมื่อหลังจากตั้งค่า GCKLaunchOptions แล้ว เราจะสาธิตเรื่องนี้โดยเพิ่มตรรกะสำหรับปุ่ม Creds เพื่อตั้งค่าข้อมูลเข้าสู่ระบบที่จะส่งต่อเมื่อสร้างเซสชัน เพิ่มโค้ดต่อไปนี้ใน MediaTableViewController.swift

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))
  }
}

ตั้งค่าข้อมูลเข้าสู่ระบบในคำขอโหลด

หากต้องการจัดการ credentials ในทั้งแอปตัวรับสัญญาณบนเว็บและ Android TV ให้เพิ่มโค้ดต่อไปนี้ในคลาส MediaTableViewController.swift ภายใต้ฟังก์ชัน loadSelectedItem

let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
...
mediaLoadRequestDataBuilder.credentials = credentials
...

SDK จะใช้ข้อมูลเข้าสู่ระบบข้างต้นกับเซสชันที่กำลังดำเนินอยู่โดยอัตโนมัติ ทั้งนี้ขึ้นอยู่กับแอปตัวรับที่ผู้ส่งแคสต์

การทดสอบ Cast Connect

ขั้นตอนในการติดตั้ง Android TV APK บน Chromecast พร้อม Google TV

  1. ค้นหาที่อยู่ IP ของอุปกรณ์ Android TV โดยปกติแล้ว คุณจะดูได้ที่การตั้งค่า > เครือข่ายและอินเทอร์เน็ต > (ชื่อเครือข่ายที่อุปกรณ์เชื่อมต่ออยู่) ทางด้านขวาจะแสดงรายละเอียดและ IP ของอุปกรณ์ในเครือข่าย
  2. ใช้ที่อยู่ IP ของอุปกรณ์เพื่อเชื่อมต่อผ่าน ADB โดยใช้เทอร์มินัล
$ adb connect <device_ip_address>:5555
  1. จากหน้าต่างเทอร์มินัล ให้ไปที่โฟลเดอร์ระดับบนสุดสำหรับตัวอย่าง Codelab ที่คุณดาวน์โหลดไว้ตอนต้นของ Codelab นี้ เช่น
$ cd Desktop/ios_codelab_src
  1. ติดตั้งไฟล์ .apk ในโฟลเดอร์นี้ลงใน Android TV โดยเรียกใช้คำสั่งต่อไปนี้
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
  1. ตอนนี้คุณควรจะเห็นแอปชื่อ Cast Videos ในเมนูแอปของคุณบนอุปกรณ์ Android TV
  2. เมื่อเสร็จแล้ว ให้สร้างและเรียกใช้แอปในโปรแกรมจำลองหรืออุปกรณ์เคลื่อนที่ เมื่อสร้างเซสชันการแคสต์กับอุปกรณ์ Android TV แล้ว ตอนนี้เซสชันควรเปิดแอปพลิเคชันตัวรับสัญญาณ Android บน Android TV การเล่นวิดีโอจากอุปกรณ์ iOS ที่เป็นตัวส่งควรเปิดวิดีโอในตัวรับ Android และให้คุณควบคุมการเล่นโดยใช้รีโมตสำหรับอุปกรณ์ Android TV

11. ปรับแต่งวิดเจ็ต Cast

การเริ่มต้น

เริ่มต้นด้วยโฟลเดอร์ App-Done เพิ่มโค้ดต่อไปนี้ลงในเมธอด applicationDidFinishLaunchingWithOptions ในไฟล์ AppDelegate.swift

func application(_: UIApplication,
                 didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  ...
  let styler = GCKUIStyle.sharedInstance()
  ...
}

เมื่อปรับแต่งอย่างน้อย 1 รายการตามที่ระบุไว้ในส่วนที่เหลือของโค้ดแล็บนี้แล้ว ให้คอมมิตรูปแบบโดยเรียกใช้โค้ดด้านล่าง

styler.apply()

การปรับแต่งมุมมองการแคสต์

คุณปรับแต่งมุมมองทั้งหมดที่ Cast Application Framework จัดการได้โดยมีหลักเกณฑ์การจัดรูปแบบเริ่มต้นในมุมมองต่างๆ ตัวอย่างเช่น เราจะเปลี่ยนสีเฉดไอคอน

styler.castViews.iconTintColor = .lightGray

คุณสามารถลบล้างค่าเริ่มต้นในแต่ละหน้าจอได้หากจำเป็น เช่น หากต้องการลบล้าง lightGrayColor สำหรับสีการปรับสีไอคอนเฉพาะสำหรับตัวควบคุมสื่อแบบขยาย

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

การเปลี่ยนสี

คุณปรับแต่งสีพื้นหลังสำหรับทุกมุมมอง (หรือแต่ละมุมมองแยกกัน) ได้ โค้ดต่อไปนี้จะตั้งค่าสีพื้นหลังเป็นสีน้ำเงินสำหรับมุมมองทั้งหมดที่ Cast Application Framework จัดเตรียมไว้

styler.castViews.backgroundColor = .blue
styler.castViews.mediaControl.miniController.backgroundColor = .yellow

การเปลี่ยนแบบอักษร

คุณปรับแต่งแบบอักษรสำหรับป้ายกำกับต่างๆ ที่เห็นในมุมมองการแคสต์ได้ มาตั้งค่าแบบอักษรทั้งหมดเป็น "Courier-Oblique" เพื่อเป็นตัวอย่างกัน

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)

การเปลี่ยนรูปภาพปุ่มเริ่มต้น

เพิ่มรูปภาพที่กำหนดเองลงในโปรเจ็กต์ และกำหนดรูปภาพให้กับปุ่มเพื่อจัดรูปแบบ

let muteOnImage = UIImage.init(named: "yourImage.png")
if let muteOnImage = muteOnImage {
  styler.castViews.muteOnImage = muteOnImage
}

การเปลี่ยนธีมปุ่มแคสต์

นอกจากนี้ คุณยังกำหนดธีมให้วิดเจ็ต Cast ได้โดยใช้โปรโตคอล UIAppearance โค้ดต่อไปนี้จะกำหนดธีม GCKUICastButton ในมุมมองทั้งหมดที่ปรากฏ

GCKUICastButton.appearance().tintColor = UIColor.gray

12. ขอแสดงความยินดี

ตอนนี้คุณทราบวิธีเปิดใช้การแคสต์ในแอปวิดีโอโดยใช้วิดเจ็ต Cast SDK บน iOS แล้ว

ดูรายละเอียดเพิ่มเติมได้ในคู่มือสำหรับนักพัฒนาซอฟต์แวร์ iOS Sender