我创建了一个简单的AppleTV项目,按类别显示多个视频,浏览和播放视频工作正常.它已经被实现为使用TVML和TVJS的客户端 – 服务器应用程序,因此大多数应用程序逻辑都在
Javascript文件中.这些是在动态内容的背景下静态生成的.
然后我在应用程序中添加了一个TopShelf扩展,从API中提取了一些特色视频,这也工作正常,按预期拉入视频.
我遇到的问题是检测并响应用户从顶层架子上选择视频.我创建了一个URL方案exampletvapp://我在plist文件中注册了该方案.
我还将displayURL和playURL添加到TVContentItems.选择其中一个视频时,我的应用程序按预期启动,但实际上并未处理该视频的播放.
在我的AppDelegate文件中,我添加了print语句来打印launchOptions并添加了一个openUrl函数,该函数会被调用,但只有在我关闭应用程序并在应用程序关闭之前快速从顶层架构中选择一些内容时才会记录这个函数并且我会丢失调试会话.
// AppDelegate
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
print("App Launch: \(launchOptions)")
window = UIWindow(frame: UIScreen.mainScreen().bounds)
let appControllerContext = TVApplicationControllerContext()
guard let javaScriptURL = NSURL(string: AppDelegate.TVBootURL) else {
fatalError("unable to create NSURL")
}
appControllerContext.javaScriptApplicationURL = javaScriptURL
appControllerContext.launchOptions["BASEURL"] = AppDelegate.TVBaseURL
if let options = launchOptions {
for (kind, value) in options {
if let kindStr = kind as? String {
appControllerContext.launchOptions[kindStr] = value
}
}
}
appController = TVApplicationController(context: appControllerContext, window: self.window, delegate: self)
return true
}
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
guard let javaScriptURL = NSURL(string: AppDelegate.TVBootURL) else {
fatalError("unable to create NSURL")
}
let appControllerContext = TVApplicationControllerContext()
appControllerContext.javaScriptApplicationURL = javaScriptURL
appControllerContext.launchOptions["BASEURL"] = AppDelegate.TVBaseURL
for (kind, value) in options {
appControllerContext.launchOptions[kind] = value
}
appController = TVApplicationController(context: appControllerContext, window: self.window, delegate: self)
return true
}
func application(application: UIApplication, handleOpenURL url: NSURL) -> Bool {
print("handle Url called")
}
使用Javascript:
// Application.js
App.onLaunch = function(options) {
var javascriptFiles = [
`${options.BASEURL}js/ResourceLoader.js`,
`${options.BASEURL}js/Presenter.js`
];
console.log("options", options);
我已经在JS文件中添加了一个console.log来检查选项是否被传递,但它没有记录任何内容.我的意图是创建一个Player对象,其中只有TopShelf中所选视频的播放列表.但由于URL似乎只传递了ID,这意味着我需要发出ajax请求来获取视频信息,即使我已经在TVContentItem中使用了它.
所以我的问题是:我是否应该将topshelf中的视频本地添加到播放列表中并播放(使用Swift)或将详细信息传递到javascript端以便播放.如果是javascript有没有办法看到console.log的输出?因为我没有看到任何使得它很难使用的东西.
更新:
我对此有了进一步了解,我发现(通过Apple Developer Forums)你可以通过Develop>将Safari连接到Apple TV的模拟器中的JS Context.设备菜单.我已经完成了这个,到目前为止,URL没有通过选项传递给JS. url被传递给openURL委托函数,该函数需要以某种方式传递给JS,或者我需要本地播放视频.
我目前正在调查本地播放视频,方法是在displayURL中传递所有必需的信息以创建TVContentItem.我无法看到从openURL方法将此对象传递给JS的方法,除非我创建一个新的上下文和控制器的实例(甚至可能不起作用)
最佳答案 我终于让这个本地工作了.我也设法通过将openUrl传递给JS来实现它,但对我来说似乎不太可靠.稍后我会进一步研究,我现在只需要这个工作.
下面的代码创建了一个AVPlayer和AVPlayerViewController并呈现了ViewController,并在完成时将其解散.到目前为止,我还没有发现这种方法存在任何问题,但我仍在测试中.
// AppDelegate.swift
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
let urlString = "http:\(url.path!)"
let url = NSURL(string: urlString)!
print("opening URL: \(url)")
let item = AVPlayerItem(URL: url)
// Need to listen to the end of the player so we can dismiss the AVPlayer
NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerDidFinishPlaying:", name: AVPlayerItemDidPlayToEndTimeNotification, object: item)
let player = AVPlayer(playerItem: item)
player.actionAtItemEnd = AVPlayerActionAtItemEnd.None
let playerVC = AVPlayerViewController()
playerVC.player = player
appController?.navigationController.presentViewController(playerVC, animated: true, completion: nil)
player.play()
return true
}
func playerDidFinishPlaying (note: NSNotification) {
// Dimiss the AVPlayer View Controller from the Navigation Controller
appController?.navigationController.dismissViewControllerAnimated(true, completion: nil)
}