Handling RecognitionListener Errors

android, speech-recognition

Solution

- If you get recognizer busy error you have to call `cancel` and then call `startListening`

- If you get server or network errors you have to check for network connection before calling `startListening`

Problem

I am using the Android's speech API to continuously getting input from the user. However this doesn't work quite well when errors occur. What I do is restarting the listener in the method that detects error. It works sometime but the recognizer hangs often for some time. Especially after detecting Server, network time out and recognizer busy errors. This is annoying! I have found some attempt to solve this problem, but none of them worked for me. Do you have a better idea? Here i my code: ``` private void startSR(){ intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); //intent.putExtra(RecognizerIntent., value) intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, mContext.getPackageName()); intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 10); Log.d(TAG,"Speech recognition started!"); if (recognizer != null) { recognizer = null; mListener = null; } Log.d(TAG,"setRecognitionListener"); recognizer = SpeechRecognizer.createSpeechRecognizer(mContext); mListener = new Listener(); recognizer.setRecognitionListener(mListener); recognizer.startListening(intent); } class Listener implements RecognitionListener{ @Override public void onBeginningOfSpeech() { Log.i(TAG, "onBeginningOfSpeech"); mStatus = "Beginning speech"; } @Override public void onBufferReceived(byte[] buffer) { Log.i(TAG, "onBufferReceived"); } @Override public void onEndOfSpeech() { Log.i(TAG, "onEndOfSpeech"); mStatus = "Speech ended"; } @Override public void onEvent(int eventType, Bundle params) { Log.i(TAG, "onEvent " + eventType); } @Override public void onPartialResults(Bundle partialResults) { Log.i(TAG, "onPartialResults"); mStatus = "Partial results"; } @Override public void onReadyForSpeech(Bundle params) { Log.i(TAG, "onReadyForSpeech"); mReady = true; mStatus = "Speech engine ready"; } @Override public void onRmsChanged(float rmsdB) { // TODO Auto-generated method stub } @Override public void onError(int error) { // TODO Auto-generated method stub mError = ""; mStatus = "Error detected"; switch (error) { case SpeechRecognizer.ERROR_NETWORK_TIMEOUT: mError = " network timeout"; startListening(); break; case SpeechRecognizer.ERROR_NETWORK: mError = " network" ; //toast("Please check data bundle or network settings"); return; case SpeechRecognizer.ERROR_AUDIO: mError = " audio"; break; case SpeechRecognizer.ERROR_SERVER: mError = " server"; startListening(); break; case SpeechRecognizer.ERROR_CLIENT: mError = " client"; break; case SpeechRecognizer.ERROR_SPEECH_TIMEOUT: mError = " speech time out" ; break; case SpeechRecognizer.ERROR_NO_MATCH: mError = " no match" ; startListening(); break; case SpeechRecognizer.ERROR_RECOGNIZER_BUSY: mError = " recogniser busy" ; break; case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS: mError = " insufficient permissions" ; break; } Log.i(TAG, "Error: " + error + " - " + mError); //startSR(); } @Override public void onResults(Bundle results) { mStatus = "Got some results"; mResultAvailable = true; String str = new String(); Log.d(TAG, "onResults " + results); mResults = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); //mConfidences = results.getDoubleArray(SpeechRecognizer.CONFIDENCE_SCORES); Log.i(TAG, toString()); startListening(); } }// class Listener public ArrayList<String> getResults(){ return mResults; } public void startListening(){ if (SpeechRecognizer.isRecognitionAvailable(mContext)) { if (recognizer!=null){ recognizer.startListening(intent); mResultAvailable = false; mResults = new ArrayList<String>(); } else startSR(); } } ```

Original source