2016-08-16 2 views
2

У меня была проблема, когда Text to Speech ничего не говорил. Я понял, что это было связано с тем, что я пытался вызвать «Speak()» до того, как TTS инициализировался.Android Подождите, пока текст в речь OnInit называется

Мне нужно подождать, пока 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(); 
    } 
} 

Но это не может инициализироваться вообще. Есть ли способ сделать это эффективно?

ответ

1

Хмм .. Не очень хорошая идея.

Вы можете попробовать добавить текст в очередь TTS и позволить ему выполнять свою работу. Этот фрагмент может быть внутри нажатия кнопки, и т.д., как:

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

Малый tutorial, который помог бы.

+0

Это неверное описание. ProgressListener отслеживает речь, а не инициализацию двигателя. – brandall

+0

Плохо, качаюсь с потоком, который у меня есть, где я создаю аудио. Обновлен ответ. – sumandas

2

Инициализация движка 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.

Надеюсь, вам удалось это сделать.

+0

Что делать, если вы попытаетесь использовать функцию speak(), но она еще не инициализирована? Если вы сделаете это так, как вы предлагали, не будет ли значительная задержка в произношении, нажав кнопку и говорящий (как вам придется переинициализировать и ждать, когда OnInit будет уволен?) Можно ли что-то сделать например: определить, была ли инициализирована инициализация или нет, если она не указана, отобразится диалог прогресса до тех пор, пока он не появится? – Daniel

+0

@ Daniel Ваш метод произнесения будет пытаться говорить как обычно, в любой реализации. Если он возвращает «ERROR», вам нужно попытаться инициализировать движок, а затем обработать любую ожидающую речь, как показано выше. В большинстве случаев вы надеетесь, что он уже инициализирован, поэтому он будет говорить сразу. В противном случае вы можете поднять уведомление между началом инициализации и удалить его, когда ваш 'UtteranceProgressListener' называет 'onStart' – brandall

Смежные вопросы