SwiftUI:在锁定屏幕上显示 AVPlayer 播放(媒体)
SwiftUI: showing AVPlayer playback (media) on locked screen
我尝试了几个 iOS 示例,但它们似乎不适用于 SwiftUI,例如 https://medium.com/@quangtqag/background-audio-player-sync-control-center-516243c2cdd1
如何在 SwiftUI 框架的锁定屏幕上显示控制按钮和媒体信息?
UPD:添加示例
import SwiftUI
import MediaPlayer
import AVFoundation
class ViewModel: ObservableObject {
@Published var isPlaying = false
private let audioSession = AVAudioSession.sharedInstance()
private let player = AVPlayer()
init() {
if let path =
Bundle.main.path(forResource: "5.mp3", ofType: nil) {
let asset = AVAsset(url: URL(fileURLWithPath: path))
let playerItem = AVPlayerItem(asset: asset)
player.replaceCurrentItem(with: playerItem)
}
try! self.audioSession.setCategory(AVAudioSession.Category.playback)
try! self.audioSession.setActive(true)
setupRemoteTransportControls()
setupNowPlaying()
}
func setupRemoteTransportControls() {
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.playCommand.isEnabled = true
commandCenter.playCommand.addTarget { [unowned self] event in
if !self.isPlaying {
self.play()
return .success
}
return .commandFailed
}
commandCenter.pauseCommand.isEnabled = true
commandCenter.pauseCommand.addTarget { [unowned self] event in
if self.isPlaying {
self.pause()
return .success
}
return .commandFailed
}
}
func setupNowPlaying() {
// Define Now Playing Info
var nowPlayingInfo = [String : Any]()
nowPlayingInfo[MPMediaItemPropertyTitle] = "My Movie"
if let image = UIImage(named: "lockscreen") {
nowPlayingInfo[MPMediaItemPropertyArtwork] =
MPMediaItemArtwork(boundsSize: image.size) { size in
return image
}
}
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = player.currentItem?.currentTime().seconds
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = player.currentItem?.asset.duration.seconds
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate
// Set the metadata
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}
func play() {
isPlaying.toggle()
player.play()
}
func pause() {
isPlaying.toggle()
player.pause()
}
}
struct ContentView: View {
@StateObject private var viewModel = ViewModel()
var body: some View {
Button(action: {
if viewModel.isPlaying {
viewModel.pause()
} else {
viewModel.play()
}
}, label: {
Image(systemName: viewModel.isPlaying ? "pause" : "play")
})
}
}
我也尝试添加 beginReceivingRemoteControlEvents,但没有任何区别
struct PlayerApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
application.beginReceivingRemoteControlEvents()
return true
}
}
音频在锁定屏幕下播放正常,只是没有播放控件和媒体信息
我刚刚在我正在开发的有声读物播放器应用程序中实现了这两个功能,它们按照 Apple 文档中的概述(以及您编写的代码)工作。我唯一能想到的就是尝试将 AVAudioSession 的类别更改为:
.playAndRecord
我的 setCategory 调用如下所示:
try audioSession.setCategory(.playAndRecord, mode: .spokenAudio, options: [.defaultToSpeaker, .allowAirPlay, .allowBluetoothA2DP])
我尝试了几个 iOS 示例,但它们似乎不适用于 SwiftUI,例如 https://medium.com/@quangtqag/background-audio-player-sync-control-center-516243c2cdd1
如何在 SwiftUI 框架的锁定屏幕上显示控制按钮和媒体信息?
UPD:添加示例
import SwiftUI
import MediaPlayer
import AVFoundation
class ViewModel: ObservableObject {
@Published var isPlaying = false
private let audioSession = AVAudioSession.sharedInstance()
private let player = AVPlayer()
init() {
if let path =
Bundle.main.path(forResource: "5.mp3", ofType: nil) {
let asset = AVAsset(url: URL(fileURLWithPath: path))
let playerItem = AVPlayerItem(asset: asset)
player.replaceCurrentItem(with: playerItem)
}
try! self.audioSession.setCategory(AVAudioSession.Category.playback)
try! self.audioSession.setActive(true)
setupRemoteTransportControls()
setupNowPlaying()
}
func setupRemoteTransportControls() {
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.playCommand.isEnabled = true
commandCenter.playCommand.addTarget { [unowned self] event in
if !self.isPlaying {
self.play()
return .success
}
return .commandFailed
}
commandCenter.pauseCommand.isEnabled = true
commandCenter.pauseCommand.addTarget { [unowned self] event in
if self.isPlaying {
self.pause()
return .success
}
return .commandFailed
}
}
func setupNowPlaying() {
// Define Now Playing Info
var nowPlayingInfo = [String : Any]()
nowPlayingInfo[MPMediaItemPropertyTitle] = "My Movie"
if let image = UIImage(named: "lockscreen") {
nowPlayingInfo[MPMediaItemPropertyArtwork] =
MPMediaItemArtwork(boundsSize: image.size) { size in
return image
}
}
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = player.currentItem?.currentTime().seconds
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = player.currentItem?.asset.duration.seconds
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate
// Set the metadata
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}
func play() {
isPlaying.toggle()
player.play()
}
func pause() {
isPlaying.toggle()
player.pause()
}
}
struct ContentView: View {
@StateObject private var viewModel = ViewModel()
var body: some View {
Button(action: {
if viewModel.isPlaying {
viewModel.pause()
} else {
viewModel.play()
}
}, label: {
Image(systemName: viewModel.isPlaying ? "pause" : "play")
})
}
}
我也尝试添加 beginReceivingRemoteControlEvents,但没有任何区别
struct PlayerApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
application.beginReceivingRemoteControlEvents()
return true
}
}
音频在锁定屏幕下播放正常,只是没有播放控件和媒体信息
我刚刚在我正在开发的有声读物播放器应用程序中实现了这两个功能,它们按照 Apple 文档中的概述(以及您编写的代码)工作。我唯一能想到的就是尝试将 AVAudioSession 的类别更改为:
.playAndRecord
我的 setCategory 调用如下所示:
try audioSession.setCategory(.playAndRecord, mode: .spokenAudio, options: [.defaultToSpeaker, .allowAirPlay, .allowBluetoothA2DP])