13

I'm using Android's TextToSpeech class. Everything is working normally. However, there are languages/locales that aren't installed by default but supported by the TTS engine and I can't capture the state of missing voice data.

With the internet on, when I try to setLanguage to a new locale which its voice data hasn't been downloaded, it'll simply download the voice data and perform the speak method normally/successfully.

However, with internet off, when I try to setLanguage to a new locale which its voice data hasn't been downloaded, it attempts to download the voice data. But with no internet, it just indicates "downloading" on the "TTS voice data" settings screen under "Language and input" for the selected locale, without any progress. And as expected the speak method doesn't work since the voice data isn't downloaded. When this happens, I would think TTS methods setLanguage/isLanguageAvailable will return LANG_MISSING_DATA for me to capture this state, however, it simply returns LANG_COUNTRY_AVAILABLE. The situation is shown in this image: enter image description here

I want to be able to detect when the voice data of the locale being chosen isn't downloaded/missing and either give a toast message or direct user to download it. I have seen several posts suggesting the use of using isLanguageAvailable like this one. I also looked at the android documentation and it seems like isLanguageAvailable's return values should capture the state of missing voice data with LANG_MISSING_DATA.

I also tried sending an intent with ACTION_CHECK_TTS_DATA as the other way to check for missing data as suggested in the Android documentation I linked. However, the resultCode again didn't capture/indicate that the voice data is missing (CHECK_VOICE_DATA_FAIL) but returned CHECK_VOICE_DATA_PASS instead.

In this case, how should I capture the state of a language/locale being available/supported, with the voice data missing? I'm also curious why CHECK_VOICE_DATA_PASS and LANG_MISSING_DATA aren't the values returned. When the voice data is missing, shouldn't it return these values? Thanks! Below is the return value when I try to use setLanguage and isLanguageAvailable on locales that haven't had its voice data downloaded (0 and 1 are the returned value of the method shown in the logs, -1 is the one that corresponds to missing voice data): enter image description here

Charles Li
  • 1,835
  • 3
  • 24
  • 40

3 Answers3

5

You can find all available Locale of the device using following function. hope this code will help you.

 Locale loc = new Locale("en");
 Locale[] availableLocales= loc.getAvailableLocales();
 Boolean available=Boolean.FALSE;
 for (int i=0;i<availableLocales.length;i++)
 {
  if(availableLocales[i].getDisplayLanguage().equals("your_locale_language"))
   {
        available=Boolean.TRUE;
        // TODO:  
   }
 }
Guru raj
  • 806
  • 11
  • 10
  • Thank you for your input! However, that's not what I was looking for. You can even use a TTS instance to get all supported and available languages supported by the engine more effectively. Anyways, thanks for your input! – Charles Li Jun 23 '17 at 02:13
2

I have this implementation as part of a wrapper class to work with TextToSpeech, I hope it helps:

public boolean isLanguageAvailable(Locale language)
{
    if(language == null) return false;
    boolean available = false;
    switch (tts.isLanguageAvailable(language))
    {
        case TextToSpeech.LANG_AVAILABLE:
        case TextToSpeech.LANG_COUNTRY_AVAILABLE:
        case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
            if(Build.VERSION.SDK_INT >= 21){
                tts.setLanguage(language);
                Voice voice = tts.getVoice();
                if(voice != null){
                    Set<String> features = voice.getFeatures();
                    if (features != null && !features.contains(TextToSpeech.Engine.KEY_FEATURE_NOT_INSTALLED))
                        available = true;
                } else available = false;
                tts.setLanguage(this.language);
            }
            break;

        case TextToSpeech.LANG_MISSING_DATA:
        case TextToSpeech.LANG_NOT_SUPPORTED:
        default:
            break;
    }
    return available;
}
luis
  • 131
  • 10
  • This seems to be working fine on API 21, it captures the state and I can display a proper message that a language is not available. However, it still automatically queues a download for the missing language. What about API <21 ? Is there a way to get a proper availability state so that I could display a warning? – xinaiz Jun 13 '19 at 08:39
  • android TextToSpeech has a method `getFeatures(Locale)` which can be used on API < 21 to get the set of features and then you can use the same check to see if the features contains the key and then download the voice data. – Shivam Pokhriyal Nov 24 '20 at 11:03
1

It looks like a long waiting question but anyway. It seems that you have to check voice features to find it out:

Set<String> features = voice.getFeatures();
if (features.contains(TextToSpeech.Engine.KEY_FEATURE_NOT_INSTALLED)) {
//Voice data needs to be downloaded
...
}
Maxim
  • 11
  • 1