不久前,我发现playEarcon() never produces onUtteranceCompleted()

当时,我只是解释了文档“说出话已经被合成调用”的文档,因为onUtteranceCompleted()不适用于耳塞,因为耳塞实际上并不是TTS合成的结果。

但是再看一下Android的源代码,我根本找不到可以证明我的解释合理的解释。

有关my test jig的一些事实:

  • onUtteranceCompleted()总是在耳标之前到达发话ID。这种话语是普通的TTS话语,而不是耳塞。
  • 那个之后的耳机会播放(即完全按照预期)。
  • 该耳标的
  • onUtteranceCompleted() 从不显示。这是非常一致且可重现的行为。

  • 深入研究TtsService源代码,似乎只有两种方法可能会影响onUtteranceCompleted()的到达(或缺少):
  • TtsService.processSpeechQueue()
  • TtsService.onCompletion()

  • 如果您检查该代码,则将由于上述事实#2而排除了第三个候选者TtsService.getSoundResource()(这是造成我的Earcon缺少onUtteranceComplete的原因):耳机始终播放,因此getSoundResource()可能不会返回null。

    使用相同的逻辑,对于第二个事实,也可以排除第一个候选者TtsService.processSpeechQueue():耳塞始终在播放,因此始终执行以下两个关键语句:
    1108   mPlayer.setOnCompletionListener(this);
    ...
    1111   mPlayer.start();
    

    因此,我们只剩下第二个候选者TtsService.onCompletion(),作为关于为什么playEarcon() never produces 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,因为我记录了所有utteranceId,并且耳塞肯定在那里。

    另外,检查整个系统日志:
    Log.v(SERVICE_TAG, "TTS callback: dispatch started");
    

    缺少的onUtteranceCompleted()可能是由于未调用dispatchUtteranceCompletedCallback()导致的,但也可能是mCallbacksMap.get(packageName)返回null的结果。

    因此,我们再次有两种可能性,这两种方法对我来说意义不大:
  • 在调用earcon的onCompletion()时,earcon的mCurrentSpeechItem为空。但是为什么呢?
  • mCallbacksMap为空。它是什么?何时填充?

  • 对于解决这个谜题有什么建议或其他解释吗?

    最佳答案

    android.speech.tts.TextToSpeech#playEarcon()行检查807。传递给文本语音转换服务绑定(bind)器的params参数为null,这意味着该服务永远不会收到您的语音ID。

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

    08-26 03:15