34

これまでに、私はそれを発見しましたplayEarcon()never producesonUtteranceCompleted()。私はちょうどearconが本当にTTSの合成の結果ではない、のでonUtteranceCompleted()はイアコンには適用されないものとして「発話がを合成されたときに呼び出されます」と述べた文書を解釈する時にはTitsServiceでplayEarcon()のonUtteranceCompleted()が不足していると説明できますか?

Androidのソースコードをもう一度見れば、私の解釈を正当化する説明は見つけられません。

my test jigに関するいくつかの事実:

  1. onUtteranceCompleted()は常にearconの前の発話IDのために到着しました。その発話は普通のTTSの発話であり、イヤコンではない。
  2. それ以降のイヤコンは、です。が再生されます(つまり、意図した通りです)。
  3. onUtteranceCompleted()イヤコンが表示されません。これは非常に一貫性のある再現性のある動作です。深いTtsServiceソースコードに踏み込ん

onUtteranceCompleted()の到着(または不在)に影響を与えることができる唯一の2つの方法があるように思われる:

  1. TtsService.processSpeechQueue()
  2. TtsService.onCompletion()

そのコードを調べると、3番目の候補であるTtsService.getSoundResource()が除外されていることがわかります(自分の電子メールにonUtteranceCompleteがないarcon)上の事実#2のために:earconは常に再生するので、getSoundResource()はおそらくnullを返すことができません。 earconは常に果たしている、したがって、次の2つの重要なステートメントが常に実行されています:

1108 mPlayer.setOnCompletionListener(this); 
... 
1111 mPlayer.start(); 

同じロジックを使用して、第一候補、TtsService.processSpeechQueue()は、また同じ事実#2のため、除外することができる

だから、私たちはなぜplayEarcon()never producesonUtteranceCompleted()のための可能な説明として、TtsService.onCompletion()、唯一の第二候補が残されています。

そこで
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(); 
} 

、pは失敗する唯一の2つの条件がありますroduce dispatchUtteranceCompletedCallback()

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

しかし、私はすべてのutteranceIdsとログので、条件#2を除外することができることを確実に知りますイヤコンは間違いなくそこにあります。また

、システム全体のログを調べる:

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

行方不明onUtteranceCompleted()dispatchUtteranceCompletedCallback()の結果が呼び出されていないことでしたが、それはまたmCallbacksMap.get(packageName)返すヌルの結果である可能性があります。

私たちは私にはあまり意味がありません。どちらも2つの可能性、と再び残っているので、:earconのonCompletion()が呼び出された時点で

  1. 、earconのmCurrentSpeechItemはnullです。しかしなぜですか?
  2. mCallbacksMapは空です。それは何ですか、いつそれが人口になるのですか?

このミステリーを解決するための提案や説明がありますか?

+1

同じ問題がありますが、回避策はearconの後ろに空の発話を追加することです。また、新しいAPIバージョン(16)のように見える*これは、イヤコンのためのコールバックを生成します。 –

+1

'TextToSpeech'コンストラクタには、' onInit'ハンドラがTTSエンジンのNULL(約1%のチャンス)にアクセスするという厄介な競合状態もあります。コールバックパラメータには入っていないからです!コンストラクタが実行を終了する前に実際にあなたの 'onInit'を呼び出します。これは非常に深刻です。なぜなら、あなたは 'onInit'で初期化(' setOnUtteranceComplete'、 'addEarcon')を行うことを期待しているからです。 –

+1

エミュレータをチェックインし、再生が終了すると 'playEarcon'はコールバックを送信します。これはAPI15以上です。以前のコメントで述べた回避策を、より低いAPIに使用することができます。 –

答えて

1

android.speech.tts.TextToSpeech#playEarcon()の行807を確認してください。 text-to-speechサービスバインダーに渡されたparams引数はヌルです。つまり、サービスはあなたの発言IDを受け取ることはありません。

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