Java Android会一直等到调用文本到语音的OnInit

Java Android会一直等到调用文本到语音的OnInit,java,android,text-to-speech,Java,Android,Text To Speech,我有一个问题,文字到语音不能说任何东西。我意识到这是因为我在TTS初始化之前试图调用“Speak()” 我需要等到TTS初始化后,才能成功调用“Speak()”。我认为按照这条思路做一些事情会奏效: @Override public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { mTTSInitialised = true; } else { Log.e("TTS",

我有一个问题,文字到语音不能说任何东西。我意识到这是因为我在TTS初始化之前试图调用“Speak()”

我需要等到TTS初始化后,才能成功调用“Speak()”。我认为按照这条思路做一些事情会奏效:

@Override
public void onInit(int status) {
    if (status == TextToSpeech.SUCCESS) {
        mTTSInitialised = true;
    } else {
        Log.e("TTS", "Initialisation Failed!");
    }
}

...

while(!mTTSInitialised){
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
但这根本无法初始化。有没有办法有效地做到这一点?

嗯。。 这不是个好主意

您可以尝试将文本添加到TTS队列,并让它完成它的工作。此代码段可以位于按钮单击等内部,如下所示:

tts.speak(toSpeak, TextToSpeech.QUEUE_ADD, null);

这会有帮助。

文本到语音引擎的初始化是异步的,这就是为什么您意识到在请求它处理一个话语之前,必须“等待”它完成的原因

即使它最终成功初始化,它也可能随后被系统终止,当然也可能无法初始化,因此在引擎未准备好的情况下,您始终需要准备好处理发言请求

添加以下帮助器类

public class PendingTTS {

    private String pendingUtterance;
    private int pendingQueueType;

    public String getPendingUtterance() {
        return this.pendingUtterance;
    }

    public void setPendingUtterance(@NonNull final String pendingUtterance) {
        this.pendingUtterance = pendingUtterance;
    }

    public int getPendingQueueType() {
        return this.pendingQueueType;
    }

    public void setPendingQueueType(final int pendingQueueType) {
        this.pendingQueueType = pendingQueueType;
    }
}
假设您使用的是
活动
,则需要声明以下变量:

private volatile PendingTTS pendingTTS;
private static final int MAX_INIT_ATTEMPTS = 4;
private volatile int initCount;
并在
onCreate()中初始化文本到语音对象

在您的
onInitListener
中,您将检查是否有任何悬而未决的演讲:

@Override
public void onInit(final int status) {

    switch (status) {

        case TextToSpeech.SUCCESS:
            initCount = 0;
            // Set up tts stuff
            tts.setOnUtteranceProgressListener(YOURprogressListener);

            if (pendingTTS != null) {

                // We have pending speech, process it and check the result

                int speechResult = tts.speak(pendingTTS.getPendingUtterance(),pendingTTS.getPendingQueueType(),
                        // remaining tts variables here)

                switch (speechResult){

                    case TextToSpeech.SUCCESS:

                        // Result was successful
                        pendingTTS = null;

                        break;
                    case TextToSpeech.ERROR:
                        // Speech failed
                        // Check if it has repeatedly failed up to the max attempts
                        if(initCount < MAX_INIT_ATTEMPTS){
                            initCount ++;
                            tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
                        } else {
                            // Totally broken - let the user know it's not working
                        }

                        break;
                }
            } else {
                // there was nothing to process
            }

            break;
        case TextToSpeech.ERROR:

            // Check if it has repeatedly failed up to the max attempts
            if(initCount < MAX_INIT_ATTEMPTS){
                initCount ++;
                tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
            } else {
                // Totally broken - let the user know it's not working
            }

            break;
    }
如果成功,请确保
pendingts
设置为空

总体设计是,如果初始化失败,它将尝试再次初始化,直到允许的最大尝试次数。如果语音失败,它将尝试再次初始化发动机,首先设置
pendingts
参数


希望您能做到这一点。

这是错误的。监听器跟踪演讲,而不是引擎的初始化。我很糟糕,在我创建音频的地方,它随着我的声音流动而摇摆。更新了答案。如果您尝试使用speak(),但它尚未初始化,该怎么办?如果你按照你的建议去做,会不会有相当大的延迟,比如说,点击一个按钮,然后它说话(因为你必须重新初始化并等待onInit被激活?),是否可以做一些类似的事情:检测它是否已经被初始化,如果没有,显示进度对话框,直到它有?@Daniel在任何实现中,您的speak方法都会尝试正常说话。如果返回
ERROR
,则需要尝试初始化引擎,然后处理任何挂起的语音,如上所示。在大多数情况下,你会希望它已经被草签,所以它会立即说话。否则,当您的
utranceprogresslistener
调用“onStart”时,您可能会在启动初始化和删除初始化之间发出通知
@Override
public void onInit(final int status) {

    switch (status) {

        case TextToSpeech.SUCCESS:
            initCount = 0;
            // Set up tts stuff
            tts.setOnUtteranceProgressListener(YOURprogressListener);

            if (pendingTTS != null) {

                // We have pending speech, process it and check the result

                int speechResult = tts.speak(pendingTTS.getPendingUtterance(),pendingTTS.getPendingQueueType(),
                        // remaining tts variables here)

                switch (speechResult){

                    case TextToSpeech.SUCCESS:

                        // Result was successful
                        pendingTTS = null;

                        break;
                    case TextToSpeech.ERROR:
                        // Speech failed
                        // Check if it has repeatedly failed up to the max attempts
                        if(initCount < MAX_INIT_ATTEMPTS){
                            initCount ++;
                            tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
                        } else {
                            // Totally broken - let the user know it's not working
                        }

                        break;
                }
            } else {
                // there was nothing to process
            }

            break;
        case TextToSpeech.ERROR:

            // Check if it has repeatedly failed up to the max attempts
            if(initCount < MAX_INIT_ATTEMPTS){
                initCount ++;
                tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
            } else {
                // Totally broken - let the user know it's not working
            }

            break;
    }
    pendingTTS = new PendingTTS();
    pendingTTS.setPendingQueueType(// your queue type);
    pendingTTS.setPendingUtterance(// your utterance);