MacOS 在后台不响应 MPRemoteCommandCenter 命令

MacOS not responding to MPRemoteCommandCenter commands in the background

我正在为自己的目的编写一个应用程序,目的是无论系统中发生什么情况都可以获得播放暂停事件。我做了这么多工作

let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.togglePlayPauseCommand.isEnabled = true
commandCenter.togglePlayPauseCommand.addTarget { (MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus in
    print("Play Pause Command")
    return .success
}

commandCenter.nextTrackCommand.isEnabled = true
commandCenter.nextTrackCommand.addTarget { (MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus in
    print("NextTrackCommand")
    return .success
}
commandCenter.previousTrackCommand.isEnabled = true
commandCenter.previousTrackCommand.addTarget { (MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus in
    print("previousTrackCommand")
    return .success
}
commandCenter.playCommand.isEnabled = true
commandCenter.playCommand.addTarget { (MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus in
    print("playCommand")
    return .success
}

MPNowPlayingInfoCenter.default().playbackState = .playing

大多数方法都在那里,因为显然如果没有实现 nextTrackCommand 或 previousTrackCommand 或 playCommand,您将不会收到任何通知。

无论如何,我的一个问题是,一旦您打开另一个使用音频的应用程序,这些事件处理程序就会停止调用,我无法找到检测和修复此问题的方法。

我通常会尝试做 AVAudioSession 的事情来将其声明为后台应用程序,但这似乎不起作用。关于无论系统处于何种状态如何获取播放暂停事件的任何想法?

我希望能够始终收听这些事件,或者在其他人何时控制了音频时得到指示?甚至可以重新订阅这些播放暂停事件。

系统中有一个内部队列,其中包含所有音频事件订阅者。当您开始使用其他应用程序时,其他应用程序会优先于它。

I would like to be able to always listen for these events

没有 API,但有一个肮脏的解决方法。如果我正确理解你的问题,这个片段:

    MPNowPlayingInfoCenter.default().playbackState = .paused
    MPNowPlayingInfoCenter.default().playbackState = .playing

如果您 运行 它在您的应用程序中某处的循环中,则必须为您完成技巧。

请注意,这不是 100% 可靠,因为:

  1. 如果在您切换到不同的应用程序后立即在两个后续 playbackState 状态更改之前生成一个事件,它仍会被活动 window 中的应用程序捕获;
  2. 如果另一个应用程序正在做同样的事情,队列中就会出现持续的竞争条件,结果不可预测。

参考文献:

  • playbackStateis here的文档;
  • 另见
  • 另请参阅 a bug report 以获得 mpv 具有类似 问题(MPRemoteCommandCenter 之前的一期,但仍然很有价值)

OR get an indication of when someone else has taken control of the audio

据我所知,在 macOS 中没有 public API。