iOS 14及以上版本实现无限后台运行时长的解决方案问询
iOS14+ 非上架应用后台持续保活可行方案
iOS14及以上版本对后台模式的判定逻辑做了升级,原有方案失效的核心原因是两个:
- 系统可以识别到循环播放的无声音频属于无效媒体会话,不会给持续的后台运行权限
- 你调用的
beginBackgroundTask默认最多只能申请30秒的后台运行时长,到期系统会直接终止应用,和音频保活逻辑没有绑定
可行优化方案(均仅适用于非上架场景)
方案1:优化音频保活逻辑(改动最小,推荐)
修改点如下:
- 替换无声音频文件为低振幅白噪音音频,音量设置为0.01(人耳不可感知,同时可以绕过系统的无效音频检测)
- 将计算任务放到音频播放的定时回调中执行,不要创建游离的独立线程,避免被系统判定为无关后台任务
- 调整音频会话的配置,添加
mixWithOthers选项,避免被其他应用的音频会话抢占权限
优化后的代码示例
class ViewController: UIViewController, UITextFieldDelegate,AVAudioPlayerDelegate { var backgroundTask = UIBackgroundTaskIdentifier.invalid var audioPlayer: AVAudioPlayer? // 计算任务定时器,和音频播放绑定 var computeTimer: Timer? func registerBackgroundTask() { // 后台任务每次到期前重新申请,延长运行时长 backgroundTask = UIApplication.shared.beginBackgroundTask { [weak self] in self?.endBackgroundTask() self?.registerBackgroundTask() } assert(backgroundTask != UIBackgroundTaskIdentifier.invalid) } func endBackgroundTask() { print("Background task expired, renewing...") UIApplication.shared.endBackgroundTask(backgroundTask) backgroundTask = UIBackgroundTaskIdentifier.invalid } // 你的计算任务逻辑写在这里 @objc func runComputeTask() { // 单次计算任务不要超过2秒,避免占用过高CPU触发系统查杀 print("Running compute task...") } override func viewDidLoad() { super.viewDidLoad() registerBackgroundTask() do { // 替换为低振幅白噪音音频文件 let aSound = URL(fileURLWithPath: Bundle.main.path(forResource: "low_vol_noise", ofType: "mp3")!) audioPlayer = try AVAudioPlayer(contentsOf: aSound) do { // 添加mixWithOthers选项,避免被其他音频打断 try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.mixWithOthers]) try AVAudioSession.sharedInstance().setActive(true) } catch { print(error) } // 音量调到0.01,人耳不可感知 audioPlayer!.setVolume(0.01, fadeDuration: 0) audioPlayer!.numberOfLoops = -1 audioPlayer!.prepareToPlay() audioPlayer!.delegate = self audioPlayer!.play() // 绑定计算任务到定时器,每1秒执行一次,和音频保活逻辑绑定 computeTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(runComputeTask), userInfo: nil, repeats: true) } catch { print("Audio player init error: \(error)") } } }
方案2:位置后台保活(适用于需要位置权限的场景)
如果你的应用本身需要位置权限,可以开启后台位置更新模式,设置精度为最低的三公里精度,持续请求位置更新,也可以获得无限后台运行权限,缺点是会增加一点功耗。
内容的提问来源于stack exchange,提问作者Jesse Taube
相关产品推荐
相关产品推荐

