Skip to content

Commit

Permalink
fix: ensure error notified after auto stop fix #51
Browse files Browse the repository at this point in the history
Previously errors were suppressed if listening stopped
before the error happened, even if the listening was
stopped implicitly by the native device rather than explicitly
by the user canceling or stopping. This change only blocks
error callbacks after an explicit user cancel or stop operation.
  • Loading branch information
sowens-csd committed Apr 7, 2020
1 parent bb87ec0 commit 6beb564
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
25 changes: 20 additions & 5 deletions lib/speech_to_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ class SpeechToText {
bool _recognized = false;
bool _listening = false;
bool _cancelOnError = false;

/// True if not listening or the user called cancel / stop, false
/// if cancel/stop were invoked by timeout or error condition.
bool _userEnded = false;
String _lastRecognized = "";
String _lastStatus = "";
double _lastSoundLevel = 0;
Expand Down Expand Up @@ -182,6 +186,11 @@ class SpeechToText {
/// *Note:* Cannot be used until a successful [initialize] call. Should
/// only be used after a successful [listen] call.
Future<void> stop() async {
_userEnded = true;
return _stop();
}

Future<void> _stop() async {
if (!_initWorked) {
return;
}
Expand All @@ -200,6 +209,11 @@ class SpeechToText {
/// *Note* Cannot be used until a successful [initialize] call. Should only
/// be used after a successful [listen] call.
Future<void> cancel() async {
_userEnded = true;
return _cancel();
}

Future<void> _cancel() async {
if (!_initWorked) {
return;
}
Expand Down Expand Up @@ -250,6 +264,7 @@ class SpeechToText {
if (!_initWorked) {
throw SpeechToTextNotInitializedException();
}
_userEnded = false;
_cancelOnError = cancelOnError;
_recognized = false;
_resultListener = onResult;
Expand All @@ -261,7 +276,7 @@ class SpeechToText {
channel.invokeMethod(listenMethod, listenParams);
if (null != listenFor) {
_listenTimer = Timer(listenFor, () {
cancel();
_stop();
});
}
}
Expand Down Expand Up @@ -350,19 +365,19 @@ class SpeechToText {
}

Future<void> _onNotifyError(String errorJson) async {
if (isNotListening) {
if (isNotListening && _userEnded) {
return;
}
Map<String, dynamic> errorMap = jsonDecode(errorJson);
SpeechRecognitionError speechError =
SpeechRecognitionError.fromJson(errorMap);
_lastError = speechError;
if (_cancelOnError && speechError.permanent) {
await cancel();
}
if (null != errorListener) {
errorListener(speechError);
}
if (_cancelOnError && speechError.permanent) {
await _cancel();
}
}

void _onNotifyStatus(String status) {
Expand Down
13 changes: 11 additions & 2 deletions test/speech_to_text_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,7 @@ void main() {
MethodCall(SpeechToText.notifyErrorMethod, permanentErrorJson));
expect(speech.isListening, isFalse);
});
test('Error not sent after cancel',
() async {
test('Error not sent after cancel', () async {
await speech.initialize(onError: listener.onSpeechError);
await speech.listen();
await speech.cancel();
Expand All @@ -267,6 +266,16 @@ void main() {
expect(speech.isListening, isFalse);
expect(listener.speechErrors, 0);
});
test('Error still sent after implicit cancel', () async {
await speech.initialize(onError: listener.onSpeechError);
await speech.listen(cancelOnError: true);
await speech.processMethodCall(
MethodCall(SpeechToText.notifyErrorMethod, permanentErrorJson));
await speech.processMethodCall(
MethodCall(SpeechToText.notifyErrorMethod, permanentErrorJson));
expect(speech.isListening, isFalse);
expect(listener.speechErrors, 2);
});
});
group('locales', () {
test('fails with exception if not initialized', () async {
Expand Down

0 comments on commit 6beb564

Please sign in to comment.