Cannot enable video using Google to work correctly in the iOS app.

I am working on a project with a custom video player based on AVPlayer. Trying to integrate Google. I did integration based on google tuts: https://codelabs.developers.google.com/codelabs/cast-videos-ios/ But with conversion to fast. It seems that everything works fine when you shoot, if the video player opens, and there is a connected device (or if I connect from the panel), I generate meta-information for the file, and it is transmitted to google cast - everything works fine.

But I have a strange behavior: 1) Start casting, open the video, then another video, then the third video. 2) Stop casting 3) Switch to another video, enable casting, but it does not start this video. First, it launches the first video that I opened earlier.

I tried to find any method that clears the cache or queue, but no. Please, help

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

and my 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)") }} 
+5
source share
1 answer

A possible solution may be caused by:

 sessionManager?.add(self) 

You add a delegate, but in no case clear it. As a result, VideoVC never destroyed due to a saved link from the session manager. When you reopen VideoVC session manager still also accesses the delegate the first time you download it.

Because of this, when the following is called:

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

This is called on your first instance of VideoVC , which now has the wrong file information.

You can control this by placing a print (self) in the above method and look at the value of the memory pointer. Make sure that it also matches the same memory pointer value that is called in viewDidLoad

Update

To better manage the delegate, change the following method: 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) } 
+1
source

Source: https://habr.com/ru/post/1264574/


All Articles