diff --git a/lib/speech_to_text.dart b/lib/speech_to_text.dart index 69ba1478..41542702 100644 --- a/lib/speech_to_text.dart +++ b/lib/speech_to_text.dart @@ -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; @@ -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 stop() async { + _userEnded = true; + return _stop(); + } + + Future _stop() async { if (!_initWorked) { return; } @@ -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 cancel() async { + _userEnded = true; + return _cancel(); + } + + Future _cancel() async { if (!_initWorked) { return; } @@ -250,6 +264,7 @@ class SpeechToText { if (!_initWorked) { throw SpeechToTextNotInitializedException(); } + _userEnded = false; _cancelOnError = cancelOnError; _recognized = false; _resultListener = onResult; @@ -261,7 +276,7 @@ class SpeechToText { channel.invokeMethod(listenMethod, listenParams); if (null != listenFor) { _listenTimer = Timer(listenFor, () { - cancel(); + _stop(); }); } } @@ -350,19 +365,19 @@ class SpeechToText { } Future _onNotifyError(String errorJson) async { - if (isNotListening) { + if (isNotListening && _userEnded) { return; } Map 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) { diff --git a/test/speech_to_text_test.dart b/test/speech_to_text_test.dart index 8b78f0b1..a0be7c21 100644 --- a/test/speech_to_text_test.dart +++ b/test/speech_to_text_test.dart @@ -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(); @@ -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 {