SpeechToText and running the ACTION_CHECK_TTS_DATA intent - android

I've implemented the TextToSpeech integration exactly as mentioned in this blog post. After I've added it to my program it's now interfering with my other intents.
For example:
List item
User starts app
User invokes load activity
User picks a file to load, and activity returns fileanme to load in the intent
Main activity starts, and realizes it needs to load a filename so it starts doing so
The check for TTS needs to be done so I launch the ACTION_CHECK_TTS_DATA intent
This pauses the main activity again and the loading process gets interrupted
When the TTS check returns, the loading never happened.
When do I need this TTS check? Can I just do it once on application start up? It's causing my application to load slowly. I would like this load to be performed in a separate thread if possible.

Do the check once. Once the data is installed, it's very unlikely that the user will need to ever do it again. Once the data is installed, there's no way for the user to delete it, even if they wanted to.
Also, don't use the ACTION_CHECK_TTS_DATA Intent, that's awkward to use.
Instead, do the following:
Create TextToSpeech
OnInit, check isLanguageAvailable()
if it is, your app is all set.
if not, send the ACTION_INSTALL_TTS_DATA
Here's some code that initializes a TextToSpeech in the way I suggest. As a bonus, it sets the language as well.
public class DemoCreateTTS
{
private static final String TAG = "DemoCreateTTS";
private TextToSpeech tts;
public void createTextToSpeech(final Context context,
final Locale locale)
{
tts = new TextToSpeech(context, new OnInitListener()
{
#Override
public void onInit(int status)
{
if (status == TextToSpeech.SUCCESS)
{
Locale defaultOrPassedIn = locale;
if (locale == null)
{
defaultOrPassedIn = Locale.getDefault();
}
// check if language is available
switch (tts.isLanguageAvailable(defaultOrPassedIn))
{
case TextToSpeech.LANG_AVAILABLE:
case TextToSpeech.LANG_COUNTRY_AVAILABLE:
case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
Log.d(TAG, "SUPPORTED");
tts.setLanguage(locale);
//pass the tts back to the main
//activity for use
break;
case TextToSpeech.LANG_MISSING_DATA:
Log.d(TAG, "MISSING_DATA");
Log.d(TAG, "require data...");
Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
context.startActivity(installIntent);
break;
case TextToSpeech.LANG_NOT_SUPPORTED:
Log.d(TAG, "NOT SUPPORTED");
break;
}
}
}
});
}
}

Related

How to make sure TextToSpeech is initialized before using speak?

I'd like to ask you for some help with Android TextToSpeech feature.
Basically, I'd like to develop a simple AI which speaks, asking a question then waits for an answer, and at last, based on answer asks another question and so on, until user pronounces a keyword which stops everything.
Now I know TextToSpeech has to be initialized before using speak method, and I'm trying to take this into account by using onActivityResult method.
Below some code:
Activity class:
public class MainActivity extends AppCompatActivity implements OnInitListener, Button.OnClickListener{
Button sayHello;
TextView textView;
private static final int CHECK_DATA = 0;
private static final Locale defaultLocale = Locale.UK; // British English
private static final String TAG = "TTS";
private TextToSpeech tts;
private boolean isInit = false;
sayIt Method: used to speak:
public void sayIt(String text, boolean flushQ){
if(isInit){
if(flushQ){
tts.speak(text, TextToSpeech.QUEUE_FLUSH, null, null);
} else {
tts.speak(text, TextToSpeech.QUEUE_ADD, null, null);
}
} else {
Log.i(TAG, "Failure: TTS instance not properly initialized");
}
}
TextToSpeech Listener:
#Override
public void onInit(int status){
if(status == TextToSpeech.SUCCESS){
isInit = true;
// Enable input text field and speak button now that we are initialized
sayHello.setEnabled(true);
// Set to a language locale after checking availability
Log.i(TAG, "available="+tts.isLanguageAvailable(Locale.UK));
tts.setLanguage(defaultLocale);
// Examples of voice controls. Set to defaults of 1.0.
tts.setPitch(1.0F);
tts.setSpeechRate(1.0F);
// Issue a greeting and instructions in the default language
tts.speak("Initialized!", TextToSpeech.QUEUE_FLUSH, null, Integer.toString(12));
} else {
isInit = false;
Log.i(TAG, "Failure: TTS instance not properly initialized");
}
}
Button Listener:
#Override
public void onClick(View v){
if(isInit)
sayIt("You clicked!", true);
}
onActivityResult Method:
// Create the TTS instance if TextToSpeech language data are installed on device. If not
// installed, attempt to install it on the device.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CHECK_DATA) {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
// Success, so create the TTS instance. But can't use it to speak until
// the onInit(status) callback defined below runs, indicating initialization.
Log.i(TAG, "Success, let's talk");
tts = new TextToSpeech(this, this);
// Use static Locales method to list available locales on device
Locale[] locales = Locale.getAvailableLocales();
Log.i(TAG,"Locales Available on Device:");
for(int i=0; i<locales.length; i++){
String temp = "Locale "+i+": "+locales[i]+" Language="
+locales[i].getDisplayLanguage();
if(locales[i].getDisplayCountry() != "") {
temp += " Country="+locales[i].getDisplayCountry();
}
Log.i(TAG, temp);
}
} else {
// missing data, so install it on the device
Log.i(TAG, "Missing Data; Install it");
Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
}
And, at last, onCreate Method:
#Override
public void onCreate(Bundle savedInstance){
super.onCreate(savedInstance);
setContentView(R.layout.activity_main);
sayHello = findViewById(R.id.sayBtn);
textView = findViewById(R.id.textView);
sayHello.setEnabled(false);
sayHello.setOnClickListener(this);
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, CHECK_DATA);
/* THIS SPEAK DOES NOT WORK! */
sayIt("Speech from method!", true);
}
Issue is: Button successfully gets enabled when onInit method initialises TextToSpeech and successfully pronounces text.
My goal is to make the Activity speak from onCreate method, since at the moment it only works from onInit and onClick listeners, bot not in onCreate, even if I check for tts initialization using onActivityResult.
Basically I want the TextToSpeech to speak with no Buttons involved.
I know very similar questions were already posted, but none solved my problem. Have some idea?
Hope I've been clear, Thank you!
UPDATE: Log shows ERROR detected occurs in else branch of onInit method, where Log.i(TAG, "Failure: TTS instance not properly initialized"); line is.
SOLUTION:
The only thing to do here is to wait a little time in order to let TextToSpeech initialize for good.
A good way seems to be by using a delayed Handler as follows:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Waiting for RobotTextToSpeech initialization for 1500ms
rtts.speak("This speak will work!");
rtts.speak("This other speak will work too!");
}
}, 1500);
}
By doing this, looks like TextToSpeech works well even in onCreate method, we just have to wait little time.
Hope this can help.

How to prevent config class from getting freed, when APP in background

I made an Android APP, which has an config structure, which contains data,and services I need throughout all activities.
I now face the issue, that if my APP is in the background for a while, my APP crash, because my config structure has been deleted.
In my config structure, I also have data, I can not easily recreate at runtime.
So in my first Activity, I create the config structure.
FreightWeightConfig config = new FreightWeightConfig(getApplicationContext()); // make sure our config is up and running
And the start of my config class looks like
public FreightWeightConfig(Context appContext) {
instance = this;
mApplicationContext = appContext;
tcBlue.setCallingContext(appContext);
tcBlueConfig = Config.getInstance(); // to make sure it is available straight away
mFirebaseAuth = FirebaseAuth.getInstance();
....
}
I have a second function in the config structure, which allows me to get the instance of my config class, which I need to get access to functions and interfaces in config and services.
public static synchronized FreightWeightConfig getInstance () {
//if (FreightWeightConfig.instance == null) {
// FreightWeightConfig.instance = new FreightWeightConfig(getApplication().getApplicationContext());
//}
if (FreightWeightConfig.instance == null){
FirebaseCrash.logcat(Log.ERROR, LOG_TAG, "Fatal Error : FreightWeightConfig.getInstance()==null. Try restarting the APP");
FirebaseCrash.logcat(Log.ERROR, LOG_TAG, "Fatal Error : Killing ourself, as we have no chance to go on");
//System.exit(0); // we are in a bad state
// Toast.makeText(mApplicationContext, "Fatal Error : FreightWeightConfig.getInstance()==null. Try restarting the APP", Toast.LENGTH_SHORT).show();
}
return FreightWeightConfig.instance;
}
In every Activity, I created a variable that hold a copy the instance. This is simply, because I thought it tells the system, I still need this class, do not kill it. Which does not seem to work.
I first thought, whenever I find my config class to be dead, I can recreate it. But it is not a simple task, as I need the APP context and need to recreate my services in the background. Also I store selections made, while navigating my APP
Anyone has a good Idea, how to solve the unloading / deleting my config class?
Based on the suggestion I extended Application like this:
public class FreightWeightApp extends Application implements DialogInterface.OnCancelListener {
private String LOG_TAG = "FreightWeightApp";
private FreightWeightConfig config;
public static int GOOGLE_PLAY_SERVIE_ABBORTED = 1001;
public void onCreate() {
super.onCreate();
// We first check if the google services are present, if not, better abort!!
int result = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this);
switch (result) {
case SUCCESS:
Log.d(LOG_TAG, "Google Services available");
break;
case SERVICE_MISSING:
Log.e(LOG_TAG, "Google Services missing, STOP");
googleServiceNotUpToDateDialog(result);
break;
case SERVICE_VERSION_UPDATE_REQUIRED:
Log.w(LOG_TAG, "Service update required");
googleServiceNotUpToDateDialog(result);
break;
case SERVICE_DISABLED:
Log.e(LOG_TAG, "Service disabled, STOP");
googleServiceNotUpToDateDialog(result);
break;
}
config = new FreightWeightConfig(getApplicationContext()); // make sure our config is up and running
}
private void googleServiceNotUpToDateDialog(int result) {
// Try to ask the user to update or finish off
// GoogleApiAvailability gaa = GoogleApiAvailability.getInstance();
// Dialog dialog = gaa.getErrorDialog(this, result, GOOGLE_PLAY_SERVIE_ABBORTED, this); //<==== Can not call this, as I have no Activity Context
// dialog.show();
}
#Override
public void onCancel(DialogInterface dialogInterface) {
// Now I should abbort the APP, or we will crash.
}
}
But now I have issues with verifying the GoogleService.
Dialog dialog = gaa.getErrorDialog(this, result, GOOGLE_PLAY_SERVIE_ABBORTED, this);
as I have no Activity Context.
Create your own implementation of Application, then initialize your config object in the onCreate() method(in this case the getInstance() method could also initialize the object).
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
FreightWeightConfig config = FreightWeightConfig.getInstance(getApplicationContext());
}
}
Declare your implementation in your app's module manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="your.package">
<application
android:name="your.package.MyApplication"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
...
</application>
</manifest>
Now you can use your config instance in the activities just like you do, calling getInstance(); the Application onCreate will do the load work. But there is no way to "unload the resources before the app process gets killed/cached", you just have to understand how Android components' lifecycle works.

Auto download offline speech recognition language on Android

Is there any way in Java to detect if an Android device has an offline speech recognition language installed, and if it does not prompt the user to download it?
I know you can ask to speech to text to prefer offline speech to text, but how do you know if the device has the language installed?
This question is not on how to use offline speech, this works.
The question is "how to detect and download/install offline speech languages" from Java app code. i.e. have the app detect if they have offline German language installed, and if not prompt the user to download/install it.
This is not the answer you are hoping for, as at the time of writing, I don't believe there is a straight forward solution to this. I very much hope to be proved wrong.
I requested an enhancement to provide this information programmatically a long time ago - here
The enhancement suggested an additional parameter RecognizerIntent.EXTRA_SUPPORTED_OFFLINE_LANGUAGES:
It would surely be trivial for this to be added and used in the following way:
final Intent vrIntent = new Intent(RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS);
getContext().sendOrderedBroadcast(vrIntent, null, new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
final ArrayList<String> vrStringLocales = intent.getExtras().getStringArrayList(
RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES);
// This would be nice
final ArrayList<String> vrStringOfflineLocales = intent.getExtras().getStringArrayList(
RecognizerIntent.EXTRA_SUPPORTED_OFFLINE_LANGUAGES);
}
}, null, 1234, null, null);
Alas, it has never happened.
You do have two other options to attempt to handle this gracefully.
In the unlikely event you application runs with root permissions, you can check the location of /data/data/com.google.android.googlequicksearchbox/app_g3_models/ which contains the offline files, labelled quite handily by their locale.
The second involves knowing when the user needs a prompt to install the missing offline files.
From my experience, the recognition error of SpeechRecognizer.ERROR_SERVER most often denotes this, but it is not foolproof.
#Override
public void onError(final int error) {
switch (error) {
case SpeechRecognizer.ERROR_SERVER:
// TODO - prompt to install offline files
break;
}
}
When detected, you can guide the user to the correct installation screen.
public static final String PACKAGE_NAME_GOOGLE_NOW = "com.google.android.googlequicksearchbox";
public static final String ACTIVITY_INSTALL_OFFLINE_FILES = "com.google.android.voicesearch.greco3.languagepack.InstallActivity";
public static boolean showInstallOfflineVoiceFiles(#NonNull final Context ctx) {
final Intent intent = new Intent();
intent.setComponent(new ComponentName(PACKAGE_NAME_GOOGLE_NOW, ACTIVITY_INSTALL_OFFLINE_FILES));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
ctx.startActivity(intent);
return true;
} catch (final ActivityNotFoundException e) {
} catch (final Exception e) {
}
return false;
}
Using hard-coded values such as this, is of course not ideal, but neither is this situation!
Once you've messed around with all of the above and think you have a good interim solution - think again! Regardless of whether the user has correctly installed the missing offline files, it is highly likely it still won't work.....
My answer here describes the process I still have to guide my user's with. It's very frustrating.
Finally one more bug to throw into the mix - RecognitionListener.onError(int) can be thrown when there isn't an error. Check my gist from the answer here to use a BugRecognitionListener so you can check the callbacks are being sent in the correct order and ignore those that aren't. This remains a problem, despite my answer suggesting a fix in a previous release.
The above should keep you busy! Good luck....
To detect whether needed Language(German) is available, please follow below :
Iterate the Locale list and check whether Locale available for German language.
If you didn't get any Locale object in return, you can conclude that German language is not available offline. Then you can write code to download and do other stuff.
I did below implementation for my project. Hope below code helps you !!!
private TextToSpeech t1;
private void setForOtherLangAudio() {
Locale[] locales = Locale.getAvailableLocales();
Locale loc = null;
for (Locale locale : locales) {
// Replace XXX with your German codes
if (locale.getDisplayCountry().equals("XXX") && locale.getDisplayLanguage().equals("XXX")) {
loc = locale ;
break;
}
}
final Locale germanLocale = loc;
t1 = new TextToSpeech(getContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
t1.setLanguage(germanLocale);
}
}
});
}

Multiple Smart Lock dialogs on orientation change

I recently integrated Google's Smart Lock for Passwords feature into my app and almost everything is running smoothly as expected.
There is just one small issue I was not able to fix yet: In ResultCallback#onResult, if status.getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED the following command leads to the presentation of a Google resolution dialog that is asking whether to save the credentials via Smart Lock (see attached image) or which credentials to use, if there are already multiple credentials saved in Smart Lock:
status.startResolutionForResult(getActivity(), REQUEST_CODE_READ);
When the resolution dialog is presented, and the user does some orientation changes, then the resolution dialog multiplies, each of them overlapping the others. As a user, you first don’t see that there are multiple copies of the dialog, but if you close the first (by tapping on „Never“ or „Save Password“) then the uppermost dialog disappears, revealing another identical dialog below.
You can handle this by maintaining some state between the activity starting and stopping.
See use of the mIsResolving variable in this sample code. Simply save whether there is a pending dialog already when onSaveInstanceState() is called and restore in onCreate(), and guard against calling the API again if so, clearing the state once onActivityResult() is received for the intent.
private void resolveResult(Status status, int requestCode) {
// We don't want to fire multiple resolutions at once since that can result
// in stacked dialogs after rotation or another similar event.
if (mIsResolving) {
Log.w(TAG, "resolveResult: already resolving.");
return;
}
if (status.hasResolution()) {
try {
status.startResolutionForResult(MainActivity.this, requestCode);
mIsResolving = true;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
...
if (savedInstanceState != null) {
mIsResolving = savedInstanceState.getBoolean(KEY_IS_RESOLVING);
}
...
#Override
protected void onSaveInstanceState(Bundle outState) {
...
outState.putBoolean(KEY_IS_RESOLVING, mIsResolving);
...
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
...
mIsResolving = false;
...
This is a common pitfall for many apps, so we'll look into whether we can support this state in Play Services layer, but for now, using the boolean for the activity is the current and general recommendation for maintaining resolution state.
I know, that it's an old question, but recently i have to fight with this issue, in my case I was using status.startResolutionForResult() in custom class and i didn't have any access to onSaveInstanceState() (I could make some custom callback with interface, but i didn't want to), but in my custom class i had an instance of an activity, so always before calling startResolutionForResult() I'm checking mActivity.hasWindowFocus() to see if activity lose focus, becouse of dialog that show, if it's true, then I call startResolutionForResult(), otherwise i do nothing
#Override
public void onResult(#NonNull LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()){
case LocationSettingsStatusCodes.SUCCESS:
getLocation();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
if (mActivity.hasWindowFocus()) {
try {
status.startResolutionForResult(mActivity, SETTINGS_CHECK);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
mReceiver.unableToObtainLocation();
break;
}
}

Android not acknowledging TTS Engine

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.

Categories

Resources