SpeechRecognizer throws onError on the first listening

青春壹個敷衍的年華 提交于 2019-12-29 07:54:14

问题


In the Android 5 I faced with strange problem. The first call to the startListening of SpeechRecognizer results to the onError with error code 7 (ERROR_NO_MATCH).

I made test app with the following code:

if (speechRecognizer == null) {

    speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
    speechRecognizer.setRecognitionListener(new RecognitionListener() {
        @Override
        public void onReadyForSpeech(Bundle bundle) {
            Log.d(TAG, "onReadyForSpeech");
        }

        @Override
        public void onBeginningOfSpeech() {
            Log.d(TAG, "onBeginningOfSpeech");
        }

        @Override
        public void onRmsChanged(float v) {
            Log.d(TAG, "onRmsChanged");
        }

        @Override
        public void onBufferReceived(byte[] bytes) {
            Log.d(TAG, "onBufferReceived");
        }

        @Override
        public void onEndOfSpeech() {
            Log.d(TAG, "onEndOfSpeech");
        }

        @Override
        public void onError(int i) {
            Log.d(TAG, "onError " + i);
        }

        @Override
        public void onResults(Bundle bundle) {
            Log.d(TAG, "onResults");
        }

        @Override
        public void onPartialResults(Bundle bundle) {
            Log.d(TAG, "onPartialResults");
        }

        @Override
        public void onEvent(int i, Bundle bundle) {
            Log.d(TAG, "onEvent");
        }
    });
}

final Intent sttIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
sttIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
        RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
sttIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en");
sttIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en");

speechRecognizer.startListening(sttIntent);

And have this log messages after first startListening call:

onError 7
onReadyForSpeech
onBeginningOfSpeech
onEndOfSpeech
onResults

And following messages after another startListening calls:

onRmsChanged
...
onRmsChanged
onReadyForSpeech
onRmsChanged
...
onRmsChanged
onBeginningOfSpeech
onRmsChanged
...
onRmsChanged
onEndOfSpeech
onRmsChanged
onRmsChanged
onRmsChanged
onResults

So, what is the reason of this error and how do I fix it?


回答1:


I had the same problem but I couldn't find a workaround, so I ended up just calling return inside onError if the time between startListening and onError is unreasonably short.

protected long mSpeechRecognizerStartListeningTime = 0;

protected synchronized void speechRecognizerStartListening(Intent intent) {
    if (mSpeechRecognizer != null) {
        this.mSpeechRecognizerStartListeningTime = System.currentTimeMillis();
        RLog.d(this, "speechRecognizerStartListening");
        this.mSpeechRecognizer.startListening(intent);
    }
}
...
@Override
public synchronized void onError(int error) {
    RLog.i(this, this.hashCode() + " - onError:" + error);

// Sometime onError will get called after onResults so we keep a boolean to ignore error also
    if (mSuccess) {
        RLog.w(this, "Already success, ignoring error");
        return;
    }

    long duration = System.currentTimeMillis() - mSpeechRecognizerStartListeningTime;
    if (duration < 500 && error == SpeechRecognizer.ERROR_NO_MATCH) {
        RLog.w(this, "Doesn't seem like the system tried to listen at all. duration = " + duration + "ms. This might be a bug with onError and startListening methods of SpeechRecognizer");
        RLog.w(this, "Going to ignore the error");
        return;
    }

// -- actual error handing code goes here.
}



回答2:


As soon as you configure the "Okay Google" function to every screen the error appears.

So this seems to be the reason!

Deactivate the function and the problem should be solved




回答3:


Done one workaround.

This is a regular flow

onReadyForSpeech -->onBeginningOfSpeech-->onEndOfSpeech -->onResults

But weired flow

onError(no match) -->onReadyForSpeech -->onBeginningOfSpeech-->onEndOfSpeech -->onResults

So set a boolean on the end of speech to true. and check onError to make sure that it has thrown an error after an end of speech!

speech.startListening(recognizerIntent);
isEndOfSpeech = false;

 @Override
    public void onError(int error) {
        if (!isEndOfSpeech)
            return;
}


 @Override
    public void onEndOfSpeech() { 
        isEndOfSpeech = true; 
    }



回答4:


I had the same problem on several devices. It seems onError(7) is always called before onReadyForSpeech(), so if to avoid using ugly times, you can do something like:

public void start(){
    performingSpeechSetup = true;
    speechRecognizer.startListening(intent);
}

and in the RecognitionListener:

public void onReadyForSpeech(Bundle bundle) {
    performingSpeechSetup = false;
}

@Override
public void onError(int error) {
    if (performingSpeechSetup && error == SpeechRecognizer.ERROR_NO_MATCH) return;
    // else handle error
}



回答5:


Turned out to be very easy in my case. The launching sound of the voice recognition was too loud and triggered the listening process at the very beginning. Turn down the system sound would help. (The volume key)



来源:https://stackoverflow.com/questions/31071650/speechrecognizer-throws-onerror-on-the-first-listening

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!