Search code examples
androidtext-to-speech

How to know when TextToSpeech is finished with speaking?


I am working Text to Speech for Android application. I am getting confusion on finding a method that to be called when Text to Speech was completed. I tried to call the following methods but the finished was doesn't called, Please have a look into the following code and suggest me.

 tts= new TextToSpeech(MainActivity.this, new OnInitListener() {

         @Override
         public void onInit(int status) {

             tts.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {

                @Override
                public void onUtteranceCompleted(final String utteranceId) {
                            System.out.println("Completed");

                    runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                        //UI changes
                        }
                    });
                }
            });

         }
        });

Please suggest me. I am using API Level 17.


Edit:

Minimum API level is 12;

And I got the following error in console:

01-30 09:19:14.149: E/ActivityThread(660): Service com.android.exchange.ExchangeService

    has leaked ServiceConnection com.android.emailcommon.service.ServiceProxy$ProxyConnection@40ce0ef0 that was originally bound here
01-30 09:19:14.149: E/ActivityThread(660): android.app.ServiceConnectionLeaked: Service com.android.exchange.ExchangeService has leaked ServiceConnection com.android.emailcommon.service.ServiceProxy$ProxyConnection@40ce0ef0 that was originally bound here
01-30 09:19:14.149: E/ActivityThread(660):  at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:969)
01-30 09:19:14.149: E/ActivityThread(660):  at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:863)
01-30 09:19:14.149: E/ActivityThread(660):  at android.app.ContextImpl.bindService(ContextImpl.java:1418)
01-30 09:19:14.149: E/ActivityThread(660):  at android.app.ContextImpl.bindService(ContextImpl.java:1407)
01-30 09:19:14.149: E/ActivityThread(660):  at android.content.ContextWrapper.bindService(ContextWrapper.java:473)
01-30 09:19:14.149: E/ActivityThread(660):  at com.android.emailcommon.service.ServiceProxy.setTask(ServiceProxy.java:157)
01-30 09:19:14.149: E/ActivityThread(660):  at com.android.emailcommon.service.ServiceProxy.setTask(ServiceProxy.java:145)
01-30 09:19:14.149: E/ActivityThread(660):  at com.android.emailcommon.service.AccountServiceProxy.getDeviceId(AccountServiceProxy.java:116)
01-30 09:19:14.149: E/ActivityThread(660):  at com.android.exchange.ExchangeService.getDeviceId(ExchangeService.java:1249)
01-30 09:19:14.149: E/ActivityThread(660):  at com.android.exchange.ExchangeService$7.run(ExchangeService.java:1856)
01-30 09:19:14.149: E/ActivityThread(660):  at com.android.emailcommon.utility.Utility$2.doInBackground(Utility.java:551)
01-30 09:19:14.149: E/ActivityThread(660):  at com.android.emailcommon.utility.Utility$2.doInBackground(Utility.java:549)
01-30 09:19:14.149: E/ActivityThread(660):  at android.os.AsyncTask$2.call(AsyncTask.java:287)
01-30 09:19:14.149: E/ActivityThread(660):  at java.util.concurrent.FutureTask.run(FutureTask.java:234)
01-30 09:19:14.149: E/ActivityThread(660):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
01-30 09:19:14.149: E/ActivityThread(660):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
01-30 09:19:14.149: E/ActivityThread(660):  at java.lang.Thread.run(Thread.java:856)
01-30 09:19:14.169: E/StrictMode(660): null
01-30 09:19:14.169: E/StrictMode(660): android.app.ServiceConnectionLeaked: Service com.android.exchange.ExchangeService has leaked ServiceConnection com.android.emailcommon.service.ServiceProxy$ProxyConnection@40ce0ef0 that was originally bound here
01-30 09:19:14.169: E/StrictMode(660):  at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:969)
01-30 09:19:14.169: E/StrictMode(660):  at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:863)
01-30 09:19:14.169: E/StrictMode(660):  at android.app.ContextImpl.bindService(ContextImpl.java:1418)
01-30 09:19:14.169: E/StrictMode(660):  at android.app.ContextImpl.bindService(ContextImpl.java:1407)
01-30 09:19:14.169: E/StrictMode(660):  at android.content.ContextWrapper.bindService(ContextWrapper.java:473)
01-30 09:19:14.169: E/StrictMode(660):  at com.android.emailcommon.service.ServiceProxy.setTask(ServiceProxy.java:157)
01-30 09:19:14.169: E/StrictMode(660):  at com.android.emailcommon.service.ServiceProxy.setTask(ServiceProxy.java:145)
01-30 09:19:14.169: E/StrictMode(660):  at com.android.emailcommon.service.AccountServiceProxy.getDeviceId(AccountServiceProxy.java:116)
01-30 09:19:14.169: E/StrictMode(660):  at com.android.exchange.ExchangeService.getDeviceId(ExchangeService.java:1249)
01-30 09:19:14.169: E/StrictMode(660):  at com.android.exchange.ExchangeService$7.run(ExchangeService.java:1856)
01-30 09:19:14.169: E/StrictMode(660):  at com.android.emailcommon.utility.Utility$2.doInBackground(Utility.java:551)
01-30 09:19:14.169: E/StrictMode(660):  at com.android.emailcommon.utility.Utility$2.doInBackground(Utility.java:549)
01-30 09:19:14.169: E/StrictMode(660):  at android.os.AsyncTask$2.call(AsyncTask.java:287)
01-30 09:19:14.169: E/StrictMode(660):  at java.util.concurrent.FutureTask.run(FutureTask.java:234)
01-30 09:19:14.169: E/StrictMode(660):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
01-30 09:19:14.169: E/StrictMode(660):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
01-30 09:19:14.169: E/StrictMode(660):  at java.lang.Thread.run(Thread.java:856)

Solution

  • The problem is not in onUtteranceComplete function , its most likely get called, but you're trying to print the output to System.out , please use android.utils.Log("tag", "success") instead and see what happens.

    Also You need to set UtteranceID to get onUtteranceComplete to work before calling tts.speak method. so to sum up:

                TextToSpeech tts= new TextToSpeech(MainActivity.this, new OnInitListener() {
    
             @Override
             public void onInit(int status) {
    
                 tts.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {
    
                    @Override
                    public void onUtteranceCompleted(final String utteranceId) {
                                System.out.println("Completed");
    
                        runOnUiThread(new Runnable() {
    
                            @Override
                            public void run() {
                            //UI changes
                            }
                        });
                    }
                });
    
             }
        });
        Map<String,String> ttsParams = new HashMap<String, String>();
        ttsParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
                MainActivity.this.getPackageName());
    
        mTts.speak(text, TextToSpeech.QUEUE_FLUSH, ttsParams);
    

    And the exception you're getting has nothing to do with the onUtteranceComplete method, if it is because of tts engine most likely you're not requesting to destroy your instance when finishing your activity.

    To fix that add

    @Override
    onDestroy(){
    super.onDestroy();
    mTts.shutdown(); //mTts is your TextToSpeech Object
    }
    

    To your activity class