Инициализация движка Text to Speech является асинхронной, поэтому вы поняли, что вам нужно «дождаться» ее завершения, прежде чем запрашивать, чтобы она обрабатывала высказывание.
Даже если он в конечном итоге инициализируется успешно, он может быть впоследствии уничтожен системой или, конечно, может не инициализироваться, поэтому вам всегда нужно быть готовым к обработке запроса на разговор, где двигатель не подготовлен ,
Добавьте следующий вспомогательный класс
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;
}
}
Предполагая, что вы используете Activity
, вам необходимо объявить следующие переменные:
private volatile PendingTTS pendingTTS;
private static final int MAX_INIT_ATTEMPTS = 4;
private volatile int initCount;
и инициализацию текст к объекту речи в onCreate()
tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
В вашем 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;
}
Я приклеен выше вместе с моего кода - где речь и метода инициализации все отделенной, но я попытался дать вам обзор выше всего вам нужно справиться.
В другом месте вашего кода, когда вы делаете запрос tts.speak(//stuff here)
, вам необходимо проверить результат, как показано выше, чтобы убедиться, что он был успешным. Опять же, в моем коде это разделено на один единственный метод. Если это не удастся, вам необходимо установить параметры PendingTTS перед повторной попыткой инициализацию:
pendingTTS = new PendingTTS();
pendingTTS.setPendingQueueType(// your queue type);
pendingTTS.setPendingUtterance(// your utterance);
Это успешно, убедитесь, что pendingTTS
установлено нулевое значение.
Общая конструкция заключается в том, что если инициализация не удалась, она попытается снова инициализировать, вплоть до максимально допустимых попыток. Если реплика не удалась, она попытается снова инициализировать двигатель, сначала установив параметры PendingTTS
.
Надеюсь, вам удалось это сделать.
Это неверное описание. ProgressListener отслеживает речь, а не инициализацию двигателя. – brandall
Плохо, качаюсь с потоком, который у меня есть, где я создаю аудио. Обновлен ответ. – sumandas