Некоторое время назад я обнаружил, чтоplayEarcon()
никогда не производитonUtteranceCompleted()
.
В то время я просто интерпретировал документацию, в которой говорилось: «Вызывается, когда высказывание было синтезировано » как onUtteranceCompleted()
, неприменимое для Earcons, потому что Earcon на самом деле не является результатом синтеза TTS.
Но просматривая исходный код Android, я просто не могу найти объяснение, которое оправдывало бы мою интерпретацию.
Несколько фактов о моем тестовом стенде:
onUtteranceCompleted()
всегда приходит для идентификатора высказывания, предшествующего Earcon. Это высказывание является обычным высказыванием TTS, а не слуховым аппаратом.onUtteranceCompleted()
ибо этот слуховой аппарат никогда не появляется. Это очень последовательное и воспроизводимое поведение.Углубляясь в исходный код TtsService, кажется, что есть только 2 метода, которые могут повлиять на появление (или отсутствие )onUtteranceCompleted()
:
Если вы изучите этот код, вы увидите, что третий кандидат, TtsService.getSoundResource()исключается (как ответственный за отсутствие onUtteranceComplete для моего наушника )из-за факта #2 выше :Earcon всегда воспроизводится, поэтому getSoundResource()
не может возвращать значение null.
Используя ту же логику, первый кандидат, TtsService.processSpeechQueue(), также можно исключить, по тому же факту #2 :Earcon всегда играет, поэтому всегда выполняются следующие 2 критических утверждения:
1108 mPlayer.setOnCompletionListener(this);
...
1111 mPlayer.start();
Итак, у нас остался только второй кандидат, TtsService.onCompletion(), как возможное объяснение того, почему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 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():
Но я точно знаю, что условие #2 можно исключить, потому что я логирую все utteranceId и earcon'ы точно есть.
Кроме того, просмотр всего системного журнала:
Log.v(SERVICE_TAG, "TTS callback: dispatch started");
Отсутствующий onUtteranceCompleted()
может быть результатом dispatchUtteranceCompletedCallback()не вызывается, но это также может быть результатом того, что mCallbacksMap.get(packageName)
возвращает null.
Итак, у нас снова осталось 2 возможности,и то, и другое не имеет для меня особого смысла:
mCurrentSpeechItem
имеет значение null. Но почему?Любые предложения или другие объяснения для решения этой тайны?