什么在TtsService可以解释缺乏onUtteranceCompleted()playEarcon()?

前段时间,我发现playEarcon() 永远不会产生 onUtteranceCompleted()

当时我只是解释说“当话语被合成时调用”的文档,因为onUtteranceCompleted()不适用于earcons,因为earcon实际上不是TTS合成的结果。

但再次看Android的源代码,我根本无法find一个解释,certificate我的解释。

关于我的testing夹具的一些事实:

  1. onUtteranceCompleted()总是到达earcon之前的话语ID。 这个话语是一种普通的TTS话语,而不是一个耳塞。
  2. 之后的耳朵确实发挥出来(即完全按照预期)。
  3. onUtteranceCompleted()对于这个earcon 永远不会出现。 这是非常一致和可重复的行为。

深入研究TtsService源代码,似乎只有两种方法可能影响onUtteranceCompleted()的到来(或不存在onUtteranceCompleted()

  1. TtsService.processSpeechQueue()
  2. 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() :

  1. currentSpeechItemCopy == null
  2. utteranceId.length()== 0

但是我确实知道条件#2可以排除,因为我logging了所有的发音标识,耳塞肯定存在。

另外,检查整个系统日志:

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

缺lessonUtteranceCompleted()可能是dispatchUtteranceCompletedCallback()没有被调用的结果,但也可能是mCallbacksMap.get(packageName)返回null的结果。

所以,我们又有了两种可能性,这两种可能性对我来说都没有多大意义:

  1. 当earcon的onCompletion()被调用的时候,earcon的mCurrentSpeechItem为null。 但为什么?
  2. 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); } ... }