自 iOS 6.0 以来,您管理应用程序音频会话的方式发生了一些重大变化,首先值得一提。在 iOS 6.0 之前,您将使用 AVAudioSession 和 AudioSessionServices 类,分别合并委托和属性监听。从 iOS 6.0 开始使用 AVAudioSession 类并合并通知。
以下内容适用于iOS 6.0 及以上版本。
判断您的应用程序沙箱之外的其他音频是否正在播放使用 -
// 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");
至于中断处理,您需要遵守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];
最后添加以下选择器 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;
} }
同样...
- (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;
} }
只要您在应用程序生命周期开始时检查应用程序音频会话的状态,例如在根视图控制器的viewDidLoad 中,就无需轮询任何内容。从那里开始对您的应用程序音频会话的任何更改都将通过这两个主要通知获知。根据 switch 中包含的情况,将 NSLog 语句替换为您的代码需要执行的操作。
您可以在AVAudioSession 类参考文档中找到有关AVAudioSessionInterruptionTypeKey 和AVAudioSessionRouteChangeReasonKey 的更多信息。
对于冗长的回答,我深表歉意,但我认为 iOS 中的音频会话管理相当繁琐,而且 Apple 的音频会话编程指南在撰写本文时并未包含使用通知进行中断处理的代码示例。