我正在播放来自我构建的 JSON 源的音频,该源用于将音频 URL 及其音频信息提供给我的应用程序(例如标题、描述和封面艺术 URL)。音频是广播电台的提要。音频作品、播放/停止控制作品、封面艺术作品和背景音频作品。我很难将控件添加到控制中心以在应用程序外播放/停止音频。我已经查看了Apple 在这方面的文档,它非常直截了当。我还启用了构建设置以允许后台获取、后台音频和蓝牙。但它似乎不适用于通过 USB-C 连接到 Xcode 的 iPhone(我假设 iOS 模拟器不支持控制中心)。下面是我的工作代码。关于如何使它工作的任何想法?我需要将音频传递给setupRemoteTransportControls()
? 我假设虽然标题和封面艺术需要从数据源传递,但总体而言,控制中心不会识别出应用程序正在播放音频。
ViewController.swift
import UIKit
import MediaPlayer
import AVFoundation
import Foundation
class ViewController: UIViewController {
var player: AVPlayer!
var playerItem: AVPlayerItem!
var audioCheck: Timer?
var timer: Timer?
var passText: String? = "Test"
@IBOutlet weak var trackTitle: UILabel!
@IBOutlet weak var togglePlay: UIButton!
@IBOutlet weak var coverPhoto: UIImageView!
func loadAudio() {
let audioURL = URL.init(string: "AUDIO_URL_GOES_HERE")
player = AVPlayer.init(url: audioURL!)
}
let minutes = 60
func playAudio() {
let audioURL = URL.init(string: "AUDIO_URL_GOES_HERE")
player = AVPlayer.init(url: audioURL!)
player.play()
}
@IBAction func OpenPlayer(_ sender: Any) {
performSegue(withIdentifier: "PlayerSegue", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
loadAudio()
// Audio in the background
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSession.Category.playback)
} catch {
print("Error: Audio is not paying in the background.")
}
// Timer checking if other audio sources are running
audioCheck = Timer.scheduledTimer(timeInterval: 0, target: self, selector: #selector(timedAudioCheck), userInfo: nil, repeats: true)
struct currentTrack: Codable {
let title: String
let artwork_url: String
}
struct getTrack: Codable {
// let name: String
// let status: String
let current_track: currentTrack
}
let jsonURL = URL(string: "JSON_URL_GOES_HERE")!
URLSession.shared.dataTask(with: jsonURL) {data, _, _ in
if let data = data {
let trackData = try? JSONDecoder().decode([getTrack].self, from: data)
// print(users)
// print(trackData![0].current_track.title)
// print(trackData![0].current_track.artwork_url)
DispatchQueue.main.async {
self.trackTitle.text = trackData![0].current_track.title
let coverPhotoURL = trackData![0].current_track.artwork_url
if let coverPhotoConverted = URL(string: coverPhotoURL) {
do {
let coverPhotoData = try Data(contentsOf: coverPhotoConverted)
self.coverPhoto.image = UIImage(data: coverPhotoData)
} catch {
}
}
}
}
}.resume()
_ = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: true) { timer in
// print("Data updated!")
let jsonURL = URL(string: "JSON_URL_GOES_HERE")!
URLSession.shared.dataTask(with: jsonURL) {data, _, _ in
if let data = data {
let trackData = try? JSONDecoder().decode([getTrack].self, from: data)
// print(users)
// print(trackData![0].current_track.title)
// print(trackData![0].current_track.artwork_url)
DispatchQueue.main.async {
self.trackTitle.text = trackData![0].current_track.title
let coverPhotoURL = trackData![0].current_track.artwork_url
if let coverPhotoConverted = URL(string: coverPhotoURL) {
do {
let coverPhotoData = try Data(contentsOf: coverPhotoConverted)
self.coverPhoto.image = UIImage(data: coverPhotoData)
} catch {
}
}
}
}
}.resume()
}
func setupRemoteTransportControls() {
// Get the shared MPRemoteCommandCenter
let commandCenter = MPRemoteCommandCenter.shared()
// Add handler for Play Command
commandCenter.playCommand.addTarget { [unowned self] event in
if self.player.rate == 0.0 {
self.player.play()
return .success
}
return .commandFailed
}
// Add handler for Pause Command
commandCenter.pauseCommand.addTarget { [unowned self] event in
if self.player.rate == 1.0 {
self.player.pause()
return .success
}
return .commandFailed
}
}
// Apple's Documentation on playing audio in control center
func setupRemoteTransportControls() {
// Get the shared MPRemoteCommandCenter
let commandCenter = MPRemoteCommandCenter.shared()
// Add handler for Play Command
commandCenter.playCommand.addTarget { [unowned self] event in
if self.player.rate == 0.0 {
self.player.play()
return .success
}
return .commandFailed
}
// Add handler for Pause Command
commandCenter.pauseCommand.addTarget { [unowned self] event in
if self.player.rate == 1.0 {
self.player.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] = playerItem.currentTime().seconds
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = playerItem.asset.duration.seconds
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate
// Set the metadata
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}
}
// Along with timer, checks if other audio sources are playing and resets the audio in the app
@objc func timedAudioCheck() {
if (AVAudioSession.sharedInstance().secondaryAudioShouldBeSilencedHint) {
togglePlay.setTitle("Play", for: .normal)
} else if (player.rate == 0) {
togglePlay.setTitle("Play", for: .normal)
} else {
togglePlay.setTitle("Puase", for: .normal)
}
}
@IBAction func togglePlay(_ sender: UIButton) {
if player.rate == 0 {
// Plays the audio stream
sender.setTitle("Pause", for: .normal)
playAudio()
} else {
sender.setTitle("Play", for: .normal)
player.pause()
}
}
}
苹果建议增加控制中心支持
func setupRemoteTransportControls() {
// Get the shared MPRemoteCommandCenter
let commandCenter = MPRemoteCommandCenter.shared()
// Add handler for Play Command
commandCenter.playCommand.addTarget { [unowned self] event in
if self.player.rate == 0.0 {
self.player.play()
return .success
}
return .commandFailed
}
// Add handler for Pause Command
commandCenter.pauseCommand.addTarget { [unowned self] event in
if self.player.rate == 1.0 {
self.player.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] = playerItem.currentTime().seconds
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = playerItem.asset.duration.seconds
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate
// Set the metadata
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}