无法在ios应用中通过Google正确投射视频

时间:2017-02-22 14:25:07

标签: ios swift chromecast google-cast

我正在使用基于AVPlayer的自定义视频播放器开展项目。试图整合谷歌演员。我已经基于Google tuts进行了整合:https://codelabs.developers.google.com/codelabs/cast-videos-ios/ 但随着转换迅速。一切似乎工作正常,如果投射,如果视频播放器打开,并且有连接的设备(或者如果我从面板连接),我形成文件的元信息,并且它传递给谷歌演员 - 一切正常。

但是,我有一些奇怪的行为: 1)开始投射,打开视频,然后是另一个视频,然后是第三个视频。 2)停止铸造 3)转到另一个视频,启用转换,但它不会启动此视频。它开始播放我之前打开的第一个视频....

我试图找到任何清除缓存或队列的方法,但没有..请帮助

class VideoVC: UIViewController, UIGestureRecognizerDelegate, GCKSessionManagerListener {

var filmTitle: String!
var toPass: String!
var film: MovieDetails!
var filmDetails: Movie!
var sessionManager: GCKSessionManager?
var castSession: GCKCastSession?
var castMediaController: GCKUIMediaController?
var checkPlayed = 0

override func viewDidLoad() {
    super.viewDidLoad()
    sessionManager = GCKCastContext.sharedInstance().sessionManager

    sessionManager?.add(self)

    castMediaController = GCKUIMediaController()
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)


    if let videoURL = toPass {

        if let video = URL(string: videoURL) {
            player = AVPlayer(url: video)

            player.allowsExternalPlayback = true
            player.usesExternalPlaybackWhileExternalScreenIsActive = true

            playerController.player = player
            self.addChildViewController(playerController)
            self.view.addSubview(playerController.view)
            playerController.view.frame = self.view.frame
            self.view.sendSubview(toBack: playerController.view)
        }
    }

    if isCastEnabled() {
        playSelectedItemRemotely()
    }
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)

    player.replaceCurrentItem(with: nil)

}

func buildMediaInformation() -> GCKMediaInformation {
    let metaData = GCKMediaMetadata(metadataType: GCKMediaMetadataType(rawValue: 1)!)

    metaData.setString(filmTitle, forKey: kGCKMetadataKeyTitle)

    if let imageUrl = URL(string: filmDetails.poster_cast!) {
        let image = GCKImage(url: imageUrl, width: 340, height: 450)
        metaData.addImage(image)
    }

    if let episode = film.serial_episode, let season = film.serial_season, season != "", episode != "", let title = film.title, title != "" {
        let subtitle = "\(title) \(episode) серия \(season) сезон"
        metaData.setString(subtitle, forKey: kGCKMetadataKeySubtitle)
    }


    let duration = Double(film.duration!)

    let mediaInfo = GCKMediaInformation(contentID: toPass!,
                                        streamType: GCKMediaStreamType.buffered,
                                        contentType: film.contentType!,
                                        metadata: metaData as GCKMediaMetadata,
                                        streamDuration: duration,
                                        mediaTracks: nil,
                                        textTrackStyle: nil,
                                        customData: nil)

    print("toPass: \(toPass!)")
    print("duration: \(duration)")

    return mediaInfo
}

func playSelectedItemRemotely() {

    let castSession = GCKCastContext.sharedInstance().sessionManager.currentCastSession
    if (castSession != nil) {
        castSession?.remoteMediaClient?.loadMedia(self.buildMediaInformation(), autoplay: true)
        self.dismiss(animated: true, completion: nil)
    }
    else {
        print("no castSession!")
    }
}

func sessionManager(_ sessionManager: GCKSessionManager, didStart session: GCKSession) {
    playSelectedItemRemotely()
}

func sessionManager(_ sessionManager: GCKSessionManager, didResumeSession session: GCKSession) {

}

func sessionManager(_ sessionManager: GCKSessionManager, didEnd session: GCKSession, withError error: Error?) {
    let castSession = GCKCastContext.sharedInstance().sessionManager.currentCastSession
    castSession?.endAndStopCasting(true)
}

func sessionManager(_ sessionManager: GCKSessionManager, didFailToStart session: GCKSession, withError error: Error) {
    Utils.showOverAnyVC("Ошибка подключения", message: "Попробуйте еще раз!")
}

func isCastEnabled() -> Bool {
    switch GCKCastContext.sharedInstance().castState {
    case GCKCastState.connected:
        print("cast connected")
        return true
    case GCKCastState.connecting:
        print("cast connecting")
        return true
    case GCKCastState.notConnected:
        print("cast notConnected")
        return false
    case GCKCastState.noDevicesAvailable:
        print("cast noDevicesAvailable")
        return false
    }
}}

和我的appdelegate:

class AppDelegate:UIResponder,UIApplicationDelegate,GCKLoggerDelegate,UNUserNotificationCenterDelegate {

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    let options = GCKCastOptions(receiverApplicationID: "F443E49F")
    GCKCastContext.setSharedInstanceWith(options)

    GCKLogger.sharedInstance().delegate = self

    let appStoryboard = UIStoryboard(name: "NewMain", bundle: nil)
    let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation")
    let castContainerVC: GCKUICastContainerViewController = GCKCastContext.sharedInstance().createCastContainerController(for: navigationController)
    castContainerVC.miniMediaControlsItemEnabled = true
    self.window = UIWindow(frame: UIScreen.main.bounds)
    self.window?.rootViewController = castContainerVC
    self.window?.makeKeyAndVisible()

    GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true

    return true
}



func logMessage(_ message: String, fromFunction function: String) {
    print("message: \(function)")
}}

1 个答案:

答案 0 :(得分:1)

可能的解决方案可能是由于:

sessionManager?.add(self)

您添加了委托,但在任何时候都没有清除它。因此,由于会话管理器保留的引用,VideoVC永远不会被销毁。当您重新打开VideoVC时,会话管理器仍然在您第一次加载时仍然访问该委托。

因此,当调用以下内容时:

func sessionManager(_ sessionManager: GCKSessionManager, didStart session: GCKSession) {

这是在VideoVC的第一个实例中调用的,它现在有错误的文件信息。

您可以通过将print(self)放入上述方法并查看内存指针值来监视此情况。检查它是否与viewDidLoad

中调用的相同内存指针值匹配

<强>更新

为了更好地管理委托,请更改以下方法:viewDidDisappear()

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    player.replaceCurrentItem(with: nil)

    //this stops the session manager sending callbacks to your VideoVC
    sessionManager.remove(self)
}