Некоторое время назад я обнаружил, что 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 пуст. Что это такое и когда оно когда-либо заселяется?
Любые предложения или другие объяснения для решения этой тайны?