Подтвердить что ты не робот

Что в TtsService может объяснить отсутствие onUtteranceCompleted() для playEarcon()?

Некоторое время назад я обнаружил, что playEarcon() никогда не производит onUtteranceCompleted().

В то время я просто интерпретировал документацию, в которой говорилось: "Вызывается, когда высказывание было синтезировано", поскольку onUtteranceCompleted() не применимо для earcons, потому что earcon на самом деле не является результатом TTS synthesization.

Но, глядя снова на исходный код Android, я просто не могу найти объяснение, которое оправдывало бы мою интерпретацию.

Несколько фактов о моем тестовом зажимке:

  • onUtteranceCompleted() всегда приходит для идентификатора высказывания, предшествующего ушной гарнитуре. Это высказывание - обычное высказывание TTS, а не ухо.
  • После того, как выполнит, ушной гарнизон (т.е. точно так, как предполагалось).
  • onUtteranceCompleted() для того, что появляется никогда. Это очень последовательное и воспроизводимое поведение.

Вдаваясь глубоко в исходный код TtsService, похоже, всего 2 метода, которые могут повлиять на приход (или отсутствие) onUtteranceCompleted():

Если вы изучите этот код, вы увидите, что третий кандидат, TtsService.getSoundResource() исключается (как ответственный за отсутствие onUtteranceComplete для моего наушника) из-за факта № 2 выше: ушник всегда играет, следовательно getSoundResource() не может вернуть нуль.

Используя ту же логику, 1-й кандидат, TtsService.processSpeechQueue(), также может быть исключен из-за того же факта # 2: Earcon всегда играет, поэтому следующие два критических оператора всегда выполняются:

1108   mPlayer.setOnCompletionListener(this);
...
1111   mPlayer.start();

Итак, у нас осталось только 2-й кандидат, TtsService.onCompletion(), как возможное объяснение того, почему a playEarcon() никогда не производит onUtteranceCompleted():

public void onCompletion(MediaPlayer arg0) {
  // mCurrentSpeechItem may become null if it is stopped at the same
  // time it completes.
  SpeechItem currentSpeechItemCopy = mCurrentSpeechItem;
  if (currentSpeechItemCopy != null) {
    String callingApp = currentSpeechItemCopy.mCallingApp;
    ArrayList<String> params = currentSpeechItemCopy.mParams;
    String utteranceId = "";
    if (params != null) {
      for (int i = 0; i < params.size() - 1; i = i + 2) {
        String param = params.get(i);
        if (param.equals(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID)) {
          utteranceId = params.get(i + 1);
        }
      }
    }
    if (utteranceId.length() > 0) {
      dispatchUtteranceCompletedCallback(utteranceId, callingApp);
    }
  }
  processSpeechQueue();
}

Там есть только 2 условия, которые не смогли бы произвести dispatchUtteranceCompletedCallback():

  • currentSpeechItemCopy == null
  • utteranceId.length() == 0

Но я точно знаю, что условие №2 можно исключить из-за того, что я регистрирую все выражения utteranceIds, и гарнитура определенно существует.

Кроме того, проверка всего системного журнала:

Log.v(SERVICE_TAG, "TTS callback: dispatch started");

Отсутствующий onUtteranceCompleted() может быть результатом dispatchUtteranceCompletedCallback(), который не вызывается, но также может быть результатом mCallbacksMap.get(packageName) возврат null.

Итак, мы снова остаемся с двумя возможностями, обе из которых не приносят мне большого смысла:

  • К моменту вызова onCompletion(), earcon mCurrentSpeechItem имеет значение null. Но почему?
  • mCallbacksMap пуст. Что это такое и когда оно когда-либо заселяется?

Любые предложения или другие объяснения для решения этой тайны?

4b9b3361

Ответ 1

Отметьте android.speech.tts.TextToSpeech # playEarcon() в строке 807. Аргумент params, передаваемый в текстовое сообщение, имеет значение NULL, что означает, что служба никогда не получает ваш идентификатор высказывания.

 public int playEarcon(String earcon, int queueMode,
         HashMap<String,String> params) {
     synchronized (mStartLock) {
         ...
         result = mITts.playEarcon(mPackageName, earcon, queueMode, null);
     }
     ...
 }