使用流时 AVPlayer 实例始终为 nil
AVPlayer instance always nil when using stream
我正在尝试在 swift 上实施 EventChannel
以实现 flutter 方面。所以这就是我正在做的,
我是如何注册活动频道的,
public class SwiftMusicPlayer: NSObject, FlutterPlugin {
final var audioPlayer = AudioPlayer()
struct Constants {
static let methodChannelName = "MethodChannel"
static let durationEventChannel = "durationEventChannel"
...
}
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: Constants.methodChannelName, binaryMessenger: registrar.messenger())
let instance = SwiftMusicPlayer()
registrar.addMethodCallDelegate(instance, channel: channel)
let durationChannel = FlutterEventChannel(name: Constants.durationEventChannel, binaryMessenger: registrar.messenger())
durationChannel.setStreamHandler(AudioPlayer())
}
// The method calls
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let args = call.arguments as? Dictionary<String, Any>
switch call.method {
case Constants.preparePlayer:
audioPlayer.preparePlayer(path: args?[Constants.path] as? String, volume: args?[Constants.volume] as? Double,result: result)
break
case Constants.startPlayer:
audioPlayer.startPlayer(result: result)
break
case Constants.pausePlayer:
audioPlayer.pausePlayer(result)
break
case Constants.stopPlayer:
audioPlayer.stopPlayer(result)
break
}
}
}
AudioPlayer
class
class AudioPlayer : NSObject,FlutterStreamHandler{
var player: AVPlayer?
private var sink: FlutterEventSink?
// I'm initialising it using method call before doing anything
func preparePlayer(path: String?, volume: Double?,result: @escaping FlutterResult){
if(!(path ?? "").isEmpty){
let url = URL.init(fileURLWithPath: path!)
player = AVPlayer(url: url)
player?.volume = Float(volume ?? 1.0)
result(true)
} else {
result(FlutterError(code: "", message: "Path to file can't be empty or null", details: nil))
}
}
func startPlayer(result: @escaping FlutterResult){
do{
if(player?.status == .readyToPlay){
player?.play()
result(true)
}
} catch {
result(FlutterError(code: "", message: "Failed to start player", details: nil))
}
}
func pausePlayer(_ result: @escaping FlutterResult){
print(player?.currentItem?.duration.seconds)
player?.pause()
result(true)
}
//Here it is being nil
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
print(self?.player?.currentItem?.asset.duration)//<---prints always nil
sink = events
let interval = CMTimeMakeWithSeconds(0.5, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
//never goes inside because player is nil
player?.addPeriodicTimeObserver(forInterval: interval, queue: nil, using: {[weak self] time in
print(time)
self?.sink!(0)
})
return nil
}
func onCancel(withArguments arguments: Any?) -> FlutterError? {
sink = nil
timer.invalidate()
return nil
}
}
在这里,当我调用启动播放器时,它会播放音频文件。暂停和停止也有效。
现在,当我在 pausePlayer()
中调用 self?.player?.currentItem?.asset.duration
时,它确实给了我持续时间,但是当我尝试在 onListen()
函数中打印它时,它总是 returns nil。
当我尝试打印 AVPlayer
的实例时,这里是 player
,它也打印为 nil。
那么这里哪里做错了?
当我将 AudioPlayer()
实例传递给 setStreamHandler
时,它正在为流创建 AudioPlayer 的新实例,所以我总是 nil
所以我创建了一个单例,这样它只会创建一个副本。
class AudioPlayer : NSObject, FlutterStreamHandler {
static let sharedInstance = AudioPlayer()
}
现在在处理程序中,
public static func register(with registrar: FlutterPluginRegistrar) {
let durationChannel = FlutterEventChannel(name: Constants.durationEventChannel, binaryMessenger: registrar.messenger())
durationChannel.setStreamHandler(AudioPlayer.sharedInstance)
}
我正在尝试在 swift 上实施 EventChannel
以实现 flutter 方面。所以这就是我正在做的,
我是如何注册活动频道的,
public class SwiftMusicPlayer: NSObject, FlutterPlugin {
final var audioPlayer = AudioPlayer()
struct Constants {
static let methodChannelName = "MethodChannel"
static let durationEventChannel = "durationEventChannel"
...
}
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: Constants.methodChannelName, binaryMessenger: registrar.messenger())
let instance = SwiftMusicPlayer()
registrar.addMethodCallDelegate(instance, channel: channel)
let durationChannel = FlutterEventChannel(name: Constants.durationEventChannel, binaryMessenger: registrar.messenger())
durationChannel.setStreamHandler(AudioPlayer())
}
// The method calls
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let args = call.arguments as? Dictionary<String, Any>
switch call.method {
case Constants.preparePlayer:
audioPlayer.preparePlayer(path: args?[Constants.path] as? String, volume: args?[Constants.volume] as? Double,result: result)
break
case Constants.startPlayer:
audioPlayer.startPlayer(result: result)
break
case Constants.pausePlayer:
audioPlayer.pausePlayer(result)
break
case Constants.stopPlayer:
audioPlayer.stopPlayer(result)
break
}
}
}
AudioPlayer
class
class AudioPlayer : NSObject,FlutterStreamHandler{
var player: AVPlayer?
private var sink: FlutterEventSink?
// I'm initialising it using method call before doing anything
func preparePlayer(path: String?, volume: Double?,result: @escaping FlutterResult){
if(!(path ?? "").isEmpty){
let url = URL.init(fileURLWithPath: path!)
player = AVPlayer(url: url)
player?.volume = Float(volume ?? 1.0)
result(true)
} else {
result(FlutterError(code: "", message: "Path to file can't be empty or null", details: nil))
}
}
func startPlayer(result: @escaping FlutterResult){
do{
if(player?.status == .readyToPlay){
player?.play()
result(true)
}
} catch {
result(FlutterError(code: "", message: "Failed to start player", details: nil))
}
}
func pausePlayer(_ result: @escaping FlutterResult){
print(player?.currentItem?.duration.seconds)
player?.pause()
result(true)
}
//Here it is being nil
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
print(self?.player?.currentItem?.asset.duration)//<---prints always nil
sink = events
let interval = CMTimeMakeWithSeconds(0.5, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
//never goes inside because player is nil
player?.addPeriodicTimeObserver(forInterval: interval, queue: nil, using: {[weak self] time in
print(time)
self?.sink!(0)
})
return nil
}
func onCancel(withArguments arguments: Any?) -> FlutterError? {
sink = nil
timer.invalidate()
return nil
}
}
在这里,当我调用启动播放器时,它会播放音频文件。暂停和停止也有效。
现在,当我在 pausePlayer()
中调用 self?.player?.currentItem?.asset.duration
时,它确实给了我持续时间,但是当我尝试在 onListen()
函数中打印它时,它总是 returns nil。
当我尝试打印 AVPlayer
的实例时,这里是 player
,它也打印为 nil。
那么这里哪里做错了?
当我将 AudioPlayer()
实例传递给 setStreamHandler
时,它正在为流创建 AudioPlayer 的新实例,所以我总是 nil
所以我创建了一个单例,这样它只会创建一个副本。
class AudioPlayer : NSObject, FlutterStreamHandler {
static let sharedInstance = AudioPlayer()
}
现在在处理程序中,
public static func register(with registrar: FlutterPluginRegistrar) {
let durationChannel = FlutterEventChannel(name: Constants.durationEventChannel, binaryMessenger: registrar.messenger())
durationChannel.setStreamHandler(AudioPlayer.sharedInstance)
}