34

Hace un tiempo, descubrí que playEarcon()never producesonUtteranceCompleted().¿Qué en TtsService podría explicar la falta de onUtteranceCompleted() para playEarcon()?

En el momento acabo interpretado la documentación que dijo "llama cuando un enunciado ha sido sintetizado " como onUtteranceCompleted() no siendo aplicable para earcons porque, una Earcon no es realmente un resultado de TTS sintetización.

Pero mirando de nuevo el código fuente de Android, simplemente no puedo encontrar una explicación que justifique mi interpretación.

Algunos datos sobre my test jig:

  1. onUtteranceCompleted() siempre llega para la identificación del enunciado anterior a la Earcon. Esa emisión es una expresión TTS ordinaria, no un earcon.
  2. El auricular después de eso funciona (es decir, exactamente como se esperaba).
  3. onUtteranceCompleted() para ese auricular nunca aparece. Este es un comportamiento muy consistente y reproducible.

profundizando en el código fuente TtsService, parece que hay sólo 2 métodos que podrían afectar a la llegada (o ausencia) de onUtteranceCompleted():

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

Si examina ese código, verá que se descarta un tercer candidato, TtsService.getSoundResource() (como responsable de la falta de onUtteranceComplete para mi correo electrónico). arcon) debido al hecho # 2 anterior: el earcon siempre se reproduce, por lo tanto, getSoundResource() no puede devolver nulo.

Usando la misma lógica, la primera candidata, TtsService.processSpeechQueue(), también se puede descartar, por el mismo hecho # 2: El Earcon siempre juega, por lo tanto, los siguientes 2 declaraciones críticas se ejecutan siempre:

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

por lo tanto, nos queda sólo el segundo candidato, TtsService.onCompletion(), como una posible explicación de por qué 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(); 
} 

En allí, sólo hay 2 condiciones que dejaría de p laborar dispatchUtteranceCompletedCallback():

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

Pero sé con seguridad que la condición # 2 se puede descartar porque me conecto todos utteranceIds y la Earcon's definitivamente están ahí.

Además, el examen de todo el registro del sistema:

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

La falta onUtteranceCompleted() podría ser el resultado de dispatchUtteranceCompletedCallback() no ser llamado, pero también podría ser el resultado de mCallbacksMap.get(packageName) devolver nulo.

Por lo tanto, no nos queda otra vez con 2 posibilidades, las cuales no tienen mucho sentido para mí:

  1. Por el momento se llama de onCompletion() un Earcon, de Earcon mCurrentSpeechItem es nulo. Pero ¿por qué?
  2. mCallbacksMap está vacío. ¿Qué es y cuándo se llena?

¿Alguna sugerencia u otra explicación para resolver este misterio?

+1

Tenemos el mismo problema, la solución es agregar un enunciado vacío después del earcon. También parece que las versiones de API más recientes (16) * do * producen la devolución de llamada para earcons, investigando esto. –

+1

También hay una desagradable condición de carrera en el contstructor 'TextToSpeech' que hace que tu manejador' onInit' acceda a NULL (aproximadamente 1% de probabilidad) para el motor TTS, ¡ya que no viene en los parámetros de devolución de llamada! En realidad, llama a su 'onInit' antes de que el constructor termine de ejecutarse. Esto es muy serio, porque esperan que hagas la inicialización ('setOnUtteranceComplete',' addEarcon') en 'onInit'. –

+1

Emuladores registrados y 'playEarcon' ahora envía una devolución de llamada cuando termina de reproducirse. Esto está en API 15 y superior. Puede usar la solución alternativa que mencioné en comentarios anteriores para API inferiores. –

Respuesta

1

Compruebe android.speech.tts.TextToSpeech#playEarcon() en la línea 807. El argumento params pasado al cuaderno de mensajes de texto a voz es nulo, lo que significa que el servicio nunca recibe su ID de emisión.

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