1

I'm working on an application which needs to use the class Text to speech to be able to read a text. The thing is that the initialization is very slow, approximately 4 sec. I followed this tutorial : http://code.tutsplus.com/tutorials/use-text-to-speech-on-android-to-read-out-incoming-messages--cms-22524. I made some research but I didn't find really good answers or I miss them.

For example I tried this solution by calling my checkTTS function in a thread but no result where visible. Here and here, they said that my checkTTS function with intent is maybe not so useful and I can just see if my needed language is available.

So my questions :

  • Can I really just check if my language exist, what is really the big difference between ACTION_CHECK_TTS_DATA and just check if language is available ?
  • Can I improve something else ?

Here is my activity code :

public class MyActivity extends Activity {
    private Speaker _speaker;
    private final int CHECK_CODE = 0x1;
    private final int SHORT_DURATION = 1000;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        System.out.println("I'm just before checkTTS");
        checkTTS();
    }


    private void checkTTS(){
        System.out.println("I'm in checkTTS");
        Intent check = new Intent();
        check.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
        startActivityForResult(check, CHECK_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == CHECK_CODE){
            if(resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS){
                System.out.println("I'm in onActivityResult");
                _speaker = new Speaker(this);
            }else {
                Intent install = new Intent();
                install.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                startActivity(install);
            }
        }
    }

    @Override
    protected void onDestroy() {    
        super.onDestroy();
        _speaker.destroy();
    }
}

And here is my Speaker class :

public class Speaker implements OnInitListener {
    private TextToSpeech _tts;
    private boolean _ready = false;
    private boolean _allowed = false;

    public Speaker(Context context){
        _tts = new TextToSpeech(context, this);
    }   

    public void setSpeedRate(float speechrate) {
        _tts.setSpeechRate(speechrate);
    }

    public boolean isAllowed(){
        return _allowed;
    }

    public void allow(boolean allowed){
        _allowed = allowed;
    }

    @Override
    public void onInit(int status) {
        System.out.println("I'm in onInit from Speaker");
        if(status == TextToSpeech.SUCCESS){
            _tts.setLanguage(Locale.UK);
            _ready = true;
        } else{
            _ready = false;
        }
    }

    public void speak(String text){
        if(_ready && _allowed) {
            HashMap<String, String> hash = new HashMap<String,String>();
            hash.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_NOTIFICATION));
            _tts.speak(text, TextToSpeech.QUEUE_ADD, hash);
        }
    }

    public boolean isSpeaking() {
        return _tts.isSpeaking();
    }

    public void pause(int duration){
        _tts.playSilence(duration, TextToSpeech.QUEUE_ADD, null);
    }

    public void stop() {
        _tts.stop();
    }

    public void destroy(){
        _tts.shutdown();
    }
}

Here is the log from eclipse :

15:14:58.897: D/dalvikvm(23966): GC_CONCURRENT freed ...
15:15:00.014: I/System.out(23966): I'm just before checkTTS
15:15:00.014: I/System.out(23966): I'm in checkTTS
15:15:00.046: D/AbsListView(23966): unregisterIRListener() is called 
15-13 15:15:01.272: I/System.out(23966): I'm in onActivityResult
15:15:01.311: I/TextToSpeech(23966): Sucessfully bound to com.samsung.SMT
15:15:01.663: D/AbsListView(23966): onVisibilityChanged() is called, visibility : 4
15:15:01.663: D/AbsListView(23966): unregisterIRListener() is called 
15:15:02.600: I/TextToSpeech(23966): Connected to ComponentInfo{com.samsung.SMT/...}
15:15:02.608: I/TextToSpeech(23966): onServiceConnected but waiting
15:15:02.608: I/System.out(23966): I'm in onInit from Speaker
15:15:02.616: I/System.out(23966): Speaker ready
15:15:02.616: I/TextToSpeech(23966): onServiceConnected waiting end

Thank you for your help, Best regards, Zed13

Ps : sorry for the mistakes...

Edit : funny facts, it seems to launched faster with samsung voices than with google voices...

Community
  • 1
  • 1
zed13
  • 357
  • 4
  • 21
  • The reason for it working on Samsung voices faster is that Samsung phones use the Samsung TTSEngine by default, which does not have intialization lag like the Google TTS Engine. Speaking of which, did you find a solution to your issue? – SoulRayder Feb 24 '17 at 16:48

1 Answers1

0
  1. According to the Android API, ACTION_CHECK_TTS_DATA "Starts the activity from the platform TextToSpeech engine to verify the proper installation and availability of the resource files on the system". In that case, does not make sense create a TTS instance until you receive CHECK_VOICE_DATA_PASS. Alternatively, if for some reason (state flag, etc) you are confident that the system has the required TTS resources installed, you may use a "optimistic approach", i.e., you skip this step, initialize a TTS instance (for example, in your onCreate method) and after check the available languages or if some language is supported. Since you are skipping a step (ACTION_CHECK_TTS_DATA), if everything succeed, your initialization will be quicker.

You can check the engines installed in the system looking to this code and use that information to launch more accurate ACTION_CHECK_TTS_DATA intents.

  1. The rest of the code looks good from a performance point of view. However, keep in mind that you can launch ACTION_CHECK_TTS_DATA intent and initialize the TTS instance simultaneously! If something is missing the intent is already launched and TTS will not work as expected. If the device has all TTS resources, the intent will pass and TTS is already initialized. You can look to the Audio News app as an example of this behavior ;)
r.pedrosa
  • 709
  • 5
  • 12
  • I made the modifications and I won 2 sec. So now my question is, is it optimistic that thinking TTS will be installed on smartphone with android 4.0 or more ? On my Galaxy S3, on the Galaxy Tab 2 and xperia it was ok. – zed13 May 14 '15 at 08:07
  • If you look to a [somehow old post](http://android-developers.blogspot.pt/2009/09/introduction-to-text-to-speech-in.html), "Although all Android-powered devices that support the TTS functionality ship with the engine, some devices have limited storage and may lack the language-specific resource files. If a user wants to install those resources, the TTS API enables an application to query the platform for the availability of language files and can initiate their download and installation. So upon creating your activity, a good first step is to check for the presence of the TTS resources". – r.pedrosa May 14 '15 at 09:01