无法在iOS应用中通过Google投射正确的视频 [英] Can't cast video via google cast correctly in ios app
问题描述
我正在基于AVPlayer使用自定义视频播放器进行项目开发。试图整合Google Cast。我已经基于Google tut进行了集成: https://codelabs.developers。 google.com/codelabs/cast-videos-ios/
但可以迅速转换。投放时,如果视频播放器打开,并且连接了设备(或者从面板连接),一切似乎都可以正常工作,我形成了文件的元信息,并将其传递给了Google投射-一切正常。
I'm working on a project with custom video player, based on AVPlayer. Trying to integrate google cast. I've made integration based on google tuts: https://codelabs.developers.google.com/codelabs/cast-videos-ios/ But with conversion to swift. Everything seems to work fine, when cast, if video player opens, and there is connected device (or if I connect from panel), I form meta info for file, and it's passed to google cast - everything works fine.
但是,我有一个奇怪的行为:
1)开始投射,打开视频,然后是另一个视频,然后是第三个视频。
2)停止投射
3)转到另一个视频,启用投射功能,但它不会开始播放此视频。它开始投射我之前打开的第一个视频。...
But, i have strange behavior: 1) Start casting, open video, then another video, then third video. 2) Stop casting 3) Go to another video, enable casting, but it doesn't start this video. It start casting the first video I opened earlier....
我试图找到清除缓存或队列的任何方法,但是没有。.请帮助
I tried to find any method that clears cache or queue, but there is 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
}
}}
和我的appdelegate:
and my appdelegate:
class AppDelegate:UIResponder,UIApplicationDelegate,GCKLoggerDelegate,UNUserNotificationCenterDelegate {
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)")
}}
推荐答案
可能的解决方案可能是由于:
On possible solution could be due to:
sessionManager?.add(self)
您添加了委托,但您一点都没有清除它。结果,由于会话管理器保留了引用, VideoVC
从未被销毁。当您重新打开 VideoVC
时,会话管理器仍从第一次加载该委托开始就对其进行访问。
You add the delegate but at no point do you clear it. As a result, the VideoVC
is never destroyed due to the retained reference from the session manager. When you reopen the VideoVC
the session manager is still also accessing the delegate from the first time you loaded it.
因此,在调用以下命令时:
Because of this, when the following is called:
func sessionManager(_ sessionManager: GCKSessionManager, didStart session: GCKSession) {
这是在您的 VideoVC
的第一个实例中调用的
This is being called in your first instance of VideoVC
which now has the wrong file information.
您可以通过将print(self)放入上述方法并查看内存指针值来监视此信息。检查它是否也与 viewDidLoad
You can monitor this by putting a print(self) into the above method and look at the memory pointer value. Check that it also matches the same memory pointer value that is called in viewDidLoad
更新中调用的相同的内存指针值匹配>
Update
要更好地管理委托,请更改以下方法: viewDidDisappear()
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)
}
这篇关于无法在iOS应用中通过Google投射正确的视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!