问题描述:
监听了系统的打断事件,在来电的时候有收到系统打断的 AVAudioSessionInterruptionTypeBegan 通知,却没有收到 AVAudioSessionInterruptionTypeEnd 通知。
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive:YES error: nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interruptionNotificationHandler:) name:AVAudioSessionInterruptionNotification object:nil];
Google 搜索了好些答案:
iOS AVAudioSession Interruption Notification not working as expected
Handling interruptions during a phone call - the "begin" works but the "end" doesn't
Audio Session Programming Guide
然而,都没能解决问题。
后来自己 debug 发现,在 applicationWillResignActive: 或者是 applicationDidBecomeActive: 方法里面设置了
NSError *error = nil;
BOOL issuccess = [[AVAudioSession sharedInstance] setActive:YES error:&error];
NSLog(@"is setactive success: %d",issuccess);
if (error) {
NSLog(@"error:%@",error.description);
}
这个之后就收不到系统发出的 AVAudioSessionInterruptionTypeEnd 通知了。
解决方法:
不要在 applicationWillResignActive: 或者是 applicationDidBecomeActive: 方法里面 active AVAudiosession 。
原因:
当接到来电的时候,系统会占用 AVAudiosession ,这时候你的应用就收到了 AVAudioSessionInterruptionTypeBegan 的通知了,然后进入了 applicationWillResignActive 以响应来电,如果此时你 active 了 audiosession ,你的应用就会重新拥用 audiosession 的所有权,既然你已经拥有了 audiosession 就不再会收到 interruption end 的通知了。
这里有一个疑问:响应来电的优先级应该比你应用的优先级要高的,此时你设置
BOOL issuccess = [[AVAudioSession sharedInstance] setActive:NO error:&error];
正常情况下应该返回的是 false 才对,苹果的文档上也是这么说的,而事实上它返回的是 true,意味着你的应用抢占 audiosession 所有权成功,这就很奇怪了。