Sekhar Bhetalam
Sekhar Bhetalam

Reputation: 4535

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)

Upvotes: 1

Views: 5489

Answers (5)

kelvin andre
kelvin andre

Reputation: 415

easy way

textToSpeech=new TextToSpeech(this, new TextToSpeech.OnInitListener() {
    @Override
    public void onInit(int status) {
        if (status==TextToSpeech.SUCCESS){
            int result=textToSpeech.setLanguage(Locale.ENGLISH);

            if (result==TextToSpeech.LANG_MISSING_DATA||result==TextToSpeech.LANG_NOT_SUPPORTED){
                Log.i("TextToSpeech","Language Not Supported");
            }

            textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
                @Override
                public void onStart(String utteranceId) {
                    Log.i("TextToSpeech","On Start");
                }

                @Override
                public void onDone(String utteranceId) {
                    Log.i("TextToSpeech","On Done");
                }

                @Override
                public void onError(String utteranceId) {
                    Log.i("TextToSpeech","On Error");
                }
            });

        }else {
            Log.i("TextToSpeech","Initialization Failed");
        }
    }
});

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    textToSpeech.speak(text,TextToSpeech.QUEUE_FLUSH,null,TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED);
}

Upvotes: 2

djdance
djdance

Reputation: 3209

I found "utterance" is for synth files.

For speaking Im using while(!utteranceDone){thread.sleep...} and this code:

                                brTTS = new BroadcastReceiver(){
                                public void onReceive(Context p1, Intent p2) {
                                    //Log.d(TAG,"TTS ACTION_TTS_QUEUE_PROCESSING_COMPLETED, p2.getAction()="+p2.getAction()+", ? "+TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED);
                                    if (p2.getAction().equals(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED) && tts != null) {
                                        utteranceDone=true;
                                    }
                                }
                            };
                            registerReceiver(brTTS, new IntentFilter(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED));

Upvotes: 0

Boris Karloff
Boris Karloff

Reputation: 1328

Try this:

if(tts.myTTS.isSpeaking())

You get a boolean.

Upvotes: 0

Mr.Me
Mr.Me

Reputation: 9286

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

Upvotes: 6

Renjith
Renjith

Reputation: 5803

From API level 15 you have to use setOnUtteranceProgressListener instead of setOnUtteranceCompletedListener

Check the official doc

Upvotes: 1

Related Questions