In my android app I have a TTS using Google engine.
Have something like this:
tts=new TextToSpeech(MyClass.this, status -> {
if(status == TextToSpeech.SUCCESS){
tts.setLanguage(locale);
tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
#Override
public void onDone(String utteranceId) {
if (utteranceId.equals("***")) {
runOnUiThread(() -> {
Button view2 = findViewById(R.id.speech);
view2.setCompoundDrawablesWithIntrinsicBounds(R.drawable.play, 0, 0, 0);
});
}
}
#Override
public void onError(String utteranceId) {
}
#Override
public void onStart(String utteranceId) {
}
});
}
});
Basically I am using 2 languages, slovak and english. Both are working fine with Google TTS.
The problem is, Samsung devices have their own TTS engine set by default and therefore the app text to speech works not on those devices.
After the users changes their device settings to use Google TTS, then it is working.
But is there a way, that my code will support both TTS engines?
I found out that there might work something like this:
TextToSpeech(Context context, TextToSpeech.OnInitListener listener, String engine)
e.g. using com.google.android.tts as the engine parameter.
However in my code I have that like new TextToSpeech(MyClass.this, status -> {... and it doesn't accept engine as a 3rd parameter, and still I don't know how to detect when Samsung engine is needed and switch engines accordingly.
worth trying forcing TTS engine by passing this third param, so exchange very last line in posted snippet
});
to
}, "com.google.android.tts");
there are also two useful methods for you: getDefaultEngine() and getEngines(). just create at start some dummy new TextToSpeech with two params (empty listener) and check what possibilites you have.
also getAvailableLanguages() and isLanguageAvailable(Locale loc) may be useful when Google engine isn't present, but default one still may support your desired langs
Related
In Android, you create a TextToSpeech instance like this:
tts = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int i) {
if (i == TextToSpeech.SUCCESS) {
begin();
}
else {
Log.i(TAG, "init failed");
}
}
}, "com.google.android.tts");
Notice that the desired speech engine is specified as the last argument.
There are multiple possible speech engines that can exist on a device (Samsung, PICO, Google, and more).
Question: How can we know whether or not this this TextToSpeech instance was successful in assigning the specified Engine to itself?
I don't see any way of doing this in the documentation:
onInit() only carries SUCCESS or FAIL, and there seems to be no method to query the (private) "myEngine" variable of the TextToSpeech instance.
I'm trying to create an app which would use Google's TTS to read English, German and Russian texts. However currently it only speaks English. The device runs on Android 4.2.1 with Google TTS 3.10.9.
Below is the code I use for testing.
t1 = new TextToSpeech(getActivity().getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
t1.setLanguage(Locale.US);
// t1.setLanguage(Locale.GERMANY);
// t1.setLanguage(new Locale("ru"));
Log.d("TTS", "ok");
} else {
Log.d("TTS", "error");
}
}
});
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
t1.speak("What is your name?", TextToSpeech.QUEUE_FLUSH, null);
// t1.speak("Wie heisst du?", TextToSpeech.QUEUE_FLUSH, null);
// t1.speak("Как Вас зовут?", TextToSpeech.QUEUE_FLUSH, null);
}
});
When I run the same code on an emulator on Android 7 I can hear all the three languages being spoken.
I couldn't find any information which would help me to answer the question: Since which version does TTS support German and Russian? The wiki page only says that the support for Russian was added in 2014. The corresponding Google Play page doesn't have any information related to versions.
When I open the TTS page on Google Play with that device I only see "Installed" button.
The solution was to turn on Wi-Fi on the device and add German and Russian in "Settings -> Language & Input -> Google voice typing -> Voices". After that the languages were downloaded and the app worked as desired.
I'm trying to reproduce some text with an android aplication that will help visually impaired people, most especially with TTS, but in my case I need Portuguese-Brazil speaking, and the TTS class does not have Portuguese available as locale. Does anyone have any idea how to implement a Portuguese Brazil reader?
I'm using Android Studio, and MinSDK is 15.
...
tts = new TextToSpeech (this, this);
tts.setLanguage(Locale.[X]);
...
tts.speak("Muito obrigado a todos!", TextToSpeech.QUEUE_FLUSH, null);
...
How did you make your onInitListener()? When you call tts = new TextToSpeech (this, this); onInitListener() will connect TextToSpeech service to your tts instance. So, if you try to set language or speak sound, check this value:
tts = new TextToSpeech (this, this);
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
int res = tts.setLanguage(Locale.[X]);
if (res >= TextToSpeech.LANG_AVAILABLE) {
// Then, you can speak with your locale.
// Call speak() in here or after this method.
tts.speak("Muito obrigado a todos!", TextToSpeech.QUEUE_FLUSH, null);
}
}
}
Solved! My problem was that on the device was not installed TTS. So, just installed it from the google store(https://play.google.com/store/apps/details?id=com.google.android.tts&hl=en).
I am developing a very simple app in here. It's for my Cerebral Palsy daughter. It's just a big YES and NO buttons, so she can press them when requested.
Well... I am using SVOX Classic TTS Engine.
Everything was running smoothly until my tablet upgraded to ICS. Now, everytime I run the app, it opens the Market asking for me to install TTS. I hit "back" and then, my app speaks. This is VERY annoying.
Here is what Google API says:
*A successful check will be marked by a CHECK_VOICE_DATA_PASS result code, indicating this device is ready to speak, after the creation of our TextToSpeech object. If not, we need to let the user know to install the data that's required for the device to become a multi-lingual talking machine! Downloading and installing the data is accomplished by firing off the ACTION_INSTALL_TTS_DATA intent, which will take the user to Android Market, and will let her/him initiate the download. Installation of the data will happen automatically once the download completes. Here is an example of what your implementation of onActivityResult() would look like:*
Here is my code:
public class yesOunoActivity extends Activity implements OnInitListener{
ImageView yes;
ImageView no;
public TextToSpeech tts;
private int MY_DATA_CHECK_CODE = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
tts = new TextToSpeech(this, this);
setContentView(R.layout.yesorno);
yes = (ImageView) findViewById(R.id.yes);
no = (ImageView) findViewById(R.id.no);
yes.setClickable(true);
yes.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent arg1) {
if (arg1.getAction() == android.view.MotionEvent.ACTION_DOWN) {
tts.speak("yes!", TextToSpeech.QUEUE_ADD, null);
}
return true;
}
});
no.setClickable(true);
no.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent arg1) {
if (arg1.getAction() == android.view.MotionEvent.ACTION_DOWN) {
//Intent myIntent = new Intent(v.getContext(), ParametrosActivity.class);
tts.speak("no!", TextToSpeech.QUEUE_ADD, null);
}
return true;
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_DATA_CHECK_CODE) {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
// success, create the TTS instance
tts = new TextToSpeech(this, this);
} else {
// missing data, install it
//ATTENTION: BELOW THIS GIVES ME PROBLEMS SINCE IT OPENS MARKET
//AND I HAVE TO HIT THE BACK BUTTON, THEN, IT SPEAKS!
//BTW TTS ENGINE "IS" INSTALLED!!
Intent installIntent = new Intent();
installIntent
.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
} else if (status == TextToSpeech.ERROR) {
}
}
#Override
public void onDestroy() {
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
System.gc();
}
}
If I remove the area with "ATTENTION" above (since I am SURE I have TTS installed), it works the first time I run the app, if I leave the app and I open it again, it says "speak failed: not bound to tts engine"
It's like it doesn't create the TTS object since the app is still in memory.
So, guys... what do you guys think that I should do??
This is driving me crazy and I really need to communicate to my daughter through the tablet!
Any help is appreciated!!
I had this trouble on my application as well: TTS works in 2.3, but when I tried 4.0, it had the same symptoms as your problem (which I just found now while searching for a solution). The engine would work if you force-closed the application through Settings and started it again but just "backing out" and going back made the TTS engine in ICS not bind.
I tried setting the TTS object (mTts) to null after running mTts.shutdown(). When I started the application again after backing out, I got a null error on my mTts.speak() line.
At least for ICS, something is not letting go of the TTS engine. My solution (for now) is that I have made my TTS object static:
// in Activity
private static TextToSpeech mTts;
.
.
.
// in onCreate()
mTts = new TextToSpeech(this, this);
.
.
.
// in onDestroy()
if (mTts != null) {
mTts.stop();
mTts.shutdown();
mTts = null;
}
I was already only using one TTS object for the application so I don't think there are too many downsides to this approach.
This is what I have in onActivityResult(...)
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
if (requestCode == MY_DATA_CHECK_CODE) {
/*
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
// success, create the TTS instance
mTts = new TextToSpeech(this, this);
} else {
// missing data, install it
Intent installIntent = new Intent();
installIntent.setAction(
TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
*/
if (mTts==null) {
Intent installIntent = new Intent();
installIntent.setAction(
TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
mTts = new TextToSpeech(this, this);
}
}
Instead of using if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {...}, I check if mTts has already been instantiated. You'll also have to set mTts as static, as was mentioned by jlquant and Rakesh in an earlier post, so you'll have only a single instance of it. For example, private static TextToSpeech mTts.
So, unless you "Force stop" the app or it stops working because of an error, it won't anymore call the startActivity(installIntent);-- the annoying culprit that asks you to install TTS every time.
I fixed this by installing ivona having both Tts engines cured all problems, though I'm finding other issues such as no default tts is installed using the two together makes one work not a great fix but its s fix,
Also I can't find the option to allow my phone to install non market apps ie apk from my SD card
I had the same problem and solved. Maybe it's a timing issue in bounding, not sure, but a simple action before speak helped me.
Anyway I did this:
mTts = new TextToSpeech(this, this);
String engine = mTts.getDefaultEngine();
mTts = new TextToSpeech(this, this,engine);
Log.d("","...something here...");
Then when I hit my speak button, it speaks. You should watch your variable status on OnInit method. Maybe a separate thread can help talking in the app.
By the way, if you are sure TTS is installed, you can remove the block Intent checkIntent = new Intent(); for checking.
I definitely hope this helps you.
in my app I also used checkintent.setAction(...) to check if the necessary tts files are installed (which was working like a charm before upgrading to ICS). In ICS it always returned that the files are missing. So now I just ignore this check: i am creating the object and it initializes fine.
Moreover I was using two instances for two different languages. This also seems to not work anymore.
Now when I set the language for one of the instances, the other instance of the object is set to the same language (behaves like one instance).
gingerbread allowed setting of default tts in voice input& output / default tts
gingerbread only allows 'preferred' tts in language and input / text to speech output.
so tts is preferred instead of default, which just means it is not as clear as to which gets used.
The default with application overrides where stated is a better option I think.
How can you read data, i.e. convert simple text strings to voice (speech) in Android?
Is there an API where I can do something like this:
TextToVoice speaker = new TextToVoice();
speaker.Speak("Hello World");
Using the TTS is a little bit more complicated than you expect, but it's easy to write a wrapper that gives you the API you desire.
There are a number of issues you must overcome to get it work nicely.
They are:
Always set the UtteranceId (or else
OnUtteranceCompleted will not be
called)
setting OnUtteranceCompleted
listener (only after the speech
system is properly initialized)
public class TextSpeakerDemo implements OnInitListener
{
private TextToSpeech tts;
private Activity activity;
private static HashMap DUMMY_PARAMS = new HashMap();
static
{
DUMMY_PARAMS.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "theUtId");
}
private ReentrantLock waitForInitLock = new ReentrantLock();
public TextSpeakerDemo(Activity parentActivity)
{
activity = parentActivity;
tts = new TextToSpeech(activity, this);
//don't do speak until initing
waitForInitLock.lock();
}
public void onInit(int version)
{ //unlock it so that speech will happen
waitForInitLock.unlock();
}
public void say(WhatToSay say)
{
say(say.toString());
}
public void say(String say)
{
tts.speak(say, TextToSpeech.QUEUE_FLUSH, null);
}
public void say(String say, OnUtteranceCompletedListener whenTextDone)
{
if (waitForInitLock.isLocked())
{
try
{
waitForInitLock.tryLock(180, TimeUnit.SECONDS);
}
catch (InterruptedException e)
{
Log.e("speaker", "interruped");
}
//unlock it here so that it is never locked again
waitForInitLock.unlock();
}
int result = tts.setOnUtteranceCompletedListener(whenTextDone);
if (result == TextToSpeech.ERROR)
{
Log.e("speaker", "failed to add utterance listener");
}
//note: here pass in the dummy params so onUtteranceCompleted gets called
tts.speak(say, TextToSpeech.QUEUE_FLUSH, DUMMY_PARAMS);
}
/**
* make sure to call this at the end
*/
public void done()
{
tts.shutdown();
}
}
Here you go . A tutorial on using the library The big downside is that it requires an SD card to store the voices.
A good working example of tts usage can be found in the "Pro Android 2 book". Have a look at their source code for chapter 15.
There are third-party text-to-speech engines. Rumor has it that Donut contains a text-to-speech engine, suggesting it will be available in future versions of Android. Beyond that, though, there is nothing built into Android for text-to-speech.
Donut has this: see the android.speech.tts package.