1

I have been refering to Android Speech Recognition as a service on Android 4.1 & 4.2 post to try and implement speech recognition in a service.

I guess I have got it right. On running in my device I am getting "Ready for Speech" toast message which I have declared inside onReadyForSpeech() function.

According to Hoan Nguyen the person who gave the ans for the above post, we can start speaking as soon as onReadyForSpeech() function is called.

My problem is I don't know how to get the speech which we are speaking and convert it to text and where to do it.

Does any one know how to do it? I know its a very lame question to ask but its my first time working with speech recognition. So please bear with me.

Any help on this is very much appreciated. Thanks in advance :)

    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;

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

       mSpeechRecognizer.startListening(mSpeechRecognizerIntent);
        //Toast.makeText(this, "onCreate", Toast.LENGTH_SHORT).show();
        Log.d("onCreate","Entered");
    }


    protected static class IncomingHandler extends Handler
    {
        private WeakReference<MyService> mtarget;

        IncomingHandler(MyService target)
        {
            mtarget = new WeakReference<MyService>(target);

            Log.d("IncomingHandler","Entered");
        }


        @Override
        public void handleMessage(Message msg)
        {
            Log.d("handleMessage","Entered");

            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  
                        target.mAudioManager.setStreamMute(AudioManager.STREAM_SYSTEM, 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:
                      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
            Log.d("onTick","Entered");
        }

        @Override
        public void onFinish()
        {
            Log.d("onFinish","Entered");

            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 int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        //mSpeechRecognizer.startListening(mSpeechRecognizerIntent);

        try
        {
            Message msg = new Message();
            msg.what = MSG_RECOGNIZER_START_LISTENING; 
            mServerMessenger.send(msg);
        }
        catch (RemoteException e)
        {
            Log.d("msg",""+e);
        }
        return  START_NOT_STICKY;
        //return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();

        if (mIsCountDownOn)
        {
            mNoSpeechCountDown.cancel();
        }
        if (mSpeechRecognizer != null)
        {
            mSpeechRecognizer.destroy();
        }

        Log.d("onDestroy","Entered");
    }

    protected class SpeechRecognitionListener implements RecognitionListener
    {

        private static final String TAG = "Sppech---->";

        @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$
            Log.d("onBeginningOfSpeech","Entered");
        }

        @Override
        public void onBufferReceived(byte[] buffer)
        {
            String sTest = "";
            Log.d("onBufferReceived","Entered");
        }

        @Override
        public void onEndOfSpeech()
        {
            //Log.d(TAG, "onEndOfSpeech"); //$NON-NLS-1$
            Log.d("onEndOfSpeech","Entered");
         }

        @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$
             Log.d("onError","Entered");
        }

        @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();
                mAudioManager.setStreamMute(AudioManager.STREAM_SYSTEM, false);
            }
            //Log.d("TAG", "onReadyForSpeech"); 
            Toast.makeText(getApplicationContext(), "Ready for Speech", Toast.LENGTH_SHORT).show();
            Log.d("onReadyForSpeech","Entered");//$NON-NLS-1$
        }

        @Override
        public void onResults(Bundle results)
        {
            //Log.d(TAG, "onResults"); //$NON-NLS-1$

        }

        @Override
        public void onRmsChanged(float rmsdB)
        {

        }



    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
}
Community
  • 1
  • 1
ik024
  • 3,566
  • 7
  • 38
  • 61

1 Answers1

1

You get it in onResult(Bundle result), which you can then get what the user speak into an ArrayList

ArrayList<String> matches = result.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
Hoan Nguyen
  • 18,033
  • 3
  • 50
  • 54
  • Its working and thanks a lot. I just knew that u would be the one who will ans this question. Though u can't see it there is a big smile on my face right now :P – ik024 Feb 11 '14 at 07:34
  • Right now I have just copied ur code with out understanding most of the stuff I would really like to understand every thing that u have done. Can pls help me out here by providing some links so that I can understand it. – ik024 Feb 11 '14 at 07:36
  • Just read RecognitionListener, RecognizerIntent and SpeechRecognizer at http://developer.android.com/reference/android/speech/package-summary.html – Hoan Nguyen Feb 11 '14 at 07:52
  • Okay now there is one more problem which has already been asked by others. I am testing it in android 4.4.2 and onReadyForSpeech() function is called max 3 times. How do I solve this and y does it stops after 3 attempts ? (3 attemps - only if I say something if not it keeps calling onReadyForSpeech()) – ik024 Feb 11 '14 at 08:00
  • ok that was simple I was initially returning START_NOT_STICKY in my onStartCommand(). I changed it to START_STICKY and its working fine :) – ik024 Feb 11 '14 at 08:21
  • I guess it was a partial solution – ik024 Feb 11 '14 at 08:54
  • I will get a 4.4 phone in the near future and then maybe I can answer your comment. – Hoan Nguyen Feb 11 '14 at 22:09
  • thanks for that :) I will try and resolve it b4 dat. If I do I will update it here with the soln :) – ik024 Feb 12 '14 at 04:35
  • hey i knoe its been quite some time since i have asked this question, but i have a dout and i think u r the right person to ask. Can i run the speech recognition in background even when my app is not running like a broad cast receiver? so that wen a particular word is said my app starts running. – ik024 Feb 17 '14 at 05:10
  • Yes, just make sure you acquire a wakelock in your service. You can start your service when the device boot. – Hoan Nguyen Feb 17 '14 at 06:00
  • okay how to handle this situation - the user is using my app at that time the service is running fine in the background. But wen the user exits my app even the service dies. How to keep my service awake even wen user exits my app? thanks for ur reply though :) – ik024 Feb 17 '14 at 06:50
  • i think wakelocks are basically used wen the device goes into sleep mode - right? like partial wakelock to keep the CPU running in sleep mode – ik024 Feb 17 '14 at 06:58
  • Did you stop your service when the user exits your app? You should start the service in the foreground. Then your service would not be killed so often. Make sure in your code that when your service is restarted after getting killed by the OS, you send a listening message in the appropriate place (onStart I think). Yes partial wakelock is to keep CPU running. You should acquire in onCreate and release in onDestroy. – Hoan Nguyen Feb 17 '14 at 07:10
  • Regarding the android 4.4.2 thing - As I say some word the service would recognize it give a list of possible matches and would stop bt i wnted my service to run continuously. In my case - wen a particular word is said a new activity wud be created, so in my new activity's onResume() I wud stop n start the service again. In dis way i had my service running all the tym – ik024 Feb 18 '14 at 04:47
  • Instead of stop and start you should bindServive and unbindService – Hoan Nguyen Feb 18 '14 at 05:10
  • wats the difference between those two using stop and start v/s using bindService and unbindservice ? – ik024 Feb 19 '14 at 12:08
  • You startService in onCreate and then bindService in onStart and unbindService in onStop, then when your app is closed the service is still running. – Hoan Nguyen Feb 19 '14 at 20:40
  • Just a quick question - In ur implementation y did u use WeakReference is it just ur practise or is it its required ? – ik024 Feb 24 '14 at 06:48
  • That is for garbage collection, just look up WeakReference. – Hoan Nguyen Feb 24 '14 at 19:05
  • Yeah I was reading about it, I dint knew abt this earlier, its a good concept... I just wanted to knw if its ur practise or is it required in this particular implementation. As in if we use strong reference will it still work ?(i think the objects which we define normally are strong referenced, right?) – ik024 Feb 25 '14 at 04:08
  • And also can we use weak reference to all our obj initializations? for eg for creating a textview obj etc etc? – ik024 Feb 25 '14 at 04:21
  • I knw i hv been asking a lot of questions but this will be last, hopefully :P Can u ans to this question of mine. http://stackoverflow.com/questions/22037438/how-does-android-speech-api-works-before-connecting-to-google-server I will be very greatful to u :) Thanks in advance :) – ik024 Feb 26 '14 at 09:56