15

StackOverflow 上有很多关于 iOS 中背景音乐播放的问题。没有人完全探索所有边缘情况,这个问题的目的是成为 iOS 上背景音频问题中的最后一句话

定义和假设

所有代码、问题和示例均参考

“背景” ——当用户按下主页按钮或电源按钮时应用程序进入的状态(因此设备显示锁定屏幕)。该应用程序还可以使用多任务切换器或 iPad 上的多任务手势置于后台。

"audio" — 使用 AudioQueue 播放的音频(包括 AVAudioPlayer)

先决条件

据我了解,让应用程序在后台播放音频有两个要求。

  1. 设置UIBackgroundModesaudio_Info.plist
  2. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

要求

我的用例是在后台播放相对较长的音频(音乐)。可能有数百首曲目,应用程序将按顺序播放它们。可以认为音频将无限期地播放。

该应用程序将通过暂停播放来处理中断。

问题

我在以下方面取得了喜忧参半的成功:

[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:...];

允许在后台播放音频。但我对它是否需要以及它与以下内容有何不同感到困惑:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

边缘案例

  1. 中断。如果您注册以接收音频中断(电话等)的通知,请成为AVAudioPlayer. 例如,如果您在中断开始时暂停或停止音频并在结束时恢复音频,如果中断超过 10 分钟(后台任务完成允许的最长时间),您的应用程序是否会暂停?

  2. 如果调用 Lock 或 Home,模拟器将停止音频,同时使用:

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    

但是,这适用于设备。这是一个已知的问题?

4

2 回答 2

5

我对 GPS 背景模式和背景音频有一些经验。这与您的情况不完全相同(您想播放长音频文件,而我播放短消息),但我可以告诉您:

  • beginBackgroundTaskWithExpirationHandler这个选择器在后台被调用时有一个目的:避免应用程序返回到暂停状态,在这种状态下不能再调用任何代码(你被“冻结”了)。因此,只要您在使用 调用beginBackgroundTaskWithExpirationHandler并终止长时间运行的任务之前beginBackgroundTaskWithExpirationHandler,您就会使用 CPU,并消耗电池。
    我真的怀疑在后台播放文件是否应该像运行应用程序一样使用 iPhone 的电池,所以我怀疑这beginBackgroundTaskWithExpirationHandler是否真的参与了你的流程。

  • 模拟器:不要依赖模拟器:它没有完全实现后台模式。实际上,当您单击主页按钮时,您的应用程序会进入后台,但是在此阶段,您仍然可以在应用程序中执行代码。一段时间后,您的应用程序将暂停(=冻结),并且您的代码执行将暂停以节省电池。这种挂起状态永远不会出现在模拟器上。

  • 中断。来电时暂停/恢复播放不取决于您。平台负责此操作,您可以使用AVAudioSessionDelegate对此做出反应。但是,您可以通过设置音频会话的属性来影响会话与其他音频声音交互的方式(例如,请参阅kAudioSessionProperty_OverrideCategoryMixWithOthers)。所以流程更多:您描述音频会话应与系统其余部分交互的方式,系统将相应地混合声音,如果您的会话被中断,您将收到 AVAudioSessionDelegate 通知。

希望这可以帮助。

于 2012-08-29T15:29:11.363 回答
3

我已将以下代码用于设备控制 -

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];

用于注册监听遥控器。完成后删除它 -

[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];

使应用程序canBecomeFirstResponder -

- (BOOL)canBecomeFirstResponder {
    return YES;
}

使用委托方法来处理 iPhone 控制,例如双击主页按钮时播放和暂停

- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
    //if it is a remote control event handle it correctly
    if (event.type == UIEventTypeRemoteControl) {
        if (event.subtype == UIEventSubtypeRemoteControlPlay) {
           [audioPlayer play];
            NSLog(@"play");
        } else if (event.subtype == UIEventSubtypeRemoteControlPause) {
           [audioPlayer stop];
             NSLog(@"pause");
        } else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause) {
            NSLog(@"toggle");
        }
    }
}
于 2012-08-30T12:24:55.747 回答