-
Notifications
You must be signed in to change notification settings - Fork 64
Description
Plugin version:
^7.0.1
Platform(s):
Android
Current behavior:
When starting speech recognition the first time, the recorder and recognition start correctly. On the second attempt (start → stop → start), the recorder UI does not start and no audio is captured. The plugin reports an error mapped to code 11 (native SpeechRecognizer.ERROR_SERVER_DISCONNECTED) but this error code is not handled in getErrorText. The failure alternates (works on 1st attempt, fails on 2nd, works on 3rd, etc.).
Expected behavior:
Speech recognition should start reliably on each start invocation (start → stop → start) without alternating failures. The plugin should either reuse the SpeechRecognizer connection or recover cleanly so the remote service does not disconnect between quick successive starts.
Steps to reproduce:
- Install the app with
@capacitor-community/speech-recognitionon an Android device or emulator running API 35. - Grant microphone permission if prompted.
- Start speech recognition (e.g.,
SpeechRecognition.start({...})withpartialResults: true,popup: false). - Let it run, then stop it (user stop or call
SpeechRecognition.stop()). - Immediately start speech recognition again.
- Observe that the second start often fails and logs an ERROR_SERVER_DISCONNECTED (11). Repeat — behavior alternates.
Related code:
await SpeechRecognition.removeAllListeners();
await SpeechRecognition.addListener('partialResults', data => { /* ... */ });
await SpeechRecognition.addListener('listeningState', data => { /* ... */ });
await SpeechRecognition.start({
language: 'en-US',
maxResults: 1,
partialResults: true,
popup: false
});
// later...
await SpeechRecognition.stop();
Native plugin: the plugin's SpeechRecognition.java lifecycle previously destroyed and recreated the SpeechRecognizer instance on each start/stop cycle. This can cause ERROR_SERVER_DISCONNECTED when the recognition service is unbound/rebound too quickly.
Other information:
- Native error code:
11=SpeechRecognizer.ERROR_SERVER_DISCONNECTED. - Observed on Android API 35 (physical device and emulator).
- Behavior: works on odd attempts (1st, 3rd, ...), fails on even attempts (2nd, 4th, ...).
- Likely root cause: destroying/unbinding the
SpeechRecognizerbetween sessions causes a race with the remote recognition service (Google speech service). Rebinding immediately can result inERROR_SERVER_DISCONNECTED. - Local mitigation that reduces the issue frequency:
- Reuse the
SpeechRecognizerinstance instead of callingdestroy()on every stop. CallstopListening()/cancel()on stop and onlydestroy()on plugin/activity destroy or when receiving ERROR_SERVER_DISCONNECTED. - On
onError()ifERROR_SERVER_DISCONNECTEDis received, explicitly destroy the recognizer and set it tonullto force a fresh create on next start (or attempt a short delay before re-creating).
- Reuse the
- Example recommended pattern (pseudo-Java):
// create once (e.g., in load())
if (speechRecognizer == null) {
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(activity);
}
speechRecognizer.setRecognitionListener(listener);
speechRecognizer.startListening(intent);
// on stop
speechRecognizer.stopListening();
speechRecognizer.cancel();
// do not destroy here - reuse the instance
// on error
if (error == SpeechRecognizer.ERROR_SERVER_DISCONNECTED) {
speechRecognizer.destroy();
speechRecognizer = null;
}- I inspected / modified locally the plugin file:
SpeechRecognition.java
(added logging, added explicit handling to map error 11, and experimented with reusing the recognizer vs destroying on every stop).
If you need full logcat traces, JS console output, or the patch I applied locally (to show the exact changes), I can attach them or open a PR with a recommended fix (reuse recognizer + error-handling + minimal retry/delay).
Capacitor doctor:
💊 Capacitor Doctor 💊
Latest Dependencies:
@capacitor/cli: 7.4.4
@capacitor/core: 7.4.4
@capacitor/android: 7.4.4
@capacitor/ios: 7.4.4
Installed Dependencies:
@capacitor/cli: 7.4.4
@capacitor/ios: 7.4.4
@capacitor/android: 7.4.4
@capacitor/core: 7.4.4
[error] Xcode is not installed
[success] Android looking great! 👌
If helpful, I can prepare a PR that:
- Reuses the
SpeechRecognizerinstance (create once). - Avoids calling
destroy()on normal stop. - Destroys + recreates only on
ERROR_SERVER_DISCONNECTEDor on plugin/activity destroy. - Adds detailed logging and an optional small delay before recreating when necessary.