4

The official introduction to Text-To-Speech in Android says that "upon creating your activity, a good first step is to check for the presence of the TTS resources with the corresponding intent:"

Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);

But @gregm in this thread suggests otherwise:

Also, don't use the ACTION_CHECK_TTS_DATA Intent, that's awkward to use.

Instead, do the following:

  1. Create TextToSpeech
  2. OnInit, check isLanguageAvailable() if it is, your app is all set. if not, send the ACTION_INSTALL_TTS_DATA

If I understand correctly, what @gregm does/suggests is to defer the TextToSpeech.LANG_MISSING_DATA check from onActivityResult() to onInit().

Why is this better than the formal approach?

And why is ACTION_CHECK_TTS_DATA so "awkward to use"?

Community
  • 1
  • 1
an00b
  • 11,338
  • 13
  • 64
  • 101

1 Answers1

8

This is @gregm.

ACTION_CHECK_TTS_DATA requires more complicated execution and more code, but yet does the same thing as TextToSpeech.isLanguageAvailable() Let me explain:

1) You need TWO asynchronous processes when you use ACTION_INSTALL_TTS_DATA. First, to launch an Intent and receive the result. Second, to wait for TextToSpeech to call onInit() More can go wrong while your app is doing all that waiting.

2) All you are trying to do is execute an if statement and you need the same code to handle installing the language data if need be, so why bother adding extra complexity?

It boils down do this:

Do you want 1 line of code:

if (TextToSpeech.isLanguageAvailable())
{
 (same tts init code here)
}

or >1 lines of code like:

Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);

public void onActivityResult(...)
{
 if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS)
 (same tts init code here)
}

In my point of view, I'd rather just get to the if statement, instead of using an Intent runaround. I believe the official Android documentation needs to change to recommend this approach.

If you still don't believe that both approaches we are discussing do the same exact thing, check out the alternative implementations I have here and here. Also, If you don't care about all this stuff and just want your app to speak, just extend this Activity and be done.

gregm
  • 12,019
  • 7
  • 56
  • 78
  • Thank you! With your permission I am highlighting the **why bother adding extra complexity?** which is essentially the crux of the answer. I wanted to make sure that I'm not missing something critical that would make applications not work if the "formal" approach is taken. +1 & accepting. – an00b Jul 19 '12 at 23:03
  • 4
    Hello, I tested using isLanguageAvailable, but it's not giving the desired result. For example, Korean's voice data isn't installed. However when I called isLanguageAvailable on the Korean's voice data when it's not downloaded, it simply returned LANG_COUNTRY_AVAILABLE, which is also correct. The locale is available for the engine just the voice data not downloaded yet. However, due to this I can never check to see if the voice data is downloaded or not, since I'm never getting LANG_MISSING_DATA. Is the solution no longer applicable? Thanks! – Charles Li Jun 18 '17 at 16:00
  • 4
    To add on to it, LANG_COUNTRY_AVAILABLE doesn't indicate that the voice data is downloaded, it just indicates it is supported and can be downloaded. – Charles Li Jun 18 '17 at 16:03