尽管启用了后台功能,但计时器仍会停止

Posted

技术标签:

【中文标题】尽管启用了后台功能,但计时器仍会停止【英文标题】:Timer stops despite background capability is enabled 【发布时间】:2020-03-21 23:53:13 【问题描述】:

我正在使用AVAudioPlayer 播放循环声音。我当前的代码有这一行:audioPlayer.numberOfLoops = -1,这会导致无限循环。我使用计时器在一段时间后停止循环音频。这在应用程序处于前台时有效,但在进入后台后无效。

我的应用的后台功能是:

尽管启用了后台模式并且在应用程序进入后台时正在播放音频,但应用程序似乎在调用applicationDidEnterBackground 后立即暂停。我之所以这么说是因为 (1) 计时器每秒停止向控制台打印输出 (2) 即使计时器应该结束,音频也会无限期地播放。

我已经阅读here 说这一定不是这样,如果在后台播放音频,则不应暂停应用程序,但在我的应用程序中似乎并非如此。

我在这里缺少什么?我应该怎么做才能让计时器真正在后台运行,如果不够,除了播放循环声音之外?

运行音频的代码:

    var audioPlayer = AVAudioPlayer()
    do 
        let (fileName, fileExtension) = fileNameExtension(fileName: soundFileName)
        let soundURL = URL.init(fileURLWithPath: Bundle.main.path(forResource: fileName, ofType: fileExtension)!)
        audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
        audioPlayer.prepareToPlay()            
        let audiosession = AVAudioSession.sharedInstance()
        do 
            try audioSession.setCategory(.playback, mode: .default, options: [.allowAirPlay, .allowBluetooth, .allowBluetoothA2DP, .mixWithOthers])            
            try AVAudioSession.sharedInstance().setActive(true)
         catch let error as NSError 
        print("Fetch error: \(error) description: \(error.userInfo)")
           
     catch let error as NSError 
        print("Fetch error: \(error) description: \(error.userInfo)")
    
    audioPlayer.numberOfLoops = -1        
    audioPlayer.play()

运行计时器的代码。此代码在应用程序处于前台时运行。:

    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block:  [weak self] _ in
        self?.updateTimer()
    )        
    RunLoop.current.add(timer, forMode: .common)        
    timer.tolerance = 0.2

更新定时器:

@objc func updateTimer()         
    remainingTime -= 1              
    if remainingTime <= 0.0 
       complete()
            

【问题讨论】:

@matt 感谢您的回复。我假设由于以下原因(1)我的计时器在调试控制台中每秒打印一个输出。但是,在我在控制台中看到 applicationDidEnterBackground 后,计时器停止打印任何输出,而应用程序在后台,(2)即使在计时器应该结束后,音频也会在后台无限期地播放。我一定在这里遗漏了一些东西,但我看不到它...... 是的@matt,我正在设备上进行测试。 @matt 感谢您的链接。我正在读它。查看 AppDelegate 中的代码,我的第一个猜测是我未能正确保持音频会话处于活动状态。我添加了一些希望相关的代码。如果您希望我分享其他任何内容,请告诉我。 这是一个可下载的小例子。 github.com/mattneub/timerRunsInBackground 下载。构建它。运行。把它放到后台。在 Xcode 中观看控制台。声音循环和计时器运行(控制台中的“滴答声”)。正如我父亲常说的那样,一个反例足以证明这个定理。 @matt 我怎么看不到它......是的!应用程序进入后台时计时器失效... ????????‍♂️ 请写下答案,让我接受... 【参考方案1】:

这个问题有一些错误的前提:

applicationDidEnterBackground 并不意味着您的应用将被暂停。 通常会这样做,但是如果您具有音频背景模式功能和playback 音频类别,并且当您进入后台时正在播放声音,您不会被暂停;相反,你在后台运行。

在您进入后台之前启动的计时器在这些情况下确实在后台工作。

因此,如果您在应用程序的后台听到声音,但您的计时器没有触发,那一定是由于您正在执行其他操作。也许您已经配置了一些东西,以便在您进入后台时计时器无效?

【讨论】:

以上是关于尽管启用了后台功能,但计时器仍会停止的主要内容,如果未能解决你的问题,请参考以下文章

关于移动端浏览器转入后台后倒计时停止运行的问题

倒数计时器停止在后台运行

在 iPhone 的后台运行定时器功能

Cocos2d-x三种定时器启用和停止

unity 后台计时器实现

警报代码有问题,需要用户输入和后台计时器。定时器工作,但不停止程序