【问题标题】:start playing audio from a background task via AVAudioPlayer in Xcode通过 Xcode 中的 AVAudioPlayer 开始从后台任务播放音频
【发布时间】:2013-12-06 10:32:43
【问题描述】:

我正在尝试通过随后实例化的 AVAudioPlayer 从后台任务开始播放声音,所以这就是我所拥有的。

为了便于阅读,我删除了所有用户选择的值。

- (void)restartHandler {
    bg = 0;
    bg = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [[UIApplication sharedApplication] endBackgroundTask:bg];
    }];
    tim = [NSTimer timerWithTimeInterval:.1 target:self selector:@selector(upd) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:tim forMode:NSRunLoopCommonModes];
}

- (void)upd {
    if ([[NSDate date] timeIntervalSinceDate:startDate] >= difference) {
        [self playSoundFile];
        [tim invalidate];
        [[UIApplication sharedApplication] endBackgroundTask:bg];
    }
}

- (void)playSoundFile {

    NSError *sessionError = nil;
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&sessionError];


    // new player object
    _player = [[AVQueuePlayer alloc] init];
    [_player insertItem:[AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"Manamana" withExtension:@"m4a"]] afterItem:nil];

    [_player setVolume:.7];
    [_player play];

    NSLog(@"Testing");
}

说明:bgtimstartDatedifference_player 是全局声明的变量。我从用户触发的方法中调用- (void)restartHandler,并在其中启动- (void)upd 的10Hz 重复计时器。当达到预设差异时,- (void)playSoundFile 被调用并启动并启动播放器。方法末尾的测试 NSLog 被调用。

现在奇怪的是,如果我在应用程序处于活动状态时调用 - (void)playSoundFile,一切正常,但如果我从后台任务启动它,它就不会播放任何声音。

编辑

所以我尝试在运行时使用不同的线程,看起来,如果播放器没有在主线程上实例化,则会出现同样的问题。 我还尝试使用AVPlayerAVAudioPlayer,其中AVAudioPlayer.playing 属性确实返回YES,但仍然没有声音播放。

【问题讨论】:

    标签: ios iphone objective-c ios7


    【解决方案1】:

    根据我在编写播放器应用程序后了解到的情况,当您的应用程序已在后台超过 X 秒时,您似乎无法开始播放音频,即使您已正确配置一切。

    要修复它,您必须明智地使用后台任务。 最重要的是您必须playSoundFile 之后立即调用endBackgroundTask延迟大约 5-10 秒。

    这是我在 iOS6 和 iOS7 上的管理方法。

    1、在plist中添加音频UIBackgroundModes。

    2、设置音频会话类别:

    3、在主线程中创建一个AVQueuePlayer,在App进入后台之前将音频资源入队。

    *用于在后台继续播放(如播放播放列表)*

    4、确保AVQueuePlayer中的音频队列永远不会变空,否则你的App会在播放完最后一个asset时被挂起。

    5,如果 5 秒不足以让您获得下一个资产,您可以使用后台任务来延迟暂停。 当资产准备好后,您应该在 10 秒后致电endBackgroundTask

    【讨论】:

    • 谢谢先生!这是天才。我不确定 Apple 是否会接受我当前的解决方案,即持续循环一个 .m4a 文件,该文件包含一个空声波,直到播放器开始播放,但它现在可以工作了。
    • 你们提交到 App Store 没有被禁止吗?
    【解决方案2】:

    在下面包含您的 playSoundFile 调用,这应该始终在主线程中运行它

    dispatch_async(dispatch_get_main_queue(), ^{
    
    });
    

    将此 if 添加到您的 - (void) playSoundFile 以检查是否创建了播放器,如果没有,则创建它

    if(!_player) {
        _player = [[AVQueuePlayer alloc] init];
    }
    

    【讨论】:

    • mh,如果我使用它,当我回到应用程序并使其处于活动状态时,首先会创建整个播放器...
    • 嗯嗯,是的,但是无论有没有 _player 都会被创建,但是只有当应用再次激活时才会调用处理程序
    • 如果应用再次处于活动状态,_player 将不会被再次创建,因为它不会是 nil,如果我误解了您的评论,请纠正我。
    • 不,我的意思是我在 dipatch_async 中编写的所有内容只有在我返回应用程序时才会被调用...
    【解决方案3】:

    在我看来,好像您没有设置适当的后台模式?

    另外,看起来另一位用户也遇到了同样的问题,并通过 Apple Docs 帖子修复了它。 Link to Post

    您可能只需要执行以下步骤即可将音频会话设置为活动状态:

    [audioSession setActive:YES error:&activationError];
    

    希望对你有帮助!

    【讨论】:

    • 这是个好主意,但我已经这样做了,但没有帮助。我计划很快尝试一个新项目
    【解决方案4】:

    如果您需要开始在后台播放声音(没有技巧,例如在您需要声音之前一直以零音量播放):

    • 在您的 p.list 中设置背景模式音频;
    • 将 AudioSession 类别设置为 AVAudioSessionCategoryPlayback
    • 将 AudioSession 设置为活动状态
    • 当您的后台应用开始运行时,在播放声音之前启动一个后台任务(显然当剩余的后台时间少于 10 秒时,声音不会播放)

    这对我有用。

    【讨论】:

    • 检查 beginBackgroundTaskWithName:expiration handler:
    【解决方案5】:

    为我解决的问题是在应用程序退出时开始播放一些音频,所以我在 AppDelegate 的 applicationWillResignActive 中添加了 1 秒的空白音频

    func applicationWillResignActive(_ application: UIApplication) {
    
            self.backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
                self.endBackgroundUpdateTask(true)
            })
    
    
            let secSilence = URL(fileURLWithPath: Bundle.main.path(forResource: "1secSilence", ofType: "mp3")!)
    
            do {
                audioPlayer = try AVAudioPlayer(contentsOf: secSilence)
            }
            catch {
                print("Error in loading sound file")
            }
    
            audioPlayer.prepareToPlay()
            audioPlayer.play()
    
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 2011-11-29
      • 2010-11-12
      相关资源
      最近更新 更多