TTS onUtteranceCompleted не работает в Android - PullRequest
1 голос
/ 19 сентября 2019

Я работаю над модулем speechRecognizer в Android, интегрированном с диалоговым потоком.Я почти завершил интеграцию, и она работает нормально, но столкнулась с одной проблемой.Проблема в том, что когда TTS произносит ответ, перед завершением голосовой микрофон включается, и он также фиксирует ответ, а не только пользовательское высказывание.Итак, я хочу знать, как я могу узнать, что TTS закончил говорить ответ?Я попытался Google решение с помощью метода onUtteranceCompleted (), а также я попробовал на метод setOnUtteranceProgressListener (), но, похоже, не работает.Я хочу реализовать эти методы в asynctask, так что это может быть сделано в фоновом режиме.Но не знаю, как это сделать.Кто-нибудь может мне помочь?

вот код, который я пробовал: -

import android.Manifest;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.speech.tts.TextToSpeech;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import ai.api.PartialResultsListener;
import ai.api.android.AIConfiguration;
import ai.api.android.GsonFactory;
import ai.api.model.AIError;
import ai.api.model.AIResponse;
import ai.api.ui.AIDialog;
import android.os.AsyncTask;

import com.google.gson.Gson;

public class VoiceActivity extends AppCompatActivity implements View.OnClickListener, TextToSpeech.OnInitListener, RecognitionListener {

    private AIDialog.AIDialogListener resultsListener;
    private static final int REQUEST_AUDIO_PERMISSIONS_ID = 33;

    private Gson gson = GsonFactory.getGson();

    private ListView wordList;
    TextView txtmain;
    private static final int VR_REQUEST = 999;
    //Log tag for output information
    private final String LOG_TAG = "SpeechRepeatActivity";//***enter your own tag here***


    //variable for checking TTS engine data on user device
    private int MY_DATA_CHECK_CODE = 0;

    //Text To Speech instance
    private TextToSpeech tts;

    AIButton aiButton;
    EditText time;
    TextView matchcall;
  //  private SpeechRecognizer speech = null;
    private Intent recognizerIntent;
    TextView tvOutput ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_voice);
        aiButton = (AIButton) findViewById(R.id.speech_btn);
        txtmain =findViewById(R.id.txtmain);
        wordList = findViewById(R.id.word_list);
        tvOutput = findViewById(R.id.tvOutput);
        time = (EditText) findViewById(R.id.in_time);
        matchcall = (TextView) findViewById(R.id.matchcall);
        final AsyncTaskRunner runner = new AsyncTaskRunner();

        initService();

        PackageManager packManager = getPackageManager();
        List<ResolveInfo> intActivities = packManager.queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
        if (intActivities.size() != 0) {
            //speech recognition is supported - detect user button clicks
            aiButton.setOnClickListener(this);
            //prepare the TTS to repeat chosen words
            Intent checkTTSIntent = new Intent();
            //check TTS data
            checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
            //start the checking Intent - will retrieve result in onActivityResult
            startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE);
        } else {
            //speech recognition not supported, disable button and output message
            aiButton.setEnabled(false);
            Toast.makeText(this, "Oops - Speech recognition not supported!", Toast.LENGTH_LONG).show();
        }

    }

        private void setAIButtonCallback(final AIButton aiButton) {
            aiButton.setResultsListener(new AIButton.AIButtonListener() {
                @Override
                public void onResult(final AIResponse result) {
                    if (resultsListener != null) {
                        resultsListener.onResult(result);
                        Log.e(LOG_TAG,"onResult=="+result.getResult().getResolvedQuery());
                        final String speech = result.getResult().getFulfillment().getSpeech();
                        tvOutput.setText(speech);
                    }
                }

                @Override
                public void onError(final AIError error) {
                    if (resultsListener != null) {
                        resultsListener.onError(error);
                        Log.e(LOG_TAG,"onError=="+error);
                    }
                }

                @Override
                public void onCancelled() {
                    if (resultsListener != null) {
                        resultsListener.onCancelled();
                        Log.e(LOG_TAG,"onCancelled==");
                    }
                }
            });

            aiButton.setPartialResultsListener(new PartialResultsListener() {
                @Override
                public void onPartialResults(final List<String> partialResults) {
                    final String result = partialResults.get(0);
                    if (!TextUtils.isEmpty(result)) {
                        new Handler(Looper.getMainLooper()).post(new Runnable() {
                            @Override
                            public void run() {
                                txtmain.setText(result);
                            }
                        });
                    }
                }
            });

        }


    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.speech_btn) {
            //listen for results
            listenToSpeech();
        }
    }


    @Override
    public void onInit(int status) {
//if successful, set locale
        if (status == TextToSpeech.SUCCESS)
            tts.setLanguage(Locale.UK);//***choose your own locale here***
    }


    private void listenToSpeech() {

        SpeechRecognizer speech = SpeechRecognizer.createSpeechRecognizer(this);
        speech.setRecognitionListener(this);
        recognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE,"en");
        recognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,this.getPackageName());
        recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
        recognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,this.getPackageName());

        recognizerIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 3);
        //start listening
        speech.startListening(recognizerIntent);

    }

    @Override
    public void onResults(Bundle results) {

        Log.i(LOG_TAG, "onResults");
        ArrayList<String> matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
      /*  wordList.setAdapter(new ArrayAdapter<String>(this, R.layout.word, matches));
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                wordList.performItemClick(
                        wordList.getChildAt(0),
                        0,
                        wordList.getAdapter().getItemId(0));
                wordList.getChildAt(0).setBackgroundColor(0xFFD3D3D3);
            }
        });*/

        String  wordChosen = matches.get(0);
        tvOutput.setText(wordChosen);
        try {
            AsyncTaskRunner runner = new AsyncTaskRunner();
            runner.execute(wordChosen);
//                    aiButton.textRequest(text);
            //runner.doInBackground(text);
        } catch (Exception e) {
            e.printStackTrace();
        }



    }

    private class AsyncTaskRunner extends AsyncTask<String, AIResponse, AIResponse> {

        private AIResponse resp;
        ProgressDialog progressDialog;

        @Override
        protected AIResponse doInBackground(String... params) {
            Log.e(LOG_TAG,"doInBackground=="+params[0]);
            try {
                resp =  aiButton.textRequest(String.valueOf(params[0]));
            }
            catch (Exception e) {
                e.printStackTrace();

            }
            return resp;
        }



        protected void onPostExecute(AIResponse result) {
            Log.e(LOG_TAG,"onPostExecute== result=="+result.getResult().getFulfillment().getSpeech());

            // execution of result of Long time consuming operation
            findViewById(R.id.progBar).setVisibility(View.GONE);
            txtmain.setText(result.getResult().getFulfillment().getSpeech());
            String speech = result.getResult().getFulfillment().getSpeech();
            tts.speak( speech, TextToSpeech.QUEUE_FLUSH, null);
            Toast.makeText(VoiceActivity.this, speech, Toast.LENGTH_SHORT).show();
            listenToSpeech();

        }


        @Override
        protected void onPreExecute() {
            Log.e(LOG_TAG,"onPreExecute==");
            findViewById(R.id.progBar).setVisibility(View.VISIBLE);
        }

    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        //check speech recognition result
        if (requestCode == VR_REQUEST && resultCode == RESULT_OK)
        {
            //store the returned word list as an ArrayList
            ArrayList<String> suggestedWords = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
            //set the retrieved list to display in the ListView using an ArrayAdapter
            wordList.setAdapter(new ArrayAdapter<String>(this, R.layout.word, suggestedWords));
            /*new Handler().post(new Runnable() {
                @Override
                public void run() {
                    wordList.performItemClick(
                            wordList.getChildAt(0),
                            0,
                            wordList.getAdapter().getItemId(0));
                            wordList.getChildAt(0).setBackgroundColor(0xFFD3D3D3);
                }
            });*/

            tvOutput.setText(suggestedWords.get(0));

        }
        if (requestCode == MY_DATA_CHECK_CODE)
        {
            //we have the data - create a TTS instance
            if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS)
                tts = new TextToSpeech(this, this);
                //data not installed, prompt the user to install it
            else
            {
                //intent will take user to TTS download page in Google Play
                Intent installTTSIntent = new Intent();
                installTTSIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                startActivity(installTTSIntent);
            }
        }

        //call superclass method
        super.onActivityResult(requestCode, resultCode, data);
    }

    private void initService() {
        final AIConfiguration config = new AIConfiguration("a73d5e88477e4926ae84af46f24e0aaa",
                AIConfiguration.SupportedLanguages.English,
                AIConfiguration.RecognitionEngine.Google);
        aiButton.initialize(config);
        setAIButtonCallback(aiButton);

        Log.i(LOG_TAG, "initService:::::: ");

    }


    @Override
    protected void onPause() {
        super.onPause();
//        speech.stopListening();

        // use this method to disconnect from speech recognition service
        new java.util.Timer().schedule(
                new java.util.TimerTask() {
                    @Override
                    public void run() {
                        // your code here
                    }
                },
                5000

        );
        // Not destroying the SpeechRecognition object in onPause method would block other apps from using SpeechRecognition service

    }

    @Override
    protected void onResume() {
        super.onResume();

    }


    @Override
    protected void onStop() {
        Log.i(LOG_TAG, "stop");
        super.onStop();
       /* if (speech != null) {
            speech.destroy();*/
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    //}


    @Override
    protected void onStart() {
        super.onStart();
        checkAudioRecordPermission();
    }

    protected void checkAudioRecordPermission() {
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.RECORD_AUDIO)
                != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.RECORD_AUDIO)) {

            } else {

                // No explanation needed, we can request the permission.

                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.RECORD_AUDIO},
                        REQUEST_AUDIO_PERMISSIONS_ID);
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case REQUEST_AUDIO_PERMISSIONS_ID: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                } else {
                }
                return;
            }
        }
    }

    @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() {
        //speech.stopListening();
    }

    @Override
    public void onError(int errorcode) {

        String errorMessage = getErrorText(errorcode);
        Log.i(LOG_TAG, "FAILED " + errorMessage);
      //  speech.stopListening();
//        listenToSpeech();

    }

    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";
                //speech.stopListening();
                break;
            default:
                message = "Didn't understand, please try again.";
                break;
        }
        return message;
    }




    @Override
    public void onPartialResults(Bundle bundle) {

    }

    @Override
    public void onEvent(int i, Bundle bundle) {

    }


}
...