添加语音websocket等,还没测试
This commit is contained in:
234
keyBoard/Class/AiTalk/VM/AudioSessionManager.m
Normal file
234
keyBoard/Class/AiTalk/VM/AudioSessionManager.m
Normal file
@@ -0,0 +1,234 @@
|
||||
//
|
||||
// AudioSessionManager.m
|
||||
// keyBoard
|
||||
//
|
||||
// Created by Mac on 2026/1/15.
|
||||
//
|
||||
|
||||
#import "AudioSessionManager.h"
|
||||
|
||||
@interface AudioSessionManager ()
|
||||
@property(nonatomic, assign) BOOL isSessionActive;
|
||||
@end
|
||||
|
||||
@implementation AudioSessionManager
|
||||
|
||||
#pragma mark - Singleton
|
||||
|
||||
+ (instancetype)sharedManager {
|
||||
static AudioSessionManager *instance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
instance = [[AudioSessionManager alloc] init];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_isSessionActive = NO;
|
||||
[self setupNotifications];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
#pragma mark - Notifications
|
||||
|
||||
- (void)setupNotifications {
|
||||
// 监听音频会话中断通知
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(handleInterruption:)
|
||||
name:AVAudioSessionInterruptionNotification
|
||||
object:nil];
|
||||
|
||||
// 监听音频路由变化通知
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(handleRouteChange:)
|
||||
name:AVAudioSessionRouteChangeNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)handleInterruption:(NSNotification *)notification {
|
||||
NSDictionary *info = notification.userInfo;
|
||||
AVAudioSessionInterruptionType type =
|
||||
[info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
|
||||
|
||||
if (type == AVAudioSessionInterruptionTypeBegan) {
|
||||
// 中断开始:来电、闹钟等
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([self.delegate
|
||||
respondsToSelector:@selector(audioSessionManagerDidInterrupt:)]) {
|
||||
[self.delegate audioSessionManagerDidInterrupt:
|
||||
KBAudioSessionInterruptionTypeBegan];
|
||||
}
|
||||
});
|
||||
} else if (type == AVAudioSessionInterruptionTypeEnded) {
|
||||
// 中断结束
|
||||
AVAudioSessionInterruptionOptions options =
|
||||
[info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
|
||||
if (options & AVAudioSessionInterruptionOptionShouldResume) {
|
||||
// 可以恢复播放
|
||||
[self activateSession:nil];
|
||||
}
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([self.delegate
|
||||
respondsToSelector:@selector(audioSessionManagerDidInterrupt:)]) {
|
||||
[self.delegate audioSessionManagerDidInterrupt:
|
||||
KBAudioSessionInterruptionTypeEnded];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleRouteChange:(NSNotification *)notification {
|
||||
NSDictionary *info = notification.userInfo;
|
||||
AVAudioSessionRouteChangeReason reason =
|
||||
[info[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
|
||||
|
||||
switch (reason) {
|
||||
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
|
||||
case AVAudioSessionRouteChangeReasonNewDeviceAvailable: {
|
||||
// 旧设备不可用(如耳机拔出)或新设备可用(如耳机插入)
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([self.delegate respondsToSelector:@selector
|
||||
(audioSessionManagerRouteDidChange)]) {
|
||||
[self.delegate audioSessionManagerRouteDidChange];
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Microphone Permission
|
||||
|
||||
- (void)requestMicrophonePermission:(void (^)(BOOL))completion {
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
|
||||
[session requestRecordPermission:^(BOOL granted) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (!granted) {
|
||||
if ([self.delegate respondsToSelector:@selector
|
||||
(audioSessionManagerMicrophonePermissionDenied)]) {
|
||||
[self.delegate audioSessionManagerMicrophonePermissionDenied];
|
||||
}
|
||||
}
|
||||
if (completion) {
|
||||
completion(granted);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
- (BOOL)hasMicrophonePermission {
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
return session.recordPermission == AVAudioSessionRecordPermissionGranted;
|
||||
}
|
||||
|
||||
#pragma mark - Session Configuration
|
||||
|
||||
- (BOOL)configureForConversation:(NSError **)error {
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
|
||||
// 配置为录音+播放模式
|
||||
// Category: PlayAndRecord - 同时支持录音和播放
|
||||
// Mode: VoiceChat - 优化语音通话场景
|
||||
// Options:
|
||||
// - DefaultToSpeaker: 默认使用扬声器
|
||||
// - AllowBluetooth: 允许蓝牙设备
|
||||
NSError *categoryError = nil;
|
||||
BOOL success =
|
||||
[session setCategory:AVAudioSessionCategoryPlayAndRecord
|
||||
mode:AVAudioSessionModeVoiceChat
|
||||
options:(AVAudioSessionCategoryOptionDefaultToSpeaker |
|
||||
AVAudioSessionCategoryOptionAllowBluetooth)
|
||||
error:&categoryError];
|
||||
|
||||
if (!success) {
|
||||
if (error) {
|
||||
*error = categoryError;
|
||||
}
|
||||
NSLog(@"[AudioSessionManager] Failed to configure session: %@",
|
||||
categoryError.localizedDescription);
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)configureForPlayback:(NSError **)error {
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
|
||||
// 仅播放模式
|
||||
NSError *categoryError = nil;
|
||||
BOOL success =
|
||||
[session setCategory:AVAudioSessionCategoryPlayback
|
||||
mode:AVAudioSessionModeDefault
|
||||
options:AVAudioSessionCategoryOptionDefaultToSpeaker
|
||||
error:&categoryError];
|
||||
|
||||
if (!success) {
|
||||
if (error) {
|
||||
*error = categoryError;
|
||||
}
|
||||
NSLog(@"[AudioSessionManager] Failed to configure playback: %@",
|
||||
categoryError.localizedDescription);
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)activateSession:(NSError **)error {
|
||||
if (self.isSessionActive) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
NSError *activationError = nil;
|
||||
BOOL success = [session setActive:YES error:&activationError];
|
||||
|
||||
if (!success) {
|
||||
if (error) {
|
||||
*error = activationError;
|
||||
}
|
||||
NSLog(@"[AudioSessionManager] Failed to activate session: %@",
|
||||
activationError.localizedDescription);
|
||||
return NO;
|
||||
}
|
||||
|
||||
self.isSessionActive = YES;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)deactivateSession {
|
||||
if (!self.isSessionActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
NSError *error = nil;
|
||||
|
||||
// 使用 NotifyOthersOnDeactivation 通知其他应用可以恢复播放
|
||||
[session setActive:NO
|
||||
withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
|
||||
error:&error];
|
||||
|
||||
if (error) {
|
||||
NSLog(@"[AudioSessionManager] Failed to deactivate session: %@",
|
||||
error.localizedDescription);
|
||||
}
|
||||
|
||||
self.isSessionActive = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user