I am trying to implement an app that reads text in different languages. Surprisingly, when I use the method isLanguageAvailable(Locale loc), it returns true for languages in the Google TTS list that are not downloaded yet. They are even played when I call speak() method. I have concluded that this happens because they are on-line voices.
The documentation shows that you can know whether a voice is on-line or not using method getFeatures() over the Voice object. However, Voice class is implemented for API >= 21. For API < 21, there is a getFeatures(Locale loc) method as well over the TextToSpeech class, which is supposed to return a string array with different feature descriptions. I have tried this last method over different engines and locales, and I generally get an empty array. Probably, this is an extra information that TTS developers can fill in or not...
So, how can I know if a tts-locale is an on-line one for API < 21?
The Google Text to Speech engine is unique in that it can use network synthesised voices if the user has not installed an additional 'offline' download.
Normally to request this, you would include:
put(TextToSpeech.Engine.KEY_FEATURE_NETWORK_SYNTHESIS, String.valueOf(shouldNetwork()));
Their network synthesised voices used to be of noticeably higher quality, but this is less obvious more recently with their improvements.
The information the Text to Speech engines supplied API < 21 was hopeless and general wrong, as you've noted from calls to isLanguageAvailable(Locale loc)
which reports incorrectly for most engines. The new APIs attempt to resolve this, so you will struggle API < 21 to get detailed information which you can rely on. Check out my answer on this question as to how you can query elements.
At the time of writing this, even with the use of the new APIs, engines are providing incorrect information.
IVONA, as an example, when querying getVoices()
returns similar to:
Voice[Name: en-US, locale: en_US, quality: 300, latency: 300, requiresNetwork: false, features: [embeddedTts]]
But it is omitting:
Voice[Name: en-US, locale: en_US, quality: 300, latency: 300, requiresNetwork: false, features: [embeddedTts, **notInstalled**]]
So, your code will assume this engine will work and it wont.... It's very frustrating, along with my unanswered bug reports to them.
All of the above said, you may currently have to fall back on a simple notification the first time you attempt to speak with the engine, when clicked, leads to an FAQ for your app - In the FAQ you'll explain that if the engine doesn't speak, check the installation and downloads.......
It's frustrating that I couldn't post a simple code snippet for you where everything just works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With