使用onUtteranceProgressListener重新启动SpeechRecognizer

时间:2019-12-30 02:34:22

标签: android

尽管似乎很容易解决,但我已经在此代码上工作了数周之久,却根本没有任何进展!基本上,我使用的是带有SpeechRecognizer的TextToSpeech,以使应用程序向我提出问题,然后听听我的回答。这是我的代码...我在想这是线程问题或其他问题。

基本上,当我按住按钮时,SPeechRecognizer会开始监听,直到我松开手指为止……这可以正常工作。.但是我以编程方式希望SpeechUcognizer在“话语完成”后重新启动,或者模拟按下按钮使其进入工作,但都不行...

public class MainActivity extends AppCompatActivity {    


TextToSpeech textToSpeech;

// SpeechRecognizer
SpeechRecognizer mSpeechRecognizer;
Intent mSpeechRecognizerIntent;

// Speech Analysis Support
SpeechToTextAnalyzer speechToTextAnalyzer;
String speechToTextAnalyzerResponse;
String SPEECH_RESPONSE_BACK;
int buttonPressCounter;
boolean responsive;


TextView StatusDisplay, WordingDisplay;
Button SimulateButton;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    checkPermission();
    buttonPressCounter = 0;


    // Initialize TextToSpeech
    textToSpeech = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {

        @Override
        public void onInit(int status) {

            if(status != TextToSpeech.ERROR) {
                textToSpeech.setLanguage(Locale.CANADA);
            }

            textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {


                @Override
                public void onStart(String utteranceId) {
                    // Speaking started.
                }

                @Override
                public void onDone(String utteranceId) {
                    // Speaking stopped.
                    if(responsive){      // if(utteranceId == "LISTEN_FOR_NEW_RESPONSE")

                        // possible method one:
                        SimulateButton.performClick();

                        // possible method two:
                        //mSpeechRecognizer.startListening(mSpeechRecognizerIntent);

                        // NOTE: SO FAR NEITHER OF THESE LINES MAKE THE SPEECHRECOGNIZER START UP WITHOUT ME TOUCHING THE BUTTON!!!
                    }
                }

                @Override
                public void onError(String utteranceId) {
                    // There was an error.
                }
            });


        }



    });


    // Initialize UI View Components
    StatusDisplay = (TextView)findViewById(R.id.StatusUpdater);
    WordingDisplay = (TextView)findViewById(R.id.WordsHeard);

    // Create Reference to Classes
    speechToTextAnalyzer = new SpeechToTextAnalyzer(this, this);


    // Initialize SpeechRecognizer and Intent
    final SpeechRecognizer mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
    final Intent mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
            RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
    mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE,
            Locale.getDefault());
    mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);


    mSpeechRecognizer.setRecognitionListener(new RecognitionListener() {

        @Override
        public void onReadyForSpeech(Bundle bundle) {
        }

        @Override
        public void onBeginningOfSpeech() {
        }

        @Override
        public void onRmsChanged(float v) {
        }

        @Override
        public void onBufferReceived(byte[] bytes) {
        }

        @Override
        public void onEndOfSpeech() {
        }

        @Override
        public void onError(int errorCode) {
            String errorMessage = getErrorText(errorCode);
            //Log.d(LOG_TAG, "FAILED " + errorMessage);
            //listeningOn = false;                // UNSURE!!

        }

        // accompanying text for onError
        public String getErrorText(int errorCode) {
            String message;
            switch (errorCode) {

                case SpeechRecognizer.ERROR_AUDIO:
                    message = "Audio Recording Error";
                    break;
                case SpeechRecognizer.ERROR_CLIENT:
                    message = "Client Side Error";
                    break;
                case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS:
                    message = "Insufficient Permissions";
                    break;
                case SpeechRecognizer.ERROR_NETWORK:
                    message = "Network Error";
                    break;
                case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
                    message = "Network TimeOut";
                    break;
                case SpeechRecognizer.ERROR_NO_MATCH:
                    message = "No Match";
                    break;
                case SpeechRecognizer.ERROR_RECOGNIZER_BUSY:
                    message = "RecognitionService Busy";
                    break;
                case SpeechRecognizer.ERROR_SERVER:
                    message = "Error From Server";
                    break;
                case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
                    message = "No Speech Input";
                    break;
                default:
                    message = "Couldn't Understand, Please Try Again";
                    break;
            }
            return message;

        }

        @Override
        public void onResults(Bundle bundle) {
            //getting all the matches
            ArrayList<String> matches = bundle
                    .getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);

            String firstMatch = "";

            //displaying the first match
            if (matches != null) {

                for(int i = 0; i < matches.size(); i++){
                    firstMatch = matches.get(i);     // get the last one, which has the actual words I spoke...
                }
                matches.clear();

            }

            //StatusDisplay.setText("Not Listening...");

            // ENTRY POINT FOR ALL COMMAND FUNCTIONALITY
            speechToTextAnalyzerResponse = speechToTextAnalyzer.AnalyzeSpeechSingleResponse(firstMatch);
            buttonPressCounter = speechToTextAnalyzer.AnalyzeSpeechCounter(buttonPressCounter);
            responsive = speechToTextAnalyzer.AnalyzeSpeechResponseThenListen(buttonPressCounter);


            SPEECH_RESPONSE_BACK = speechToTextAnalyzerResponse;

            WordingDisplay.setText(SPEECH_RESPONSE_BACK);

            if(responsive){
                RESPONSIVE_SPEECH("... okay now say something new ... ");
            }
            else {
                SINGLE_RESPONSE();
            }

        }

        @Override
        public void onPartialResults(Bundle bundle) {
        }

        @Override
        public void onEvent(int i, Bundle bundle) {
        }
    });     // end of mSpeechRecognizer.setRecognitionListener


    SimulateButton = (Button)findViewById(R.id.DoSomething);

    SimulateButton.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_UP:
                    //when the user removed the finger

                    mSpeechRecognizer.stopListening();
                    StatusDisplay.setText("Not Listening...");

                    break;


                case MotionEvent.ACTION_DOWN:
                    //finger is on the button

                    StatusDisplay.setText("Listening...");
                    mSpeechRecognizer.startListening(mSpeechRecognizerIntent);
                    // WHILE I HOLD BUTTON THIS ACTUALLY WORKS BUT NOT INSIDE ONUTTERANCEPROGRESSLISTENER.........

                    break;


            }
            return true;
        }
    });







}   // end of onCreate()




public void SINGLE_RESPONSE(){

    if (!textToSpeech.isSpeaking()) {
        textToSpeech.speak(SPEECH_RESPONSE_BACK, TextToSpeech.QUEUE_FLUSH, null);
        //textToSpeech.speak(WordingDisplay.getText().toString(), TextToSpeech.QUEUE_FLUSH, null);
    } else {
        textToSpeech.stop();
    }

}

public void RESPONSIVE_SPEECH(String PleaseSayThis){

    SPEECH_RESPONSE_BACK = PleaseSayThis;

    // https://android-developers.googleblog.com/2009/09/introduction-to-text-to-speech-in.html
    if (!textToSpeech.isSpeaking()) {
        HashMap<String, String> stringStringHashMap = new HashMap<String, String>();
        stringStringHashMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "LISTEN_FOR_NEW_RESPONSE");        // when using normal text to speech, the ID is "ID_MAIN_CALL" to be searched for in onUtteranceCompleted
        textToSpeech.speak(SPEECH_RESPONSE_BACK, textToSpeech.QUEUE_FLUSH, stringStringHashMap);
    } else {
        textToSpeech.stop();
    }

}

 private void checkPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!(ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED)) {
            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                    Uri.parse("package:" + getPackageName()));
            startActivity(intent);
            finish();
        }
    }
}


protected void onDestroy(){

    if(textToSpeech != null) {
        textToSpeech.stop();
        textToSpeech.shutdown();
        textToSpeech = null;
    }

    super.onDestroy();

}

1 个答案:

答案 0 :(得分:0)

根据UtteranceProgressListener docs,“可以从多个线程中调用此方法中指定的回调。”

要验证这一点,您可以添加

boolean wasCalledFromBackgroundThread = (Thread.currentThread().getId() != 1);
                Log.i("XXX", "was onDone() called on a background thread? : " + wasCalledFromBackgroundThread);

到onDone()方法主体。

根据我的经验,在后台线程上调用它们的频率更高。

因此,在您的onDone()方法主体中,我建议使用runOnUiThread()围绕UI操作,如下所示:

@Override
public void onDone(String utteranceId) {

    runOnUiThread(new Runnable() {
        @Override
        public void run() {

            // possible method one:
            SimulateButton.performClick();

            // possible method two:
            //mSpeechRecognizer.startListening(mSpeechRecognizerIntent);

        }

     });

}