当AudioSessionActive为NO时,无法通过硬件按钮控制AVAudioPlayer的音量

时间:2013-05-10 03:34:30

标签: objective-c core-audio avaudioplayer avaudiosession

我正在构建一个转弯导航应用程序,播放周期性的短片声音。无论屏幕是否被锁定,声音都应该播放,应该与其他音乐播放混合,并且当播放此音频时应该播放其他音乐。

Apple在29:20分钟的“WWDC 2010会话412 iPhone OS第1部分音频开发”视频中详细讨论了转弯用例。实施效果很好,但有一个问题 - 当应用程序运行时,按下硬件音量控件可调整铃声音量,而不是应用音量。如果要更改应用程序音量,则必须在播放提示时按音量按钮。

Apple在视频中非常具体,您不应该让AVAudioSession处于活动状态,但如果AVAudioSession处于非活动状态,则音量按钮将无法控制我的应用程序的音量。

以下是我用来设置的代码:

UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
propertySetError = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);

UInt32 allowMixing = true;
propertySetError = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(allowMixing), &allowMixing);

UInt32 shouldDuck = true;
propertySetError = AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(shouldDuck), &shouldDuck);

OSStatus activationResult = AudioSessionSetActive(true);

NSError* err = nil;
_player = [[AVAudioPlayer alloc] initWithData:audioData error:&err];
_player.delegate = self;
[_player play];

我最后将会话激活为NO,因为Apple建议:

OSStatus activationResult = AudioSessionSetActive(false);
NSAssert(activationResult == kAudioSessionNoError, @"Error deactivating audio session");

我有什么遗漏,或者我不得不违背他们在视频中推荐的内容吗?

1 个答案:

答案 0 :(得分:7)

在您的情况下,您不希望将音频会话设置为非活动状态。您需要做的是使用两种方法,一种是设置会话以播放声音,另一种是将其设置为空闲。第一种方法设置混合+鸭音频模式,第二种方法使用背景音频友好模式,如环境。

这样的事情:

- (void)setActive {
    UInt32 mix  = 1;
    UInt32 duck = 1;
    NSError* errRet;

    AVAudioSession* session = [AVAudioSession sharedInstance];
    [session setActive:NO error:&errRet];

    [session setCategory:AVAudioSessionCategoryPlayback error:&errRet];
    NSAssert(errRet == nil, @"setCategory!");

    AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(mix), &mix);
    AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(duck), &duck);

    [session setActive:YES error:&errRet];
}

- (void)setIdle {
    NSError* errRet;

    AVAudioSession* session = [AVAudioSession sharedInstance];
    [session setActive:NO error:&errRet];

    [session setCategory:AVAudioSessionCategoryAmbient error:&errRet];
    NSAssert(errRet == nil, @"setCategory!");

    [session setActive:YES error:&errRet];
}

然后调用它:

[self setActive];
[self _playAudio:nil];

播放后进行清理:

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer*)player
                   successfully:(BOOL)flag {
[self setIdle];

}

要成为一个好公民,你的应用应该在音频会话不导航时(即执行其主要功能)将音频会话设置为非活动状态,但是当它存在时,保持音频会话处于活动状态并没有任何问题。使用模式与其他应用程序和平共存。您可以使用上面的代码复制Apple的导航应用功能。