Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android TTS checking for supported locale with missing/not downloaded voice data

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

like image 774
Charles Li Avatar asked Jun 18 '17 20:06

Charles Li


3 Answers

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;
}
like image 94
luis Avatar answered Nov 16 '22 05:11

luis


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:  
   }
 }
like image 5
Guru raj Avatar answered Nov 16 '22 03:11

Guru raj


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
...
}
like image 1
Maxim Avatar answered Nov 16 '22 04:11

Maxim