یک برنامه iOS را فعال کنید

1. بررسی اجمالی

نشان‌واره Google Cast

این لبه کد به شما می آموزد که چگونه یک برنامه ویدیویی iOS موجود را تغییر دهید تا محتوا را در یک دستگاه دارای Google Cast فعال کنید.

Google Cast چیست؟

Google Cast به کاربران امکان می دهد محتوا را از دستگاه تلفن همراه به تلویزیون ارسال کنند. سپس کاربران می توانند از دستگاه تلفن همراه خود به عنوان یک کنترل از راه دور برای پخش رسانه در تلویزیون استفاده کنند.

Google Cast SDK به شما امکان می دهد برنامه خود را گسترش دهید تا دستگاه های دارای Google Cast را کنترل کنید (مانند تلویزیون یا سیستم صوتی). Cast SDK به شما امکان می دهد اجزای رابط کاربری لازم را بر اساس چک لیست طراحی Google Cast اضافه کنید.

چک لیست طراحی Google Cast برای ساده و قابل پیش بینی کردن تجربه کاربر Cast در همه پلتفرم های پشتیبانی شده ارائه شده است.

قرار است چه چیزی بسازیم؟

وقتی این کد لبه را تکمیل کردید، یک برنامه ویدیویی iOS خواهید داشت که می‌تواند ویدیوها را به دستگاه Google Cast ارسال کند.

چیزی که یاد خواهید گرفت

  • چگونه Google Cast SDK را به یک برنامه ویدیویی نمونه اضافه کنیم.
  • نحوه اضافه کردن دکمه Cast برای انتخاب دستگاه Google Cast.
  • نحوه اتصال به دستگاه Cast و راه اندازی گیرنده رسانه.
  • نحوه پخش ویدیو
  • چگونه مینی کنترلر Cast را به برنامه خود اضافه کنید.
  • نحوه اضافه کردن یک کنترلر توسعه یافته
  • نحوه ارائه یک پوشش مقدماتی
  • چگونه ویجت‌های Cast را سفارشی کنیم.
  • نحوه ادغام Cast Connect

آنچه شما نیاز دارید

  • جدیدترین Xcode .
  • یک دستگاه تلفن همراه با iOS 9 یا جدیدتر (یا شبیه ساز Xcode).
  • یک کابل داده USB برای اتصال دستگاه تلفن همراه شما به رایانه توسعه (در صورت استفاده از دستگاه).
  • یک دستگاه Google Cast مانند Chromecast یا Android TV که با دسترسی به اینترنت پیکربندی شده است.
  • تلویزیون یا مانیتور با ورودی HDMI.
  • برای آزمایش ادغام Cast Connect به Chromecast با Google TV نیاز است، اما برای بقیه Codelab اختیاری است. اگر یکی ندارید، در پایان این آموزش از مرحله Add Cast Connect Support رد شوید.

تجربه

  • شما باید دانش قبلی توسعه iOS را داشته باشید.
  • شما همچنین به دانش قبلی در مورد تماشای تلویزیون نیاز دارید :)

چگونه از این آموزش استفاده خواهید کرد؟

فقط از طریق آن را بخوانید آن را بخوانید و تمرینات را کامل کنید

به تجربه خود از ساخت اپلیکیشن های iOS چه امتیازی می دهید؟

تازه کار حد واسط مسلط

تجربه خود را از تماشای تلویزیون چگونه ارزیابی می کنید؟

تازه کار حد واسط مسلط

2. کد نمونه را دریافت کنید

می توانید تمام کدهای نمونه را در رایانه خود دانلود کنید ...

و فایل فشرده دانلود شده را باز کنید.

3. برنامه نمونه را اجرا کنید

لوگوی اپل iOS

ابتدا، بیایید ببینیم که برنامه نمونه تکمیل شده چگونه به نظر می رسد. این برنامه یک پخش کننده ویدیوی اساسی است. کاربر می تواند یک ویدیو را از یک لیست انتخاب کند و سپس می تواند ویدیو را به صورت محلی در دستگاه پخش کند یا آن را به دستگاه Google Cast ارسال کند.

با دانلود کد، دستورالعمل های زیر نحوه باز کردن و اجرای برنامه نمونه تکمیل شده در Xcode را شرح می دهد:

سوالات متداول

راه اندازی CocoaPods

برای راه اندازی CocoaPods، به کنسول خود بروید و با استفاده از Ruby پیش فرض موجود در macOS نصب کنید:

sudo gem install cocoapods

اگر مشکلی دارید، برای دانلود و نصب Dependency Manager به مستندات رسمی مراجعه کنید.

راه اندازی پروژه

  1. به ترمینال خود بروید و به دایرکتوری Codelab بروید.
  2. وابستگی ها را از Podfile نصب کنید.
cd app-done
pod update
pod install
  1. Xcode را باز کرده و Open other project را انتخاب کنید...
  2. فایل CastVideos-ios.xcworkspace را از قسمت انتخاب کنید نماد پوشه دایرکتوری app-done در پوشه کد نمونه.

برنامه را اجرا کنید

هدف و شبیه ساز را انتخاب کنید و سپس برنامه را اجرا کنید:

نوار ابزار شبیه ساز برنامه XCode

پس از چند ثانیه باید برنامه ویدیویی ظاهر شود.

هنگامی که اعلان مربوط به پذیرش اتصالات شبکه ورودی ظاهر می شود، حتما روی «مجاز» کلیک کنید. اگر این گزینه پذیرفته نشود نماد Cast ظاهر نمی شود.

گفتگوی تأیید درخواست مجوز برای پذیرش اتصالات شبکه ورودی

روی دکمه Cast کلیک کنید و دستگاه Google Cast خود را انتخاب کنید.

یک ویدیو را انتخاب کنید، روی دکمه پخش کلیک کنید.

پخش ویدیو در دستگاه Google Cast شما شروع می شود.

کنترل کننده گسترش یافته نمایش داده می شود. می توانید از دکمه پخش/مکث برای کنترل پخش استفاده کنید.

به لیست ویدیوها برگردید.

اکنون یک مینی کنترلر در پایین صفحه قابل مشاهده است.

تصویری از آیفون در حال اجرا برنامه CastVideos با مینی کنترلر که در پایین ظاهر می شود

روی دکمه مکث در کنترلر کوچک کلیک کنید تا ویدیو روی گیرنده متوقف شود. برای ادامه پخش مجدد ویدیو، روی دکمه پخش در مینی کنترلر کلیک کنید.

روی دکمه Cast کلیک کنید تا ارسال به دستگاه Google Cast متوقف شود.

4. پروژه شروع را آماده کنید

تصویری از آیفون در حال اجرای برنامه CastVideos

باید پشتیبانی از Google Cast را به برنامه شروعی که دانلود کردید اضافه کنیم. در اینجا برخی از اصطلاحات Google Cast وجود دارد که در این کد لبه استفاده خواهیم کرد:

  • یک برنامه فرستنده روی دستگاه تلفن همراه یا لپ تاپ اجرا می شود،
  • یک برنامه گیرنده در دستگاه Google Cast اجرا می شود.

راه اندازی پروژه

اکنون شما آماده هستید تا با استفاده از Xcode در بالای پروژه شروع کننده بسازید:

  1. به ترمینال خود بروید و به دایرکتوری Codelab بروید.
  2. وابستگی ها را از Podfile نصب کنید.
cd app-start
pod update
pod install
  1. Xcode را باز کرده و Open other project را انتخاب کنید...
  2. فایل CastVideos-ios.xcworkspace را از قسمت انتخاب کنید نماد پوشه دایرکتوری app-start در پوشه کد نمونه.

طراحی اپلیکیشن

این برنامه لیستی از ویدیوها را از یک وب سرور راه دور دریافت می کند و فهرستی را برای مرورگر در اختیار کاربر قرار می دهد. کاربران می توانند یک ویدیو را برای دیدن جزئیات انتخاب کنند یا ویدیو را به صورت محلی در دستگاه تلفن همراه پخش کنند.

این برنامه از دو کنترلر اصلی تشکیل شده است: MediaTableViewController و MediaViewController.

MediaTableViewController

این UITableViewController لیستی از ویدیوها را از یک نمونه MediaListModel نمایش می دهد. لیست ویدیوها و ابرداده مرتبط با آنها در یک سرور راه دور به عنوان یک فایل JSON میزبانی می شود. MediaListModel این JSON را واکشی می کند و آن را برای ایجاد لیستی از اشیاء MediaItem پردازش می کند.

یک شی MediaItem یک ویدیو و ابرداده مرتبط با آن، مانند عنوان، توضیحات، URL برای یک تصویر و URL برای جریان را مدل می کند.

MediaTableViewController یک نمونه MediaListModel ایجاد می کند و سپس خود را به عنوان MediaListModelDelegate ثبت می کند تا از بارگیری فراداده رسانه مطلع شود تا بتواند نمای جدول را بارگیری کند.

به کاربر لیستی از تصاویر کوچک ویدیو با توضیحات کوتاه برای هر ویدیو ارائه می شود. هنگامی که یک مورد انتخاب می شود، MediaItem مربوطه به MediaViewController ارسال می شود.

MediaViewController

این کنترل‌کننده نمایش، ابرداده‌های مربوط به یک ویدیوی خاص را نمایش می‌دهد و به کاربر اجازه می‌دهد ویدیو را به صورت محلی در دستگاه تلفن همراه پخش کند.

کنترل‌کننده view میزبان LocalPlayerView ، برخی از کنترل‌های رسانه، و یک ناحیه متنی برای نمایش توضیحات ویدیوی انتخابی است. پخش کننده قسمت بالای صفحه را می پوشاند و فضایی را برای شرح دقیق ویدیو در زیر باز می کند. کاربر می تواند پخش/مکث یا جستجوی پخش محلی ویدیو را داشته باشد.

سوالات متداول

5. افزودن دکمه Cast

تصویر یک سوم بالای آیفونی که برنامه CastVideos را اجرا می کند، دکمه Cast را در گوشه سمت راست بالا نشان می دهد.

یک برنامه با قابلیت Cast، دکمه Cast را در هر یک از کنترل‌کننده‌های نمایش خود نمایش می‌دهد. با کلیک بر روی دکمه Cast، لیستی از دستگاه‌های Cast که کاربر می‌تواند انتخاب کند، نمایش داده می‌شود. اگر کاربر در دستگاه فرستنده محتوا را به صورت محلی پخش می کرد، انتخاب دستگاه Cast پخش را در آن دستگاه Cast شروع یا از سر می گیرد. در هر زمانی در طول جلسه Cast، کاربر می‌تواند روی دکمه Cast کلیک کرده و ارسال برنامه شما به دستگاه Cast را متوقف کند. همانطور که در چک لیست طراحی Google Cast توضیح داده شده است، کاربر باید بتواند در حالی که در هر صفحه ای از برنامه شما است، به دستگاه Cast متصل شود یا از آن جدا شود.

پیکربندی

پروژه شروع به همان وابستگی ها و تنظیمات Xcode نیاز دارد که برای برنامه نمونه تکمیل شده انجام دادید. به آن بخش بازگردید و همان مراحل را دنبال کنید تا GoogleCast.framework را به پروژه شروع برنامه اضافه کنید.

مقداردهی اولیه

چارچوب Cast دارای یک شی تک‌تنه جهانی به نام GCKCastContext است که همه فعالیت‌های چارچوب را هماهنگ می‌کند. این شی باید در اوایل چرخه عمر برنامه، معمولاً در روش application(_:didFinishLaunchingWithOptions:) از نماینده برنامه، مقداردهی اولیه شود، به طوری که از سرگیری جلسه خودکار در راه اندازی مجدد برنامه فرستنده به درستی راه اندازی شود و اسکن دستگاه ها شروع شود.

یک شی GCKCastOptions باید هنگام مقداردهی اولیه GCKCastContext ارائه شود. این کلاس شامل گزینه هایی است که بر رفتار فریم ورک تأثیر می گذارد. مهمترین آنها شناسه برنامه گیرنده است که برای فیلتر کردن نتایج کشف دستگاه Cast و راه اندازی برنامه گیرنده هنگام شروع جلسه Cast استفاده می شود.

متد application(_:didFinishLaunchingWithOptions:) نیز مکان خوبی برای راه اندازی یک نماینده ثبت گزارش برای دریافت پیام های گزارش گیری از چارچوب Cast است. اینها می توانند برای رفع اشکال و عیب یابی مفید باشند.

هنگامی که برنامه خود را با قابلیت Cast خود توسعه می دهید، باید به عنوان توسعه دهنده Cast ثبت نام کنید و سپس یک شناسه برنامه برای برنامه خود دریافت کنید. برای این کد لبه، از یک شناسه برنامه نمونه استفاده خواهیم کرد.

کد زیر را به 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)")
    }
  }
}

دکمه Cast

اکنون که GCKCastContext مقداردهی اولیه شده است، باید دکمه Cast را اضافه کنیم تا کاربر بتواند یک دستگاه Cast را انتخاب کند. Cast SDK یک مؤلفه دکمه Cast به نام GCKUICastButton را به عنوان زیر کلاس UIButton فراهم می کند. می توان آن را با قرار دادن آن در یک UIBarButtonItem به نوار عنوان برنامه اضافه کرد. باید دکمه Cast را هم به 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)

    ...
  }
  ...
}

حالا برنامه را اجرا کنید. باید یک دکمه Cast را در نوار ناوبری برنامه ببینید و وقتی روی آن کلیک می‌کنید، دستگاه‌های Cast را در شبکه محلی شما فهرست می‌کند. کشف دستگاه به طور خودکار توسط GCKCastContext مدیریت می شود. دستگاه Cast خود را انتخاب کنید و برنامه گیرنده نمونه در دستگاه Cast بارگیری می‌شود. می توانید بین فعالیت مرور و فعالیت پخش کننده محلی حرکت کنید و وضعیت دکمه Cast همگام نگه داشته می شود.

ما هیچ پشتیبانی برای پخش رسانه وصل نکرده‌ایم، بنابراین هنوز نمی‌توانید ویدیوها را در دستگاه Cast پخش کنید. برای توقف ارسال بر روی دکمه Cast کلیک کنید.

6. پخش محتوای ویدیویی

تصویری از آیفونی که برنامه CastVideos را اجرا می کند، که جزئیات یک ویدیوی خاص را نشان می دهد ("اشک های فولادی"). در پایین مینی پلیر قرار دارد

ما برنامه نمونه را گسترش می‌دهیم تا ویدیوها را از راه دور در دستگاه Cast پخش کند. برای انجام این کار، باید به رویدادهای مختلف تولید شده توسط چارچوب Cast گوش دهیم.

رسانه ریخته گری

در سطح بالا، اگر می‌خواهید رسانه‌ای را در دستگاه Cast پخش کنید، موارد زیر باید انجام شود:

  1. یک شی GCKMediaInformation از Cast SDK ایجاد کنید که یک آیتم رسانه را مدل می کند.
  2. کاربر برای راه اندازی برنامه گیرنده شما به دستگاه Cast متصل می شود.
  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

در این کد لبه برای شما مهم نیست که بدانید دقیقاً چگونه منطق پخش کننده نمونه کار می کند. درک این نکته مهم است که پخش کننده رسانه برنامه شما باید اصلاح شود تا از دو مکان پخش به روشی مشابه آگاه باشد.

در حال حاضر پخش کننده محلی همیشه در حالت پخش محلی است زیرا هنوز چیزی در مورد وضعیت های Casting نمی داند. ما باید رابط کاربری را بر اساس انتقال وضعیتی که در چارچوب Cast اتفاق می‌افتد، به‌روزرسانی کنیم. به عنوان مثال، اگر شروع به ارسال محتوا کنیم، باید پخش محلی را متوقف کنیم و برخی از کنترل ها را غیرفعال کنیم. به طور مشابه، اگر زمانی که در این نمایش کنترل هستیم، پخش را متوقف کنیم، باید به پخش محلی منتقل شویم. برای رسیدگی به آن باید به رویدادهای مختلف تولید شده توسط چارچوب Cast گوش دهیم.

مدیریت جلسه بازیگران

برای چارچوب Cast، یک جلسه Cast مراحل اتصال به یک دستگاه، راه‌اندازی (یا پیوستن)، اتصال به یک برنامه گیرنده، و راه‌اندازی یک کانال کنترل رسانه را در صورت لزوم ترکیب می‌کند. کانال کنترل رسانه نحوه ارسال و دریافت پیام‌ها از پخش‌کننده رسانه گیرنده توسط چارچوب Cast است.

وقتی کاربر دستگاهی را از روی دکمه Cast انتخاب می‌کند، جلسه Cast به‌طور خودکار شروع می‌شود و وقتی کاربر ارتباط خود را قطع می‌کند، به‌طور خودکار متوقف می‌شود. اتصال مجدد به جلسه گیرنده به دلیل مشکلات شبکه نیز به طور خودکار توسط چارچوب Cast انجام می شود.

جلسات Cast توسط GCKSessionManager مدیریت می‌شوند که از طریق GCKCastContext.sharedInstance().sessionManager قابل دسترسی است. از تماس‌های GCKSessionManagerListener می‌توان برای نظارت بر رویدادهای جلسه، مانند ایجاد، تعلیق، از سرگیری و خاتمه استفاده کرد.

ابتدا باید Session listener خود را ثبت کنیم و چند متغیر را مقداردهی اولیه کنیم:

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 ایجاد و پاره می شوند.

در حال بارگیری رسانه

در Cast SDK، GCKRemoteMediaClient مجموعه‌ای از APIهای راحت را برای مدیریت پخش رسانه از راه دور در گیرنده فراهم می‌کند. برای یک GCKCastSession که از پخش رسانه پشتیبانی می کند، یک نمونه از GCKRemoteMediaClient به طور خودکار توسط SDK ایجاد می شود. می توان به عنوان ویژگی 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
      }
    }
  }
  ...
}

اکنون روش‌های مختلف موجود را به‌روزرسانی کنید تا از منطق Cast Session برای پشتیبانی از پخش از راه دور استفاده کنید:

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
}

اکنون برنامه را روی دستگاه تلفن همراه خود اجرا کنید. به دستگاه Cast خود متصل شوید و شروع به پخش ویدیو کنید. شما باید ویدیو را در حال پخش روی گیرنده ببینید.

7. مینی کنترلر

چک لیست طراحی Cast مستلزم آن است که همه برنامه‌های Cast یک کنترل‌کننده کوچک ارائه دهند تا وقتی کاربر از صفحه محتوای فعلی دور می‌شود ظاهر شود. مینی کنترلر دسترسی فوری و یک یادآوری قابل مشاهده را برای جلسه Cast فعلی فراهم می کند.

تصویری از قسمت پایین آیفونی که برنامه 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()
  ...
}

برای کنترل نمایان بودن مینی کنترلر، این ویژگی و setter/getter را اضافه کنید (ما در بخش بعدی از آنها استفاده خواهیم کرد):

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 به یک برنامه فرستنده نیاز دارد تا دکمه Cast را به کاربران فعلی معرفی کند تا بدانند برنامه فرستنده اکنون از Casting پشتیبانی می کند و همچنین به کاربرانی که تازه وارد Google Cast شده اند کمک می کند.

تصویر آیفونی که برنامه CastVideos را با روکش دکمه Cast اجرا می‌کند، دکمه Cast را برجسته می‌کند و پیام «برای ارسال رسانه به تلویزیون و بلندگوهای خود لمس کنید»

کلاس GCKCastContext روشی دارد، presentCastInstructionsViewControllerOnce ، که می تواند برای برجسته کردن دکمه Cast در اولین نمایش داده شدن به کاربران استفاده شود. کد زیر را به 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 به یک برنامه فرستنده نیاز دارد تا کنترل‌کننده گسترده‌ای را برای رسانه در حال پخش فراهم کند. کنترلر توسعه یافته یک نسخه تمام صفحه از مینی کنترلر است.

تصویری از آیفونی که برنامه CastVideos را اجرا می‌کند در حال پخش یک ویدیو با کنترل‌کننده بازشده در پایین ظاهر می‌شود.

کنترلر گسترش یافته یک نمای تمام صفحه است که کنترل کامل پخش رسانه از راه دور را ارائه می دهد. این نما باید به یک برنامه ریخته گری اجازه دهد تا هر جنبه قابل مدیریت یک جلسه بازیگری را مدیریت کند، به استثنای کنترل صدای گیرنده و چرخه عمر جلسه (اتصال/توقف ارسال محتوا). همچنین تمام اطلاعات وضعیت جلسه رسانه (آثار هنری، عنوان، زیرنویس و غیره) را ارائه می دهد.

عملکرد این نما توسط کلاس GCKUIExpandedMediaControlsViewController پیاده سازی شده است.

اولین کاری که باید انجام دهید این است که کنترلر توسعه یافته پیش فرض را در زمینه Cast فعال کنید. برای فعال کردن کنترلر توسعه یافته پیش فرض، 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 نیز گفته می‌شود، باید پرچم androidReceiverCompatible را در شیء GCKLaunchOptions روی true تنظیم کنیم. این شیء 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 شما منتقل نخواهد شد.

برای تنظیم Launch Credentials، 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 در برنامه های Web و Android TV Receiver، کد زیر را در کلاس 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 که در ابتدای این کد لبه دانلود کرده‌اید، بروید. مثلا:
$ 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 Receiver را در 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()
  ...
}

پس از انجام اعمال یک یا چند سفارشی سازی همانطور که در ادامه این کد لبه ذکر شد، استایل ها را با فراخوانی کد زیر انجام دهید.

styler.apply()

سفارشی کردن نماهای Cast

می‌توانید تمام نماهایی را که 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

همچنین می‌توانید ابزارک‌های Cast را با استفاده از پروتکل UIAppearance قالب‌بندی کنید. کد زیر GCKUICastButton را در تمام نماهایی که ظاهر می‌شود مضمون می‌کند:

GCKUICastButton.appearance().tintColor = UIColor.gray

12. تبریک می گویم

اکنون می‌دانید که چگونه می‌توانید یک برنامه ویدیویی را با استفاده از ابزارک‌های Cast SDK در iOS فعال کنید.

برای جزئیات بیشتر، به راهنمای توسعه دهنده iOS Sender مراجعه کنید.