添加语音websocket等,还没测试

This commit is contained in:
2026-01-16 13:38:03 +08:00
parent 169a1929d7
commit b021fd308f
33 changed files with 5098 additions and 8 deletions

View 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