34

Qualche tempo fa, ho scoperto che playEarcon()never producesonUtteranceCompleted().Che cosa in TtsService potrebbe spiegare la mancanza di onUtteranceCompleted() per playEarcon()?

Al momento ho solo interpretato la documentazione che ha detto "chiamato quando un enunciato è stato sintetizzato ", come onUtteranceCompleted() non essendo applicabile per earcons perché, un earcon non è in realtà il risultato di TTS synthesization.

Ma guardando ancora il codice sorgente di Android, semplicemente non riesco a trovare una spiegazione che possa giustificare la mia interpretazione.

alcuni fatti circa my test jig:

  1. onUtteranceCompleted() arriva sempre per ID espressione che precede l'earcon. Quella espressione è una frase ordinaria del TTS, non un auricolare.
  2. L'auricolare dopo quello fa l'esecuzione (vale a dire esattamente come previsto).
  3. onUtteranceCompleted() per quell'accettore mai si presenta. Questo è un comportamento molto coerente e riproducibile.

scavare in profondità nel codice sorgente TtsService, sembra che ci siano solo 2 metodi che potrebbero influenzare l'arrivo (o l'assenza) di onUtteranceCompleted():

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

Se si esamina quel codice, si vedrà che un terzo candidato, TtsService.getSoundResource() è escluso (come responsabile della mancanza di onUtteranceComplete per la mia e arcon) a causa del fatto n. 2 sopra: L'auricolare funziona sempre, quindi getSoundResource() non può restituire null.

Usando la stessa logica, il primo candidato, TtsService.processSpeechQueue(), può anche essere esclusa, per lo stesso fatto # 2: L'earcon gioca sempre, quindi, i seguenti 2 dichiarazioni critiche sono sempre eseguiti:

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

così, ci ritroviamo con solo il 2 ° candidato, TtsService.onCompletion(), come una possibile spiegazione del perché un playEarcon()never producesonUtteranceCompleted():

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

lì, ci sono solo 2 condizioni che non riuscirebbe a p roduce dispatchUtteranceCompletedCallback():

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

Ma so per certo che la condizione # 2 può essere esclusa perché io accedo tutti utteranceIds e la l'auricolare è sicuramente lì.

Inoltre, esaminando l'intero log di sistema:

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

Il mancante onUtteranceCompleted() potrebbe essere il risultato di dispatchUtteranceCompletedCallback() non essere chiamato, ma potrebbe anche essere il risultato di mCallbacksMap.get(packageName) ritorno nullo.

Così, ci ritroviamo ancora una volta con 2 posti, entrambi i quali non fanno per me molto senso:

  1. Con il tempo di un onCompletion() earcon si chiama, di earcon mCurrentSpeechItem è nullo. Ma perché ?
  2. mCallbacksMap è vuoto. Che cos'è e quando viene popolato?

Eventuali suggerimenti o altre spiegazioni per risolvere questo mistero?

+1

Abbiamo lo stesso problema, la soluzione alternativa è aggiungere un enunciato vuoto dopo l'auricolare. Sembra anche una versione più recente dell'API (16) * do * produce il callback per i earcon, esaminando questo. –

+1

C'è anche una brutta condizione di competizione nel contstructor di 'TextToSpeech' che fa sì che il gestore' onInit' acceda a NULL (circa l'1% di possibilità) per il motore TTS, dal momento che non è incluso nei parametri di callback! In realtà chiama il tuo 'onInit' prima che il costruttore termini l'esecuzione. Questo è molto serio, perché si aspetta che tu faccia l'inizializzazione ('setOnUtteranceComplete',' addEarcon') in 'onInit'. –

+1

Controllato in emulatori e 'playEarcon' ora invia una richiamata quando viene eseguita la riproduzione. Questo è su API 15 e versioni successive. Puoi utilizzare la soluzione alternativa menzionata nel commento precedente per le API inferiori. –

risposta

1

Verificare android.speech.tts.TextToSpeech#playEarcon() alla riga 807. L'argomento params passato al raccoglitore di servizi di sintesi vocale è nullo, il che significa che il servizio non riceve mai l'identificatore di utenza.

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