针对API >21版本,setTextToSpeech中的setOnUtteranceProgressListener方法完全不起作用。

6

我希望setOnUtteranceProgressListener在语音完成后通知一个Toast。但是似乎没有起作用。 我已经使用了setOnUtteranceProgressListener并在说话函数中如下所示提到了参数

    Bundle params = new Bundle();
    params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, MainActivity.this.getPackageName());

在调用speak函数时,我提供了一个名为“UniqueId”的唯一标识符。

    myTTS.speak(message,TextToSpeech.QUEUE_FLUSH,params,"UniqueId");

在我的程序中,文本转语音引擎完成说话后应该运行一个Toast提示已经完成说话。但是setOnUtteranceProgressListner似乎不起作用。

    myTTS.setOnUtteranceProgressListener(new UtteranceProgressListener() {
        @Override
        public void onStart(String utteranceId) {

        }

        @Override
        public void onDone(String utteranceId) {

            Toast.makeText(MainActivity.this,"Finished speaking.",Toast.LENGTH_LONG).show();
        }

        @Override
        public void onError(String utteranceId) {

        }
    });

以下是完整的代码:

所有的代码如下:

    public class MainActivity extends AppCompatActivity {
String message;
private TextToSpeech myTTS;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    myTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
        @Override
        public void onInit(int status) {
            if(myTTS.getEngines().size() == 0){
                Toast.makeText(MainActivity.this,"No Engines Installed",Toast.LENGTH_LONG).show();
            }else{
                myTTS.setLanguage(Locale.US);

                if (status == TextToSpeech.SUCCESS){
                    //Toast.makeText(MainActivity.this,"Status working.",Toast.LENGTH_LONG).show();
                    message = "How may i help you.";
                }

            }
        }
    });

    myTTS.setOnUtteranceProgressListener(new UtteranceProgressListener() {
        @Override
        public void onStart(String utteranceId) {

        }

        @Override
        public void onDone(String utteranceId) {

            Toast.makeText(MainActivity.this,"onDone working.",Toast.LENGTH_LONG).show();
        }

        @Override
        public void onError(String utteranceId) {

        }
    });
}

请为此提供一个解决方案。
2个回答

12

主要问题如下:

1) 在tts 初始化之前设置进度监听器。

2) 尝试在后台线程中制作Toast提示。

我还有一些其他建议性的更改,但并非必需:

public class MainActivity extends AppCompatActivity {
    String message = "How may I help you?";
    String mostRecentUtteranceID;
    private TextToSpeech myTTS;

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

        myTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if(myTTS.getEngines().size() == 0){
                    Toast.makeText(MainActivity.this,"No Engines Installed",Toast.LENGTH_LONG).show();
                }else{
                    if (status == TextToSpeech.SUCCESS){
                        ttsInitialized();
                    }
                }
            }
        });
    }

    private void ttsInitialized() {

        // *** set UtteranceProgressListener AFTER tts is initialized ***
        myTTS.setOnUtteranceProgressListener(new UtteranceProgressListener() {
            @Override
            public void onStart(String utteranceId) {

            }

            @Override
            // this method will always called from a background thread.
            public void onDone(String utteranceId) {

                // only respond to the most recent utterance
                if (!utteranceId.equals(mostRecentUtteranceID)) { 
                    Log.i("XXX", "onDone() blocked: utterance ID mismatch.");
                    return; 
                } // else continue...

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

                Log.i("XXX", "onDone working.");

                // for demonstration only... avoid references to 
                // MainActivity (unless you use a WeakReference)
                // inside the onDone() method, as it
                // can cause a memory leak.
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // *** toast will not work if called from a background thread ***
                        Toast.makeText(MainActivity.this,"onDone working.",Toast.LENGTH_LONG).show();
                    }
                });
            }

            @Override
            public void onError(String utteranceId) {

            }
        });

        // set Language
        myTTS.setLanguage(Locale.US);

        // set unique utterance ID for each utterance
        mostRecentUtteranceID = (new Random().nextInt() % 9999999) + ""; // "" is String force

        // set params
        // *** this method will work for more devices: API 19+ ***
        HashMap<String, String> params = new HashMap<>();
        params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, mostRecentUtteranceID);

        myTTS.speak(message,TextToSpeech.QUEUE_FLUSH,params);

    }

}

可以告诉我你的 Gmail ID 吗? - Ranjit Vamadevan
我怎样能够在主活动中直接运行speak()方法而不需要按按钮呢? - Ranjit Vamadevan
2
不,但你可以随时问另一个问题。很高兴我能帮到你。 - Nerdy Bunz
请查看这个问题。https://stackoverflow.com/questions/52217161/problem-retrieve-similar-child-element-of-firebase - Ranjit Vamadevan
请查看这个问题。https://stackoverflow.com/questions/52379857/how-to-code-with-recognizerintent-action-voice-search-hands-free-in-speech-recog - Ranjit Vamadevan
显示剩余2条评论

6

如果您想添加 OnUtteranceProgressListener 回调,您需要像这样实现 speak 方法:

myTTS.speak(message,TextToSpeech.QUEUE_FLUSH, null , TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID);

然后它将调用你已经实现的方法(例如onStart、onDone等)


1
为我解决问题的是添加语音ID。虽然不确定原因(在Android 10上测试)。 - Mohamed Salah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接