在 iOS 设备上检测活动的 AVAudioSessions
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20371388/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Detecting active AVAudioSessions on iOS device
提问by Stavash
I'm trying to figure out if this is possible - my app activates an audio session that is initialized as:
我试图弄清楚这是否可行 - 我的应用程序激活了一个初始化为的音频会话:
[[[AVAudioSession alloc] init] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
I would like to be able to understand when an additional audio session that originated from another app or the OS is playing.
我希望能够了解何时正在播放源自另一个应用程序或操作系统的附加音频会话。
I know about the ability to implement the delegate methods beginInterruption:
and endInterruption
but these won't get invoked because of the AVAudioSessionCategoryOptionMixWithOthers
option I'm using.
我知道实现委托方法的能力beginInterruption:
,endInterruption
但由于AVAudioSessionCategoryOptionMixWithOthers
我使用的选项,这些方法不会被调用。
Is there a way to achieve this without using private API?
有没有办法在不使用私有 API 的情况下实现这一目标?
Thanks in advance.
提前致谢。
回答by Bamsworld
The way you manage your application's Audio Session has had some significant changes since iOS 6.0, and deserves a brief mention first. Before iOS 6.0you would make use of AVAudioSessionand AudioSessionServicesclasses, incorporating delegation and property listening respectively. From iOS 6.0onwards use AVAudioSessionclass and incorporate notifications.
自iOS 6.0以来,您管理应用程序音频会话的方式发生了一些重大变化,首先值得简要提及。在iOS 6.0之前,您将使用AVAudioSession和AudioSessionServices类,分别结合委托和属性侦听。从iOS 6.0开始使用AVAudioSession类并合并通知。
The following is for iOS 6.0onwards.
以下是针对iOS 6.0以后的。
To tell if other audio outside your applications sandbox is playing use -
要判断应用程序沙箱之外的其他音频是否正在播放,请使用 -
// query if other audio is playing
BOOL isPlayingWithOthers = [[AVAudioSession sharedInstance] isOtherAudioPlaying];
// test it with...
(isPlayingWithOthers) ? NSLog(@"other audio is playing") : NSLog(@"no other audio is playing");
As for interruption handling you'll need to observe AVAudioSessionInterruptionNotification
and AVAudioSessionRouteChangeNotification
. So in the class that manages your audio session you could put something like the following - this should be called once at the start of the application lifecycle and don't forget to remove observer in the dealloc method of the same class.
至于中断处理,您需要观察AVAudioSessionInterruptionNotification
和AVAudioSessionRouteChangeNotification
。因此,在管理您的音频会话的类中,您可以放置类似以下内容 - 这应该在应用程序生命周期开始时调用一次,并且不要忘记在同一类的 dealloc 方法中删除观察者。
// ensure we already have a singleton object
[AVAudioSession sharedInstance];
// register for notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(interruption:)
name:AVAudioSessionInterruptionNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(routeChange:)
name:AVAudioSessionRouteChangeNotification
object:nil];
And finally add the following selectors interruption:
and routeChange:
- these will receive a NSNotification
object that has a property called userInfo of type NSDictionary
that you read to assist any conditionals your application has.
最后添加以下选择器interruption:
和routeChange:
- 这些将接收一个NSNotification
对象,该对象具有一个名为 userInfo 的属性NSDictionary
,您读取该属性以辅助您的应用程序具有的任何条件。
- (void)interruption:(NSNotification*)notification {
// get the user info dictionary
NSDictionary *interuptionDict = notification.userInfo;
// get the AVAudioSessionInterruptionTypeKey enum from the dictionary
NSInteger interuptionType = [[interuptionDict valueForKey:AVAudioSessionInterruptionTypeKey] integerValue];
// decide what to do based on interruption type here...
switch (interuptionType) {
case AVAudioSessionInterruptionTypeBegan:
NSLog(@"Audio Session Interruption case started.");
// fork to handling method here...
// EG:[self handleInterruptionStarted];
break;
case AVAudioSessionInterruptionTypeEnded:
NSLog(@"Audio Session Interruption case ended.");
// fork to handling method here...
// EG:[self handleInterruptionEnded];
break;
default:
NSLog(@"Audio Session Interruption Notification case default.");
break;
} }
And similarly...
而同样...
- (void)routeChange:(NSNotification*)notification {
NSDictionary *interuptionDict = notification.userInfo;
NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
switch (routeChangeReason) {
case AVAudioSessionRouteChangeReasonUnknown:
NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonUnknown");
break;
case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
// a headset was added or removed
NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonNewDeviceAvailable");
break;
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
// a headset was added or removed
NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonOldDeviceUnavailable");
break;
case AVAudioSessionRouteChangeReasonCategoryChange:
// called at start - also when other audio wants to play
NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonCategoryChange");//AVAudioSessionRouteChangeReasonCategoryChange
break;
case AVAudioSessionRouteChangeReasonOverride:
NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonOverride");
break;
case AVAudioSessionRouteChangeReasonWakeFromSleep:
NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonWakeFromSleep");
break;
case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory:
NSLog(@"routeChangeReason : AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory");
break;
default:
break;
} }
There is no need to poll anything as long as you check the state of your applications audio session say for example in the viewDidLoad
of your root view controller, at the start of you apps lifecycle. Any changes from there onwards to your applications audio session will be known via these two main notifications. Replace the NSLog
statements with what ever your code needs to do based on the cases contained in the switch.
只要您viewDidLoad
在应用程序生命周期开始时检查应用程序音频会话的状态,例如在根视图控制器的状态中,就无需轮询任何内容。从那以后对您的应用程序音频会话的任何更改都将通过这两个主要通知获知。NSLog
根据 switch 中包含的情况,将语句替换为您的代码需要执行的操作。
You can find more information about AVAudioSessionInterruptionTypeKey
and AVAudioSessionRouteChangeReasonKey
in the AVAudioSession
class reference documentation.
您可以在类参考文档中找到有关AVAudioSessionInterruptionTypeKey
和 的 更多信息。AVAudioSessionRouteChangeReasonKey
AVAudioSession
My apologies for the long answer but I think Audio Session management in iOS is rather fiddly and Apple's Audio Session Programming Guide, at the time of writing this, does not include code examples using notifications for interruption handling.
我对冗长的回答表示歉意,但我认为 iOS 中的音频会话管理相当繁琐,在撰写本文时,Apple 的音频会话编程指南不包括使用通知进行中断处理的代码示例。
回答by BlackMouse
You can check if other audio is playing like this:
您可以检查其他音频是否正在播放:
UInt32 otherAudioIsPlaying;
UInt32 propertySize = sizeof (otherAudioIsPlaying);
AudioSessionGetProperty (kAudioSessionProperty_OtherAudioIsPlaying, &propertySize, &otherAudioIsPlaying );
[self handleIfAudioIsPlaying: otherAudioIsPlaying];
Then you can add a loop and check every X second if something changed.
然后您可以添加一个循环并每隔 X 秒检查一次是否发生了变化。