Android Speech Reconocimiento de voz: Llamada repetida de SpeechRecognizer.startListening () falla en JB 4.1.2

Tengo un servicio en el que estoy pateando un oyente de reconocimiento de voz en repetidas ocasiones para que pueda tener una sesión abierta para que el usuario pueda hablar. La clase también maneja el problema en Jelly Bean donde se lanza ERROR_SPEECH_TIMEOUT si no se escucha ningún mensaje en 5 segundos. Así que básicamente esto funciona. Sin embargo, si repetidamente llamo recognizer.startListening (recognizerIntent), falla silenciosamente como lo demuestra el hecho de que onBeginningOfSpeech () nunca se llama en este caso. Ahora, si yo simplemente no hablo en absoluto mi controlador de tiempo de espera de Jelly Bean reiniciará el oyente cada vez sin falta. Parece que sólo falla después onResults () se llama porque el discurso fue escuchado. Después de llamarse onResults (), recognizer.startListening (recognizerIntent) es definitivamente llamado, pero como he dicho, no pasa nada. Cuando falla es aleatorio y no hay nada en Logcat para indicar cuál es el problema. Simplemente no sé qué más intentar. Esperemos que uno de los expertos Android de reconocimiento de voz por ahí ha visto esto antes …

Mínimo: 2.2 Objetivo: Pruebas en JB: Android 4.1.2


MÁS INFORMACIÓN (11-01-13) La actualización 4.3 de mi HTC One ha abordado definitivamente este problema. Mi servicio de reconocimiento de voz a continuación es ahora fiable y preciso. He funcionado por lo menos algunos minutos sin error. En cuanto a 4.1.2, antes de mi actualización a 4,3 que parecía haber funcionado mejor (hizo Google cambiar nada en su final?) … No sé, pero todavía se pierda algunas palabras habladas y de vez en cuando sin error, Sólo dejar de escuchar (onBeginningOfSpeech () nunca se llama en este caso). Supongo que sólo tengo que advertir a mis usuarios sobre Android 4.1.2 con respecto a este problema, porque he ido tan lejos como puedo ir en mi código.

MÁS INFORMACIÓN (09-17-13) Supuestamente, hay una actualización de Android (4.3) llegando a HTC a finales de septiembre ( http://www.ubergizmo.com/2013/09/htc-one-to-receive -android-4-3-jelly-bean-update-este-septiembre / ). Así que esperemos que se abordará este problema en ese dispositivo. El problema sigue siendo para los usuarios de mi aplicación que están ejecutando Android 4.1.2 y se quedó en esa versión por un tiempo. Todavía no sé qué hacer en esos casos, y espero que sea la ÚNICA versión de Android con este problema. ¿Hay alguna manera de averiguar cuántos dispositivos están ejecutando 4.1.2 ??

MÁS INFORMACIÓN (09-15-13) En este post aquí: Google reconocimiento de voz no se inicia en Android 4.x. Los estados del estado del autor que él está viendo esta edición en su HTC uno. También tengo un HTC que estoy viendo este problema en (Android 4.1.2). Me pregunto si esto es único para el HTC uno? (O cualquier dispositivo que ejecute Android 4.1.2) – No puedo confirmar como su difícil de probar en todos los últimos dispositivos que ejecutan JB. El autor afirma además que su Nexxus con 4.2.2 funciona bien. ¿Puede alguien decirme en qué dispositivo ven este problema?

MÁS INFORMACIÓN (9-08-13) Sólo para confirmar que no hay ningún problema con mi código, también probé esto en Android 2.3.3 y pude llamar a onResult ()> startListening () 25 veces seguidas. Al orientar Android 4.1.2 nunca logro superar las 3 o 4 llamadas. No puedo creer que nadie más se ha topado con este problema?

public class VoiceRecogService extends Service { protected AudioManager mAudioManager; protected SpeechRecognizer mSpeechRecognizer; protected Intent mSpeechRecognizerIntent; protected RecognitionListener mSpeechRecognizerListner; //protected final Messenger mServerMessenger = new Messenger(new IncomingHandler(this)); protected volatile boolean mIsListening; protected volatile boolean mIsCountDownOn; static final int MSG_RECOGNIZER_START_LISTENING = 1; static final int MSG_RECOGNIZER_CANCEL = 2; private int mBindFlag; private Messenger mServiceMessenger; private Context m_ctx; private Handler mHandler = new Handler(); //private boolean m_bReadyForSpeechReceived = false; @Override public void onCreate() { super.onCreate(); m_ctx = this; mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); //do not mute beep when speech listening first kicks off Log.d("TESTING: SPEECH SERVICE: CALL START", "onCreate()"); startListening(false); } private void startListening(boolean bMuteSound){ Log.d("TESTING: SPEECH SERVICE: startListening()", mIsListening? "true":"false"); if (bMuteSound==true && Build.VERSION.SDK_INT >= 16)//Build.VERSION_CODES.JELLY_BEAN) { // turn off beep sound mAudioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true); } if (!mIsListening) { //mSpeechRecognizer.startListening(mSpeechRecognizerIntent); recognizeSpeechDirectly (); mIsListening = true; } } ///////////////////////////////////////////////////////////////////////// /** * lazy initialize the speech recognizer */ private SpeechRecognizer getSpeechRecognizer() { if (mSpeechRecognizer == null) { mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(m_ctx); } return mSpeechRecognizer; } private RecognitionListener getSpeechRecognizerListner() { if (mSpeechRecognizerListner == null) { mSpeechRecognizerListner = new SpeechRecognitionListener(); } return mSpeechRecognizerListner; } private void recognizeSpeechDirectly() { Intent recognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); // accept partial results if they come recognizerIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true); recognizeSpeechDirectly(m_ctx,recognizerIntent, getSpeechRecognizerListner(), getSpeechRecognizer()); } public static void recognizeSpeechDirectly(Context context, Intent recognizerIntent, RecognitionListener listener, SpeechRecognizer recognizer) { //need to have a calling package for it to work if (!recognizerIntent.hasExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE)) { recognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, "com.dummy"); } recognizer.setRecognitionListener(listener); recognizer.startListening(recognizerIntent); } //////////////////////////////////////////////////////////////////////////// public void stop() { if (getSpeechRecognizer() != null) { getSpeechRecognizer().stopListening(); getSpeechRecognizer().cancel(); getSpeechRecognizer().destroy(); mIsListening = false; if (Build.VERSION.SDK_INT >= 16);//Build.VERSION_CODES.JELLY_BEAN) mAudioManager.setStreamMute(AudioManager.STREAM_SYSTEM, false); } } // Count down timer for Jelly Bean work around protected CountDownTimer mNoSpeechCountDown = new CountDownTimer(5000, 5000) { @Override public void onTick(long millisUntilFinished) { // TODO Auto-generated method stub } @Override public void onFinish() { mIsCountDownOn = false; Log.d("TESTING: SPEECH SERVICE: CALL START", "onFinish()"); startListening(true); } }; @Override public void onDestroy() { super.onDestroy(); if (mIsCountDownOn) { mNoSpeechCountDown.cancel(); } if (mSpeechRecognizer != null) { mSpeechRecognizer.destroy(); } } protected class SpeechRecognitionListener implements RecognitionListener { @Override public void onReadyForSpeech(Bundle params) { if (Build.VERSION.SDK_INT >= 16)//Build.VERSION_CODES.JELLY_BEAN) { mIsCountDownOn = true; mNoSpeechCountDown.start(); } Log.d("TESTING: SPEECH SERVICE", "onReadyForSpeech"); } @Override public void onBeginningOfSpeech() { // speech input will be processed, so there is no need for count down anymore if (mIsCountDownOn) { mIsCountDownOn = false; mNoSpeechCountDown.cancel(); } } @Override public void onEndOfSpeech() { Log.d("TESTING: SPEECH SERVICE", "onEndOfSpeech"); } @Override public void onBufferReceived(byte[] buffer) { //Log.d("TESTING: SPEECH SERVICE", buffer + new String(new byte[] {0x63})); } @Override public void onError(int error) { if ((error == SpeechRecognizer.ERROR_NO_MATCH) || (error == SpeechRecognizer.ERROR_SPEECH_TIMEOUT)){ if (mIsCountDownOn) { mIsCountDownOn = false; mNoSpeechCountDown.cancel(); } mIsListening = false; Log.d("TESTING: SPEECH SERVICE: CALL START", "onError()"); startListening(true); } } @Override public void onEvent(int eventType, Bundle params) { } @Override public void onPartialResults(Bundle partialResults) { } @Override public void onResults(Bundle results) { //String str = new String(); //Log.d(TAG, "onResults " + results); ArrayList data = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); //if(data.size() >=1){ // //check for save it: //} for (int i = 0; i < data.size(); i++) { Log.d("TESTING: SPEECH SERVICE", (String)data.get(i)); } //if no "save it" somewhere in there, then continue: if (mIsCountDownOn) { mIsCountDownOn = false; } mIsListening = false; Log.d("TESTING: SPEECH SERVICE: CALL START", "onResults()"); startListening(true); } @Override public void onRmsChanged(float rmsdB) { } } @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } } 

Estoy en Android 4.4 KitKat en un Nexus 5 y tiene este mismo problema. Creo que es probable que un error de Android, porque no he visto a nadie con una solución limpia.
Esta solución es similar a Andrew_CS solución, pero creo que es en realidad permite un mejor reconocimiento. La solución de Andrews está comenzando y deteniendo constantemente el reconocedor y usted tiene que no perder de vista el estado de cosas como si usted está procesando discurso o no. Esta nueva solución / work-around básicamente hace esto:

  • Una vez que onResults es llamado y nuestros resultados son procesados, comenzamos un temporizador.
  • Si las cosas están funcionando correctamente, onReadyForSpeech será llamado y podemos cancelar nuestro temporizador.
  • Si las cosas no funcionan correctamente, el temporizador finaliza y reiniciamos el reconocedor de voz e iniciamos de nuevo el temporizador.
  • Asegúrese de cancelar el temporizador en su método OnDestroy también.

Por favor, hágamelo saber si encuentra una forma aún mejor, pero esto parece funcionar muy bien por ahora. Si realmente podemos demostrar que es un error de Android, me encantaría que alguien lo envíe a Google.

  @Override public void onReadyForSpeech(Bundle params) { Log.d("Speech", "onReadyForSpeech: Cancel Timer"); if(mTimer != null) { mTimer.cancel(); } } @Override public void onResults(Bundle results) { //If the timer is available, cancel it so it doesn't interrupt our result processing if(mTimer != null){ mTimer.cancel(); } Log.d("Speech", "onResults"); //Start processing data ArrayList<String> strlist = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); for (int i = 0; i < strlist.size();i++ ) { Log.d("Speech", "YOU SAID: " + strlist.get(i)); } //Start listening again Log.d("Speech", "onResults: Start Listening"); mSpeechRecognizer.startListening(mRecognizerIntent); //Start a timer in case OnReadyForSpeech is never called back (Android Bug?) Log.d("Speech", "onResults: Start a timer"); if(mTimer == null) { mTimer = new CountDownTimer(2000, 500) { @Override public void onTick(long l) { } @Override public void onFinish() { Log.d("Speech", "Timer.onFinish: Timer Finished, Restart recognizer"); mSpeechRecognizer.cancel(); mSpeechRecognizer.startListening(mRecognizerIntent); } }; } mTimer.start(); } 

Puedes usar:

 intent.putExtra("android.speech.extra.DICTATION_MODE", true); 

Este código hace que el servicio escuche mucho tiempo.

Para evitar este problema he utilizado un CountDownTimer para llamar incrementalmente cancelar y startListening.

 _timer = new CountDownTimer(300000000, 1000){ @Override public void onTick(long millisUntilFinished){ if(!_processingSpeech){ _mSpeechRecognizer.cancel(); _mSpeechRecognizer.startListening(_mSpeechRecognizerIntent); } } @Override public void onFinish(){ setUpTimer(); } }; _processingSpeech = false; _timer.start(); 

Utilicé el método de procesamiento booleano en los métodos RecognitionListener para asegurarse de que no cancelé y reinicie mientras estaba recibiendo / procesando la entrada.

Déjame saber si esto te ayuda o si necesitas más información. ¡Buena suerte!

Trate de usar la instancia única de SpeechRecognizer , no es necesario volver a crearlo en el método stop () . Llame a getSpeechRecognizer () en onCreate () y olvídelo. Pero no se olvide de destruir en el método onDestroy ().

  • En la aplicación de facturación V3 Service nullpointer Android
  • ActivityManager # getRunningServices devuelve el servicio que se detiene manualmente
  • ¿Cómo puedo activar automáticamente el inicio automático de mis aplicaciones en el menú de seguridad Xiaomi Mi4i?
  • Transmisión recibida dos veces
  • Proporcionar un servicio de fondo para otras aplicaciones
  • Cliente de servicio WSDL / SOAP de Android
  • ¿Cómo enlazar un servicio?
  • ¿Por qué un servicio Android no es singleton cuando se prueba?
  • REST / JSON / XML-RPC / SOAP
  • Servicios de Android: Bind on demand vs. Bind on #onCreate ()
  • Android: ¿puedo usar Google Analytics dentro de un servicio?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.