我有一个简单的 MIDI 播放器(Swift 5、SwiftUI、iOS14),想用 MPRemoteCommandCenter 切换播放/暂停命令。锁定屏幕的控制在以下设置下工作正常,但我正在努力寻找如何在从应用程序内部而不是锁定屏幕切换播放/暂停时通知 MPRemoteCommandCenter 我的播放器状态。在我的应用程序中播放或暂停不会更改锁定屏幕上的播放/暂停图标,但是我可以通过将播放速率设置为 0 来停止显示的播放位置和锁定屏幕上的进度。换句话说,唯一的问题是锁定屏幕上的播放/暂停图标不同步。
我觉得我应该在这里发出通知,但我没有找到文档。我有一个类似的使用 AVAudioPlayer 的音频媒体播放器,这只是神奇的工作,我猜 AVAudioPlayer 正在吐出所需的通知。有没有人有关于如何使用我自己的不使用 AVAudioPlayer 的播放器执行此操作的教程或建议?谢谢。
// ContentView.swift
import SwiftUI
import AudioKit
import MediaPlayer
struct ContentView: View {
let engine: AudioEngine
let sampler: MIDISampler
let sequencer: AppleSequencer
@State var playing: Bool = false
init() {
self.engine = AudioEngine()
self.sampler = MIDISampler()
self.sequencer = AppleSequencer()
let url = Bundle.main.url(forResource: "mytrack", withExtension: "mid")!
sequencer.loadMIDIFile(fromURL: url)
sequencer.setGlobalMIDIOutput(sampler.midiIn)
engine.output = sampler
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
try AVAudioSession.sharedInstance().setActive(true)
try engine.start()
} catch let error {
print(error)
}
}
var body: some View {
Text("Play a MIDI file")
.padding()
Button(action: {
self.togglePlayPause()
}) {
if playing {
Text("Pause")
} else {
Text("Play")
}
}.onAppear {
self.setupRemoteTransportControls()
}
}
func togglePlayPause() {
if playing {
sequencer.stop()
} else {
sequencer.play()
}
self.playing = playing ? false : true
self.setupNowPlayingInfo()
}
func setupNowPlayingInfo() {
var nowPlayingInfo = [String: Any]()
nowPlayingInfo[MPMediaItemPropertyTitle] = "My track"
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = sequencer.currentPosition.seconds
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = sequencer.length.seconds
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = NSNumber(value: self.playing ? 1 : 0)
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}
func setupRemoteTransportControls() {
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.togglePlayPauseCommand.addTarget { [self] _ in
self.togglePlayPause()
return .success
}
commandCenter.togglePlayPauseCommand.isEnabled = true
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}