Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android TTS onUtteranceCompleted callback isn't getting called

I am trying to get the Android TTS API to read my "utterance" and then call the onUtteranceCompleted() listener unsuccessfully. I've registered my TTS object and it returns SUCCESS, so I can't figure out for the life of me why my callback isn't getting called.

I've tried searching for help, but it seems others have difficulty with this too. Am I missing something simple?

Thanks for any help you can offer.

package com.test.mytts;

import java.util.HashMap;

import android.app.Activity;
import android.media.AudioManager;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
import android.widget.TextView;
import android.widget.Toast;

public class MyTTS extends Activity implements OnInitListener, OnUtteranceCompletedListener
{   
    TextView tv;
    private TextToSpeech _tts;

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        tv = new TextView(this);

        tv.setText("MyTTS: ");

        super.onCreate(savedInstanceState);
        setContentView(tv);

        _tts = new TextToSpeech(this, this);
    }

    @Override
    public void onInit(int status) 
    {
        HashMap<String, String> myHashAlarm = new HashMap<String, String>();

        myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_NOTIFICATION));
        myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "test");

        if (status == TextToSpeech.SUCCESS)
        {
            Toast.makeText(this, "Trying to speak...", Toast.LENGTH_SHORT).show();

            int result = _tts.setOnUtteranceCompletedListener(this);

            tv.append(String.valueOf(result));

            _tts.setSpeechRate((float) .5);

            _tts.speak("Testing one, two, three", TextToSpeech.QUEUE_ADD, myHashAlarm);
        }
        else
            Toast.makeText(this, "Failed to initialize TTS.", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onUtteranceCompleted(String utteranceId) 
    {
        Toast.makeText(this, "onUtteranceCompleted", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();
        _tts.shutdown();
    }
}
like image 943
Justin Shidell Avatar asked Jan 11 '11 00:01

Justin Shidell


3 Answers

Call the setOnUtteranceCompletedListener inside the onInit function of the tts object.

If you want to make any changes to the UI on the call of the onUtteranceCompleted function, add the code inside a runOnUIThread method.

And do remember to add the Hashmap param value while calling the speak() function

Example :

TextToSpeech tts= new TextToSpeech(context, new OnInitListener() {

 @Override
 public void onInit(int status) {

    mTts.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {

        @Override
        public void onUtteranceCompleted(String utteranceId) {

            runOnUiThread(new Runnable() {

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

 }
});


HashMap<String, String> params = new HashMap<String, String>();

params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"stringId");

tts.speak("Text to Speak",TextToSpeech.QUEUE_FLUSH, params);
like image 104
sm abbas Avatar answered Oct 14 '22 01:10

sm abbas


I believe that unless you specify an utterance with an id, like:

map.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utteranceid);

your utterance completed method will not be called.

in this case, map is the Hashmap you pass to the engine when you speak.

like image 20
ekawas Avatar answered Oct 14 '22 00:10

ekawas


this will work for you on API Level >=15

import java.util.HashMap;
import java.util.Locale;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.speech.tts.UtteranceProgressListener;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity implements OnInitListener{

    private static final int CHECK_TTS_DATA = 0X123;
    protected static final String TAG = MainActivity.class.getSimpleName();
    private TextToSpeech textToSpeech;
    private Button buttonSayIt;
    private EditText editTextTts;
    String tts;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        buttonSayIt=(Button) findViewById(R.id.buttonSayIt);
        editTextTts=(EditText) findViewById(R.id.editTextTts);
        buttonSayIt.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                tts=editTextTts.getText().toString();
                Log.d(TAG, tts);
                speach(tts,"you_utterance_id");
            }
        });
        //check for TTs data
        Intent checkTtsDataIntent=new Intent();
        checkTtsDataIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
        startActivityForResult(checkTtsDataIntent, CHECK_TTS_DATA);

    }

    protected void speach(String tts,String utteranceId) {
        HashMap<String, String> params = new HashMap<String, String>();
        params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,utteranceId);
        textToSpeech.speak(tts,TextToSpeech.QUEUE_FLUSH,params);
    }

    @Override
    public void onInit(int status) {
        if(status==TextToSpeech.SUCCESS){
            if(textToSpeech.isLanguageAvailable(Locale.US)==TextToSpeech.LANG_AVAILABLE){
                textToSpeech.setLanguage(Locale.US);
            }
        }else if(status==TextToSpeech.ERROR){
            Toast.makeText(this, "Sorry Text To Speach faild", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode==CHECK_TTS_DATA){
            if(resultCode==TextToSpeech.Engine.CHECK_VOICE_DATA_PASS){
                textToSpeech=new TextToSpeech(this, this);      
                textToSpeech.setOnUtteranceProgressListener(utteranceProgressListener);
            }else{
                Intent installTtsIntent=new Intent();
                installTtsIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                startActivity(installTtsIntent);
            }
        }
    }

    UtteranceProgressListener utteranceProgressListener=new UtteranceProgressListener() {

        @Override
        public void onStart(String utteranceId) {
            Log.d(TAG, "onStart ( utteranceId :"+utteranceId+" ) ");
        }

        @Override
        public void onError(String utteranceId) {
            Log.d(TAG, "onError ( utteranceId :"+utteranceId+" ) ");
        }

        @Override
        public void onDone(String utteranceId) {
            Log.d(TAG, "onDone ( utteranceId :"+utteranceId+" ) ");
        }
    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}
like image 2
Sanath Avatar answered Oct 14 '22 01:10

Sanath