SwiftUI:在锁定屏幕上显示 AVPlayer 播放(媒体)

时间:2021-02-23 19:50:30

标签: swiftui media-player avplayer

我尝试了几个 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
    
}
}

音频在锁定屏幕下播放正常,只是没有播放控件和媒体信息

1 个答案:

答案 0 :(得分:0)

我刚刚在我正在开发的有声读物播放器应用程序中实现了这两个功能,它们的工作方式如 Apple 文档中所述(以及您编写的代码)。我唯一能想到的可能是尝试将您的 AVAudioSession 类别更改为:

.playAndRecord

我的 setCategory 调用如下所示:

try audioSession.setCategory(.playAndRecord, mode: .spokenAudio, options: [.defaultToSpeaker, .allowAirPlay, .allowBluetoothA2DP])