iPhone 锁定时的音频画外音

Audio voiceover when iPhone is locked

解决方法如下

我正在开发一个 运行ning 应用程序,它在每次练习开始时提供画外音指导。它在设备处于活动状态时按预期工作,但在 phone 被锁定时不起作用。 [当前音频继续播放,但不会播放未来的音频。]

问题 如何在用户 iPhone 被锁定时开始播放音频画外音。

目前我使用 Timer.scheduledTimer 跟踪我显示的 2 个计时器的锻炼 [当前 activity 和整体锻炼]。当计时器达到一个 activity 结束时的预定义时间时,会播放画外音以介绍下一个 activity。 定时器触发是启动音频的原因,我相信这就是问题所在。我可以暂停锻炼、跳过部分并且一切正常 - 直到设备被锁定。

如果在我按下主页按钮或锁定 iPhone 时正在播放音频画外音,它会继续按预期播放。问题是计时器不会触发,因此永远不会播放下一个音频画外音 [比如 90 秒]。

我读过的一些答案和评论说 iOS 中无法实现此功能。 Couch to 5k 应用程序 https://itunes.apple.com/gb/app/one-you-couch-to-5k/id1082307672?mt=8 使用此功能,所以我知道这是可以实现的,我只是不知道他们是怎么做到的。 [这将是一个专门的会员,下载它看看我的意思:)]

通过搜索,我读了很多 post 说 TimerNSTimer 不能 运行 当应用程序在后台或phone 已锁定。任何说它可以工作的 post 都是旧的并且基于 iOS4/5

我读过关于使用静音和基本上有 1 个长音频文件的建议。虽然这会给跳过练习中的部分带来一些新挑战,但我也看到评论说这种行为不会通过 Apple 对 AppStore 应用程序的测试。第三个缺点是我的音频文件大小会增加。

我看到的一个选项是本地通知,但是我还没有看到一个例子,当应用程序在后台时用于播放音频画外音。

如何实现与 Couch to 5k 应用相同的功能?

谢谢

我对 VoiceOver 的理解使我了解到 只有前台应用程序 才能控制它读出的内容。

您需要使用 VoiceOver 进行对焦 才能让它说话,当设备锁定或您的应用程序处于后台模式时,您什么也不对焦。

我建议看一下 speech synthesis or the AVAudioSession class to enable background audio:两者都可能是在后台模式下接管的很好的解决方法:请尝试让我们知道。 ;o)

好的,我想出了一个解决方案,可以在整个 30 分钟的锻炼过程中向用户播放音频提示,即使 iPhone 已锁定或应用程序处于后台也是如此。 该应用程序已提交并批准进入 AppStore

为了让应用按要求执行,我使用了 2 AVAudioPlayers;一个播放画外音,另一个播放 15 分钟的无声曲目 [因为它是一个单独的曲目,只是静音,它是一个低质量的 .mp3 并且只增加了 900kb 的应用程序大小]。 15 分钟远远超过画外音之间的任何间隔,因此效果完美。

当用户开始锻炼时,会播放第一个音频提示。从那时起,直到用户停止锻炼之前,后台都会播放音频。由于正在播放背景音乐,定时器仍在运行。

画外音结束后,将调用 AVAudioPlayerDelegate 方法 audioPlayerDidFinishPlaying。在这个方法中,我重置了音频属性 [我将很快解释原因],实例化我的静音 AVAudioPlayer,然后开始播放 15 分钟的静音曲目。使用此委托方法播放另一首曲目意味着背景音频没有真正中断,因此应用程序保持活动状态。随着应用程序“活跃”,计时器继续倒计时。当需要另一个画外音时,计时器会调用一个方法来重置音频类别,实例化我的画外音 AVAudioPlayer 并播放画外音。重复这个过程,直到最后的画外音。完成后,不再播放静音,应用程序可以安全地进入后台。

音频画外音需要降低用户的音乐[降低音乐音量以便可以清楚地听到音频]。静音音频不应该这样做,音乐应该继续以最大音量播放。由于两个 AVAudioPlayer 都使用 AVAudioSession.sharedInstance,我发现我必须停用 sharedInstance,重置属性,有或没有 .duckOthers,然后在实例化我的 AVAudioSession 之前重新激活 sharedInstance。那给了我想要的结果。持续的背景音频,仅在播放画外音时才回避用户的音乐。

do{
    try AVAudioSession.sharedInstance().setActive(false)
    try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.interruptSpokenAudioAndMixWithOthers, .duckOthers])
    try AVAudioSession.sharedInstance().setActive(true)
} catch{
        print(error.localizedDescription)
}

我知道有人说 Apple 不允许无声音频,但是,在这种情况下,无声音频仅在锻炼过程中播放。一旦它结束,应用程序就可以终止,因此不会让应用程序保持运行超过必要的时间。