原因:
在AVAudioPlayer正在播放的时候去设置了AVAudioSession的active为NO,就会出现这个错误。
场景:
AVAudioPlayer播放 -> 百度TTS播报 -> AVAudioPlayer播放 -> 百度TTS播报 ......
AVAudioPlayer和百度TTS交替循环播放时,在百度TTS播报完成后百度TTS SDK会去设置 [[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];,并且这个设置是在子线程异步执行的,也就是说在播报成功的回调后才去设置AVAudioSession的active为NO,而我是在播报成功的回调中调用AVAudioPlayer播放的。这时候就造成了AVAudioPlayer正在播放的时候去设置了AVAudioSession的active为NO,然后就出现了上面的错误。
现象:
-
AVAudioPlayer已经开始播放时去设置AVAudioSession的active为NO,只是会报上面的错误,AVAudioPlayerDelegate的方法都会正常回调。
-
AVAudioPlayer刚开始播放时去设置AVAudioSession的active为NO,AVAudioPlayerDelegate的方法不会回调。
解决方法:
现在的解决办法是hook了AVAudioSession的setActive:withOptions:error:方法,然后判断AVAudioPlayer是否在播放,如果在播放则active设置成YES,如果没有在播放,则设置成NO。
@implementation AVAudioSession (LBYAudioSession)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSEL = @selector(setActive:withOptions:error:);
SEL swizzledSEL = @selector(lby_setActive:withOptions:error:);
Method originalMethod = class_getInstanceMethod(class, originalSEL);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSEL);
BOOL didAddMethod = class_addMethod(class, originalSEL , method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class, swizzledSEL, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (BOOL)lby_setActive:(BOOL)active withOptions:(AVAudioSessionSetActiveOptions)options error:(NSError * _Nullable __autoreleasing *)outError {
BOOL realActive = [LBYSoundManager getInstance].isPlaying ? YES : active;
return [self lby_setActive:realActive withOptions:options error:outError];
}
@end
网友评论