2017-02-22 2 views
5

Я работаю над проектом с пользовательским видеоплеером на основе AVPlayer. Попытка интегрировать Google. Я сделал интеграцию на основе google tuts: https://codelabs.developers.google.com/codelabs/cast-videos-ios/ Но с преобразованием в быстрый. Кажется, что все работает нормально, когда вы снимаете, если видеопроигрыватель открывается, и есть подключенное устройство (или если я подключаюсь с панели), я формирую метаинформацию для файла, и она передается в google cast - все работает нормально.Невозможно выполнить видеоролик с помощью Google, установленного в приложении 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:

класс 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)") 
}} 
+0

Пожалуйста уменьшить образец кода только часть, которая испытывает проблему. В настоящее время сложно найти проблематичную часть – Alistra

+0

Конечно, уменьшенный код только для методов google cast и добавление делегата с методами литья –

ответ

1

О возможном решении может быть связано с:

sessionManager?.add(self) 

Вы добавляете делегата, но ни в коем случае не очищаете его. В результате VideoVC никогда не уничтожается из-за сохраненной ссылки от диспетчера сеансов. Когда вы снова открываете VideoVC, диспетчер сеансов по-прежнему также получает доступ к делегату с первого раза, когда вы его загрузили.

Из-за этого, когда следующий называются:

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

Это вызывается в первом экземпляре VideoVC, который теперь имеет неверную информацию об файле.

Вы можете отслеживать это, помещая печать (self) в указанный выше метод и просматривая значение указателя памяти. Убедитесь, что она также совпадает с тем же значение указателя памяти, который вызывается в viewDidLoad

Update

Чтобы лучше управлять делегат изменить следующий метод: 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) 
} 
+0

да, Мэтью, вы правы, делегат печатает первый указатель памяти, который не то же самое, что и в viewdidload. Как я могу сбросить или удалить себя после увольнения или когда отключение отключено? –

+0

Я обновил свой ответ для вас Руслан :) –

+0

сейчас работает, спасибо! –

Смежные вопросы