Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Speech Recognition as a service on Android 4.1 & 4.2

I have managed to get continuous speech recognition working (using the SpeechRecognizer class) as a service on all Android versions up to 4.1. My question concerns getting it working on versions 4.1 and 4.2 as it is known there is a problem in that the API doesn't do as documented in that a few seconds after voice recognition is started, if no voice input has been detected then it's as if the speech recogniser dies silently. (http://code.google.com/p/android/issues/detail?id=37883)

I have found a question which proposes a work-around to this problem (Voice Recognition stops listening after a few seconds), but I am unsure as how to implement the Handler required for this solution. I am aware of the 'beep' that will happen every few seconds that this workaround will cause, but getting continuous voice recognition is more important for me.

If anyone has any other alternative workarounds then I'd like to hear those too.

like image 659
Graham Laming Avatar asked Feb 18 '13 16:02

Graham Laming


People also ask

What is offline speech recognition on Android?

Android. Speech recognition can be activated when typing on your Android device. If this facility is available in the app you are using, a microphone icon will appear on the keypad. Pressing this activates the speech recognition. Android does have offline speech recognition capabilities.

What is Android Speech API?

The Android Speech API provides recognition control, background services, intents, and support for multiple languages. Again, it can look like a simple addition to the user input for your apps, but it's a very powerful feature that makes them stand out.


1 Answers

This is a work around for android version 4.1.1.

public class MyService extends Service {     protected AudioManager mAudioManager;      protected SpeechRecognizer mSpeechRecognizer;     protected Intent mSpeechRecognizerIntent;     protected final Messenger mServerMessenger = new Messenger(new IncomingHandler(this));      protected boolean mIsListening;     protected volatile boolean mIsCountDownOn;     private boolean mIsStreamSolo;      static final int MSG_RECOGNIZER_START_LISTENING = 1;     static final int MSG_RECOGNIZER_CANCEL = 2;      @Override     public void onCreate()     {         super.onCreate();         mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);          mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);         mSpeechRecognizer.setRecognitionListener(new SpeechRecognitionListener());         mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);         mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,                                          RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);         mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,                                          this.getPackageName());     }      protected static class IncomingHandler extends Handler     {         private WeakReference<MyService> mtarget;          IncomingHandler(MyService target)         {             mtarget = new WeakReference<MyService>(target);         }           @Override         public void handleMessage(Message msg)         {             final MyService target = mtarget.get();              switch (msg.what)             {                 case MSG_RECOGNIZER_START_LISTENING:                      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)                     {                         // turn off beep sound                           if (!mIsStreamSolo)                         {                             mAudioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, true);                             mIsStreamSolo = true;                         }                     }                      if (!target.mIsListening)                      {                          target.mSpeechRecognizer.startListening(target.mSpeechRecognizerIntent);                          target.mIsListening = true;                         //Log.d(TAG, "message start listening"); //$NON-NLS-1$                      }                      break;                   case MSG_RECOGNIZER_CANCEL:                     if (mIsStreamSolo)                    {                         mAudioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, false);                         mIsStreamSolo = false;                    }                       target.mSpeechRecognizer.cancel();                       target.mIsListening = false;                       //Log.d(TAG, "message canceled recognizer"); //$NON-NLS-1$                       break;              }        }      }       // 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;             Message message = Message.obtain(null, MSG_RECOGNIZER_CANCEL);             try             {                 mServerMessenger.send(message);                 message = Message.obtain(null, MSG_RECOGNIZER_START_LISTENING);                 mServerMessenger.send(message);             }             catch (RemoteException e)             {              }         }     };      @Override     public void onDestroy()     {         super.onDestroy();          if (mIsCountDownOn)         {             mNoSpeechCountDown.cancel();         }         if (mSpeechRecognizer != null)         {             mSpeechRecognizer.destroy();         }     }      protected class SpeechRecognitionListener implements RecognitionListener     {          @Override         public void onBeginningOfSpeech()         {             // speech input will be processed, so there is no need for count down anymore             if (mIsCountDownOn)             {                 mIsCountDownOn = false;                 mNoSpeechCountDown.cancel();             }                            //Log.d(TAG, "onBeginingOfSpeech"); //$NON-NLS-1$         }          @Override         public void onBufferReceived(byte[] buffer)         {          }          @Override         public void onEndOfSpeech()         {             //Log.d(TAG, "onEndOfSpeech"); //$NON-NLS-1$          }          @Override         public void onError(int error)         {             if (mIsCountDownOn)             {                 mIsCountDownOn = false;                 mNoSpeechCountDown.cancel();             }              mIsListening = false;              Message message = Message.obtain(null, MSG_RECOGNIZER_START_LISTENING);              try              {                     mServerMessenger.send(message);              }              catch (RemoteException e)              {               }             //Log.d(TAG, "error = " + error); //$NON-NLS-1$         }          @Override         public void onEvent(int eventType, Bundle params)         {          }          @Override         public void onPartialResults(Bundle partialResults)         {          }          @Override         public void onReadyForSpeech(Bundle params)         {             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)             {                 mIsCountDownOn = true;                 mNoSpeechCountDown.start();              }             Log.d(TAG, "onReadyForSpeech"); //$NON-NLS-1$         }          @Override         public void onResults(Bundle results)         {             //Log.d(TAG, "onResults"); //$NON-NLS-1$          }          @Override         public void onRmsChanged(float rmsdB)         {          }      } } 

02/16/2013 - Fix beep sound if you use Text To Speech in your app make sure to turn off Solo stream in onResults

like image 115
Hoan Nguyen Avatar answered Sep 21 '22 23:09

Hoan Nguyen