Skip to content
This repository was archived by the owner on May 23, 2023. It is now read-only.

Commit 2dd231e

Browse files
committed
Fix hasPermission() always returning success on iOS
- Use `[AVAudioSession sharedInstance] recordPermission` to check mic permissions Closes #89
1 parent f998b16 commit 2dd231e

File tree

1 file changed

+98
-74
lines changed

1 file changed

+98
-74
lines changed

src/ios/SpeechRecognition.m

+98-74
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define MESSAGE_RESTRICTED @"Speech recognition restricted on this device"
1616
#define MESSAGE_NOT_DETERMINED @"Speech recognition not determined on this device"
1717
#define MESSAGE_ACCESS_DENIED_MICROPHONE @"User denied access to microphone"
18+
#define MESSAGE_NOT_DETERMINED_MICROPHONE @"Microphone access not determined on this device"
1819
#define MESSAGE_ONGOING @"Ongoing speech recognition"
1920

2021
@interface SpeechRecognition()
@@ -58,100 +59,97 @@ - (void)startListening:(CDVInvokedUrlCommand*)command {
5859
return;
5960
}
6061

61-
[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted){
62-
if (!granted) {
63-
NSLog(@"startListening() microphone access not authorized");
64-
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_ACCESS_DENIED_MICROPHONE];
65-
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
66-
return;
67-
}
62+
AVAudioSessionRecordPermission micStatus = [[AVAudioSession sharedInstance] recordPermission];
63+
if (micStatus != AVAudioSessionRecordPermissionGranted) {
64+
NSLog(@"startListening() microphone access not authorized");
65+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_MISSING_PERMISSION];
66+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
67+
return;
68+
}
6869

69-
NSString* language = [command argumentAtIndex:0 withDefault:DEFAULT_LANGUAGE];
70-
int matches = [[command argumentAtIndex:1 withDefault:@(DEFAULT_MATCHES)] intValue];
71-
BOOL showPartial = [[command argumentAtIndex:3 withDefault:@(NO)] boolValue];
70+
NSString* language = [command argumentAtIndex:0 withDefault:DEFAULT_LANGUAGE];
71+
int matches = [[command argumentAtIndex:1 withDefault:@(DEFAULT_MATCHES)] intValue];
72+
BOOL showPartial = [[command argumentAtIndex:3 withDefault:@(NO)] boolValue];
7273

73-
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:language];
74-
self.speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale];
75-
self.audioEngine = [[AVAudioEngine alloc] init];
74+
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:language];
75+
self.speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale];
76+
self.audioEngine = [[AVAudioEngine alloc] init];
7677

77-
// Cancel the previous task if it's running.
78-
if ( self.recognitionTask ) {
79-
[self.recognitionTask cancel];
80-
self.recognitionTask = nil;
81-
}
78+
// Cancel the previous task if it's running.
79+
if ( self.recognitionTask ) {
80+
[self.recognitionTask cancel];
81+
self.recognitionTask = nil;
82+
}
8283

83-
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
84-
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
85-
[audioSession setMode:AVAudioSessionModeDefault error:nil];
86-
[audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
84+
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
85+
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
86+
[audioSession setMode:AVAudioSessionModeDefault error:nil];
87+
[audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
8788

88-
self.recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc] init];
89-
self.recognitionRequest.shouldReportPartialResults = showPartial;
89+
self.recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc] init];
90+
self.recognitionRequest.shouldReportPartialResults = showPartial;
9091

91-
AVAudioInputNode *inputNode = self.audioEngine.inputNode;
92-
AVAudioFormat *format = [inputNode outputFormatForBus:0];
92+
AVAudioInputNode *inputNode = self.audioEngine.inputNode;
93+
AVAudioFormat *format = [inputNode outputFormatForBus:0];
9394

94-
self.recognitionTask = [self.speechRecognizer recognitionTaskWithRequest:self.recognitionRequest resultHandler:^(SFSpeechRecognitionResult *result, NSError *error) {
95+
self.recognitionTask = [self.speechRecognizer recognitionTaskWithRequest:self.recognitionRequest resultHandler:^(SFSpeechRecognitionResult *result, NSError *error) {
9596

96-
if ( result ) {
97+
if ( result ) {
9798

98-
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
99+
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
99100

100-
int counter = 0;
101-
for ( SFTranscription *transcription in result.transcriptions ) {
102-
if (matches > 0 && counter < matches) {
103-
[resultArray addObject:transcription.formattedString];
104-
}
105-
counter++;
101+
int counter = 0;
102+
for ( SFTranscription *transcription in result.transcriptions ) {
103+
if (matches > 0 && counter < matches) {
104+
[resultArray addObject:transcription.formattedString];
106105
}
106+
counter++;
107+
}
107108

108-
NSArray *transcriptions = [NSArray arrayWithArray:resultArray];
109+
NSArray *transcriptions = [NSArray arrayWithArray:resultArray];
109110

110-
NSLog(@"startListening() recognitionTask result array: %@", transcriptions.description);
111+
NSLog(@"startListening() recognitionTask result array: %@", transcriptions.description);
111112

112-
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:transcriptions];
113-
if (showPartial){
114-
[pluginResult setKeepCallbackAsBool:YES];
115-
}
116-
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
113+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:transcriptions];
114+
if (showPartial){
115+
[pluginResult setKeepCallbackAsBool:YES];
117116
}
117+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
118+
}
118119

119-
if ( error ) {
120-
NSLog(@"startListening() recognitionTask error: %@", error.description);
120+
if ( error ) {
121+
NSLog(@"startListening() recognitionTask error: %@", error.description);
121122

122-
[self.audioEngine stop];
123-
[self.audioEngine.inputNode removeTapOnBus:0];
123+
[self.audioEngine stop];
124+
[self.audioEngine.inputNode removeTapOnBus:0];
124125

125-
self.recognitionRequest = nil;
126-
self.recognitionTask = nil;
126+
self.recognitionRequest = nil;
127+
self.recognitionTask = nil;
127128

128-
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description];
129-
if (showPartial){
130-
[pluginResult setKeepCallbackAsBool:YES];
131-
}
132-
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
129+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description];
130+
if (showPartial){
131+
[pluginResult setKeepCallbackAsBool:YES];
133132
}
133+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
134+
}
134135

135-
if ( result.isFinal ) {
136-
NSLog(@"startListening() recognitionTask isFinal");
137-
138-
[self.audioEngine stop];
139-
[self.audioEngine.inputNode removeTapOnBus:0];
136+
if ( result.isFinal ) {
137+
NSLog(@"startListening() recognitionTask isFinal");
140138

141-
self.recognitionRequest = nil;
142-
self.recognitionTask = nil;
143-
}
144-
}];
145-
146-
[inputNode installTapOnBus:0 bufferSize:1024 format:format block:^(AVAudioPCMBuffer *buffer, AVAudioTime *when) {
147-
[self.recognitionRequest appendAudioPCMBuffer:buffer];
148-
}];
139+
[self.audioEngine stop];
140+
[self.audioEngine.inputNode removeTapOnBus:0];
149141

150-
[self.audioEngine prepare];
151-
[self.audioEngine startAndReturnError:nil];
142+
self.recognitionRequest = nil;
143+
self.recognitionTask = nil;
144+
}
145+
}];
152146

147+
[inputNode installTapOnBus:0 bufferSize:1024 format:format block:^(AVAudioPCMBuffer *buffer, AVAudioTime *when) {
148+
[self.recognitionRequest appendAudioPCMBuffer:buffer];
153149
}];
154150

151+
[self.audioEngine prepare];
152+
[self.audioEngine startAndReturnError:nil];
155153
}
156154

157155
- (void)stopListening:(CDVInvokedUrlCommand*)command {
@@ -183,18 +181,44 @@ - (void)getSupportedLanguages:(CDVInvokedUrlCommand*)command {
183181

184182
- (void)hasPermission:(CDVInvokedUrlCommand*)command {
185183
SFSpeechRecognizerAuthorizationStatus status = [SFSpeechRecognizer authorizationStatus];
186-
BOOL speechAuthGranted = (status == SFSpeechRecognizerAuthorizationStatusAuthorized);
184+
CDVPluginResult *pluginResult = nil;
185+
BOOL speechAuthGranted = NO;
186+
187+
switch (status) {
188+
case SFSpeechRecognizerAuthorizationStatusAuthorized:
189+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
190+
speechAuthGranted = YES;
191+
break;
192+
case SFSpeechRecognizerAuthorizationStatusDenied:
193+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_ACCESS_DENIED];
194+
break;
195+
case SFSpeechRecognizerAuthorizationStatusRestricted:
196+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_RESTRICTED];
197+
break;
198+
case SFSpeechRecognizerAuthorizationStatusNotDetermined:
199+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_NOT_DETERMINED];
200+
break;
201+
}
187202

188203
if (!speechAuthGranted) {
189-
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:NO];
190204
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
191205
return;
192206
}
193207

194-
[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted){
195-
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:granted];
196-
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
197-
}];
208+
AVAudioSessionRecordPermission micStatus = [[AVAudioSession sharedInstance] recordPermission];
209+
210+
switch (micStatus) {
211+
case AVAudioSessionRecordPermissionGranted:
212+
break;
213+
case AVAudioSessionRecordPermissionDenied:
214+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_ACCESS_DENIED_MICROPHONE];
215+
break;
216+
case AVAudioSessionRecordPermissionUndetermined:
217+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:MESSAGE_NOT_DETERMINED_MICROPHONE];
218+
break;
219+
}
220+
221+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
198222
}
199223

200224
- (void)requestPermission:(CDVInvokedUrlCommand*)command {

0 commit comments

Comments
 (0)