什么在TtsService可以解释缺乏onUtteranceCompleted()playEarcon()?
前段时间,我发现playEarcon()
永远不会产生 onUtteranceCompleted()
。
当时我只是解释说“当话语被合成时调用”的文档,因为onUtteranceCompleted()
不适用于earcons,因为earcon实际上不是TTS合成的结果。
但再次看Android的源代码,我根本无法find一个解释,certificate我的解释。
关于我的testing夹具的一些事实:
-
onUtteranceCompleted()
总是到达earcon之前的话语ID。 这个话语是一种普通的TTS话语,而不是一个耳塞。 - 之后的耳朵确实发挥出来(即完全按照预期)。
-
onUtteranceCompleted()
对于这个earcon 永远不会出现。 这是非常一致和可重复的行为。
深入研究TtsService源代码,似乎只有两种方法可能影响onUtteranceCompleted()
的到来(或不存在onUtteranceCompleted()
:
- TtsService.processSpeechQueue()
- TtsService.onCompletion()
如果你检查这个代码,你会发现第三个候选人TtsService.getSoundResource()被排除了(因为我的earcon缺lessonUtteranceComplete),因为上面的事实#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<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可以排除,因为我logging了所有的发音标识,耳塞肯定存在。
另外,检查整个系统日志:
Log.v(SERVICE_TAG, "TTS callback: dispatch started");
缺lessonUtteranceCompleted()
可能是dispatchUtteranceCompletedCallback()没有被调用的结果,但也可能是mCallbacksMap.get(packageName)
返回null的结果。
所以,我们又有了两种可能性,这两种可能性对我来说都没有多大意义:
- 当earcon的onCompletion()被调用的时候,earcon的
mCurrentSpeechItem
为null。 但为什么? - mCallbacksMap是空的。 它是什么时候,什么时候有人填充?
任何build议或解决这个谜的解释?
在807行检查android.speech.tts.TextToSpeech#playEarcon() 。 传递给文本到语音服务联编程序的params参数为null,这意味着服务不会收到您的发音ID。
public int playEarcon(String earcon, int queueMode, HashMap<String,String> params) { synchronized (mStartLock) { ... result = mITts.playEarcon(mPackageName, earcon, queueMode, null); } ... }