我有一個應用程式,用戶可以在其中播放從其他用戶收到的語音訊息。播放語音訊息應中斷設備音頻(從其他應用程式播放的音樂、播客等),播放語音訊息,然后讓設備音頻繼續播放。
這是我試圖實作的一個特定用途的用例
- 用戶開始通過 Apple Music 在設備上播放音樂
- 用戶打開應用并點擊語音訊息
- Apple Music 停止
- 應用程式中的語音訊息播放
- Apple Music 繼續播放
通過將AVAudioSessions category 設定為,.ambient我可以在播放 Apple Music 的“上方”播放語音訊息,但這并不是我所需要的。
如果我使用.playback使 Apple Music 停止的類別,則會在應用程式中播放語音訊息,但之后 Apple Music 不會繼續播放。
uj5u.com熱心網友回復:
我認為那些應該繼續使用的應用程式,如 Apple Music、Spotify、Radio 應用程式等實作了處理中斷的功能,以及當另一個應用程式的音頻被停用/想要交還音頻的責任時。
所以你能試試看看這是否有效
// I play the audio using this AVAudioPlayer
var player: AVAudioPlayer?
// Implement playing a sound
func playSound() {
// Local url for me, but you could configure as you need
guard let url = Bundle.main.url(forResource: "se_1",
withExtension: "wav")
else { return }
do {
// Set the category to playback to interrupt the current audio
try AVAudioSession.sharedInstance().setCategory(.playback,
mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
player = try AVAudioPlayer(contentsOf: url)
// This is to know when the sound has ended
player?.delegate = self
player?.play()
} catch let error {
print(error.localizedDescription)
}
}
extension AVAudioInterruptVC: AVAudioPlayerDelegate {
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer,
successfully flag: Bool) {
do {
// When the sound has ended, notify other apps
// You can do this where ever you want, I just show the
// example of doing it when the audio has ended
try AVAudioSession.sharedInstance()
.setActive(false, options: [.notifyOthersOnDeactivation])
}
catch {
print(error)
}
}
}
uj5u.com熱心網友回復:
您已經發現您可以通過激活.playback類別音頻會話來中斷其他音頻應用程式。當您完成播放音頻并希望中斷的音頻繼續播放時,請停用您的音頻會話并傳遞該notifyOthersOnDeactivation選項。
例如
try! audioSession.setActive(false, options: .notifyOthersOnDeactivation)
uj5u.com熱心網友回復:
理論上,Apple 提供了一個用于中斷和恢復背景音頻的“協議”,在一個可下載的示例中,我向您展示它是什么并證明它有效:
https://github.com/mattneub/Programming-iOS-Book-Examples/tree/master/bk2ch14p653backgroundPlayerAndInterrupter
在該示例中,有兩個專案,代表兩個不同的應用程式。您同時運行它們。BackgroundPlayer 在后臺播放聲音;Interrupter 中斷它,暫停它,當它完成中斷時,BackgroundPlayer 恢復。
正如您將看到的,這是通過讓 Interrupter 在中斷時將其音頻會話類別從環境更改為播放,并在完成時將其更改回來.notifyOthersOnDeactivation,以及在發送信號時首先完全停用自身來完成的:
func playFile(atPath path:String) {
self.player?.delegate = nil
self.player?.stop()
let fileURL = URL(fileURLWithPath: path)
guard let p = try? AVAudioPlayer(contentsOf: fileURL) else {return} // nicer
self.player = p
// error-checking omitted
// switch to playback category while playing, interrupt background audio
try? AVAudioSession.sharedInstance().setCategory(.playback, mode:.default)
try? AVAudioSession.sharedInstance().setActive(true)
self.player.prepareToPlay()
self.player.delegate = self
let ok = self.player.play()
print("interrupter trying to play \(path): \(ok)")
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { // *
let sess = AVAudioSession.sharedInstance()
// this is the key move
try? sess.setActive(false, options: .notifyOthersOnDeactivation)
// now go back to ambient
try? sess.setCategory(.ambient, mode:.default)
try? sess.setActive(true)
delegate?.soundFinished(self)
}
然而,問題在于對的回應.notifyOthersOnDeactivation完全取決于其他應用程式是否表現良好。我的另一個應用程式 BackgroundPlayer表現良好。這就是它的作用:
self.observer = NotificationCenter.default.addObserver(forName:
AVAudioSession.interruptionNotification, object: nil, queue: nil) {
[weak self] n in
guard let self = self else { return } // legal in Swift 4.2
let why = n.userInfo![AVAudioSessionInterruptionTypeKey] as! UInt
let type = AVAudioSession.InterruptionType(rawValue: why)!
switch type {
case .began:
print("interruption began:\n\(n.userInfo!)")
case .ended:
print("interruption ended:\n\(n.userInfo!)")
guard let opt = n.userInfo![AVAudioSessionInterruptionOptionKey] as? UInt else {return}
let opts = AVAudioSession.InterruptionOptions(rawValue: opt)
if opts.contains(.shouldResume) {
print("should resume")
self.player.prepareToPlay()
let ok = self.player.play()
print("bp tried to resume play: did I? \(ok as Any)")
} else {
print("not should resume")
}
@unknown default:
fatalError()
}
}
如您所見,我們注冊了中斷通知,如果我們被中斷,我們會尋找.shouldResume選項——這是中斷器notifyOthersOnDeactivation首先設定的結果。
So far, so good. But there's a snag. Some apps are not well behaved in this regard. And the most non-well-behaved is Apple's own Music app! Thus it is actually impossible to get the Music app to do what you want it to do. You are better off using ducking, where the system just adjusts the relative levels of the two apps for you, allowing the background app (Music) to continue playing but more quietly.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/452645.html
