Q:

Handling RecognitionListener Errors

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();
    }
}

A:

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

