TextToSpeech setLanguage not working? - java

I am setting my TextToSpeech to use a particular language (English - UK), using the locale "en_GB". But it always uses my devices default language. Is there no way to set it programmatically? I have downloaded the files required for the language and when I change my TTS's default language to 'English - UK' it works but when the default is different the programmatic approach does not work. I have scoured the web to my best but am unable to resolve this issue.
String ttsEngine = "com.google.android.tts";
txt2Speech = new TextToSpeech(this, this, ttsEngine);
//Locale ttsLocale = new Locale("eng", "GBR");
txt2Speech.setLanguage(new Locale("en_GB"));
Tried several methods, but none are working.
Can I not set my TTS's language programmatically?
Thank You
EDIT: In response to 'A Honey Bustard'
Other Code:
public class MainActivity extends AppCompatActivity implements TextToSpeech.OnInitListener
My onInit()
public void onInit(int status) {
// TODO Auto-generated method stub
}
Also I'm calling .setLanguage() in my onCreate(), as soon as my TextToSpeech is initialized. Is that correct? Also I'm only calling it once. It is not required to call it every time right? Also I'm testing on a GS7

You need to set the language once the Text to Speech Engine has initialised correctly.
public void onInit(int status) {
switch (status) {
case SUCCESS:
// Set the language here
break;
case ERROR:
// Something went wrong. You can't set the language
break;
}
}
That should do it.

Try the second Constructor from Locale that takes two Strings like this :
txt2Speech.setLanguage(new Locale("en", "GB"));
EDIT :
Yes it is usually ok to do instantiate it in onCreate, and it usually only needs and should be done once.
All I can do is show you my working code, I am setting the default language after instantiating in onCreate() :
textToSpeech = new TextToSpeech(getApplicationContext(), this);
textToSpeech.setLanguage(Locale.getDefault());
In my app there are buttons in which you can change the language, which trigger this code (case British English) :
textToSpeech.setLanguage(new Locale("en", "GB"));
Maybe it is not available somehow , there are some checks you can validate if the language and country is available. You might find your error there.
if (textToSpeech.isLanguageAvailable(new Locale("en", "GB")) == TextToSpeech.LANG_COUNTRY_AVAILABLE
&& textToSpeech.isLanguageAvailable(new Locale("en", "GB")) == TextToSpeech.LANG_AVAILABLE)
should return true.

Related

Android java tts.isLanguageAvailable() not working even after language is available

I want to check if a specific language pack (Google Text-to-Speech) is available or not.
t1=new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(t1.isLanguageAvailable(new Locale("bn_BD")) >= TextToSpeech.LANG_AVAILABLE)
{
// Set language
}
}
});
but the problem is t1.isLanguageAvailable(new Locale("bn_BD")) is always returing false even the language is available and also working this voice.
You must construct the Locale object using separate strings for the language and country like this:
new Locale("bn", "BD")
see this and this. :)

I upgraded to Android Studio 2.3.3 and an old, bug-free program now gives error: "Fragments should be static..."

The full text of the error is:
C:\Users\Dov\Google Drive\AndroidStudioProjects\FlagQuiz - Copy (2)\app\src\main\java\com\dslomer64\flagquiz\QuizFragment.java
Error: Fragments should be static such that they can be re-instantiated by the system, and anonymous classes are not static [ValidFragment]
To make it worse, it doesn't tell me which line the error is in. I had assumed, since it was mentioned above, that QuizFragment is at fault, but how? So I then concluded that QuizFragment was mentioned only to indicate which class the error is in.
Also, note that no line is flagged with error as the yellow square shows.
I found the word "anonymous" in 3 places in comments in the incomplete code segment below.
DialogFragment quizResults = new DialogFragment() // anonymously **********
// extend DialogFragment class
{
#Override public Dialog onCreateDialog(Bundle bundle)
{
...
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setPositiveButton
(
R.string.reset_quiz,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
resetQuiz();
}
} // end anonymous inner class *******************
);
return builder.create(); // return the AlertDialog
} // end method onCreateDialog
}; // end DialogFragment anonymous inner class ****************
Is there something wrong (as of AS 2.3.3; nothing was wrong before upgrade) with DialogFragment quizResults = new DialogFragment() or the definition of builder, which contains an anonymous inner class?
If so, why no compilation errors? And in this case, how do I fix the problem?
(I don't want to just start hacking away at code I didn't write [I received project from an author and made many modifications] since there are at least 3 conceivable starting points and maybe none address the error(s?).
nothing was wrong before upgrade
Most likely, there was. Android Studio was not complaining about your code previously, but it may not have worked properly anyway. What changed is that now Android Studio is pointing out the problem, rather than you finding out the hard way in testing.
Is there something wrong... with DialogFragment quizResults = new DialogFragment()
Yes. It's impossible to recreate the fragment.
So, when the user rotates the screen, or changes locale, or night mode kicks in, or any number of other possible configuration changes, when Android destroys the fragment and tries to recreate it, it can't. Only the lines of code in your question can recreate the fragment, and those lines of code are yours, not the framework's, and it doesn't know about them.
It is possible that you have worked around this by blocking the ordinary destroy-and-recreate cycle for the activity, via android:configChanges. That itself is usually an anti-pattern, but if you legitimately need android:configChanges and are using it properly, you should be able to suppress this Lint error.
And in this case, how do I fix the problem?
Create a regular Java class for quizResults, extending DialogFragment and including your code. Then, use that Java class.
The part that is wrong is the following:
DialogFragment quizResults = new DialogFragment() {
#Override
public Dialog onCreateDialog(Bundle bundle) {
where you are defining an anonymous subclass of DialogFragment. This is the wrong way to use Fragments as suggested by the new lint check in Android 2.3.3.
Why? Instantiating Fragments like this will cause problems if you are using an Activity's FragmentManager.
The problematic situation is as follows: when Activity#saveInstanceState(Bundle outState) is called the FragmentManager will attempt to save the state of your Fragment. When subsequently the Activity's state is restored, the FragmentManager will attempt to recreate your Fragments (using no-args constructors) and set their states to the way they were before. This is not possible if you use anonymous subclasses of Fragment.
Henec, Fragments must have a no-args constructor and the preferred way of instantiating them is with static factory methods. Instead of anonymous subclasses, use Fragment#setArguments(Bundle bundle):
inside QuizFragment.java:
public static QuizFragment instantiate(Bundle args) {
QuizFragment frag = new QuizFragment();
frag.setArguments(args);
return frag;
}
I ran into this same problem. I converted the anonymous DialogFragment class into a regular class :
public DialogFragment instantiate(Bundle args){
DialogFragment quizResults = new DialogFragment();
quizResults.setArguments(args);
Dialog aDialog = createDialog(args);
aDialog.show();
return quizResults;
}
// create an AlertDialog and return it
public Dialog createDialog(Bundle bundle){
AlertDialog.Builder builder =
new AlertDialog.Builder(getActivity());
builder.setCancelable(false);
builder.setMessage(
getResources().getString(
R.string.results, totalGuesses, (1000 / (double) totalGuesses)));
// "Reset Quiz" Button
builder.setPositiveButton(R.string.reset_quiz,
new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog,int id)
{
resetQuiz();
}
} // end anonymous inner class
); // end call to setPositiveButton
return builder.create(); // return the AlertDialog
} // end method createDialog
The original code block under onClick(View v):
///////////////////////////////////////////////////////////////////
DialogFragment quizResults = new DialogFragment()
{
// create an AlertDialog and return it
#Override
public Dialog onCreateDialog(Bundle bundle)
{
AlertDialog.Builder builder =
new AlertDialog.Builder(getActivity());
builder.setCancelable(false);
builder.setMessage(
getResources().getString(R.string.results, totalGuesses, (1000 / (double) totalGuesses)));
// "Reset Quiz" Button
builder.setPositiveButton(R.string.reset_quiz,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
resetQuiz();
}
} // end anonymous inner class
); // end call to setPositiveButton
return builder.create(); // return the AlertDialog
} // end method onCreateDialog
Was replaced with call to instantiate the DialogFragment as below:
DialogFragment quizResults = instantiate(mSavedInstanceState);
Thanks to #Commonsware and #David Rawson, I managed to make it work with static inner class for myDialogClass by changing anything the compiler griped about to static, which included several methods as well as many (every?) variable.
This posed one problem:
public static void loadNextFlag()
{
...
// display current question number--2nd and 3rd parameters are INPUT into the xml statement
questionNumberTextView.setText
(correctAnswers + 1) + //was ,
"/" + FLAGS_IN_QUIZ);
// AssetManager assets = getActivity().getAssets();
...
} // end method loadNextFlag
The line for formatting questionNumberTextView had to be changed to
questionNumberTextView.setText(
("" + (correctAnswers + 1)
"/" + FLAGS_IN_QUIZ);
because the original
questionNumberTextView.setText(getResources().getString
(R.string.question,
(correctAnswers + 1),
FLAGS_IN_QUIZ);
gave the static vs. non-static error for getResources. I just settled for not as great a format, but suitable.
I also made assets a global static variable to be assigned only once, in onCreateView.
So textbooks don't always do it right, since to do so would raise the level of the text too far above the intended audience.

Google Fit Listen for Data Updates not working

I'm trying to implement a Google Fit Listener when data is updated into Google Fit services.
In this link of Google Fit documentation there is a simple example, however, it is not 100% clear. For that reason, I have two problems:
I don't know how to implement mResultCallback variable (there aren't any examples in this documentation).
When I define a simple ResultCallback (it seems to work but I'm not sure) and I launch the application, it gives me a result error code: java.lang.SecurityException: Signature check failed
The code within the HistortyApi lists one of android.permission.ACCESS_FINE_LOCATION or android.permission.BODY_SENSORS as being required.
Adding those permissions to my code hasn't resolved the same problem though.
Confirmed bug in Google Fit services. See discussion in https://plus.google.com/110141422948118561903/posts/Lqri4LVR7cD
mResultCallback is a ResultCallback<Status> so you need to implement a class of that type. Documentation is here, but there's only one method you need to implement:
public abstract void onResult (Status result)
The standard way is to do this using an anonymous class either when you declare mResultCallback or when you're using it as a parameter. Below is an example from Google's BasicRecordingAPI example:
Fitness.RecordingApi.subscribe(mClient, DataType.TYPE_ACTIVITY_SAMPLE)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
if (status.getStatusCode()
== FitnessStatusCodes.SUCCESS_ALREADY_SUBSCRIBED) {
Log.i(TAG, "Existing subscription for activity detected.");
} else {
Log.i(TAG, "Successfully subscribed!");
}
} else {
Log.i(TAG, "There was a problem subscribing.");
}
}
});
If you want to use a member variable you can simply make an assignment instead:
ResultCallback<Status> mResultCallback = new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
...
}
});
Of course you can define a non-anonymous class, but if you did that for every callback you had you would end up creating a LOT of classes.

java callback, unscribe listener inside of interface implementation

I would like to implement system of callbacks which looks like this (pseudo code):
final Listener listener = ListenerCtrl.addListener(new Listener() {
void onNotify(String response){
ListenerCtrl.unsetListener(listener);
} }
This code mean that after received message, i want to unscribe from future notifications. I found very attractive have this action inside of callback.
Here is my actual implementation:
final WebServiceMsgListener wml = new WebServiceMsgListener()
{
public void onMsgNotify(JSONObject response, int ecode)
{
Log.v(TAG, "getSetStateProgressBar MSG_MGT_STATICINFO: onMsgNotify ecode" +
ecode);
authDelegate.unsetMsgListener(wml);
}
};
authDelegate.addMsgListener(NAOMsg.MSG_MGT_STATICINFO, wml);
Unfortunately, my current implementation show me eclipse error:"The local variable wml may not have been initialized"
Question: how I can get round this, to finally unscribe inside of callback and dont have this error ?
Change your code to:
authDelegate.unsetMsgListener(this);
this refers to the current object (whose onMsgNotify() is being executed at the time this statement is executed).
Note: Although, the variable wml is available to the new object, it has not yet been initialized at the time of the creation of the object, hence the error. It is initialized right after the object is fully created.

Is this typically how Java interfaces are used to set up event handlers, and are there hidden drawbacks to this approach?

Hey all, I'm still relatively new to Java, and looking for a sanity check.
I've been studying this Java port of Cocos2D and noticed that the CCLayer class has built-in hooks to the Android native touch events. That's great, but what I'd really like is for objects like CCSprite to directly respond to touch events without having to listen for those events in the layer and iterate through all the children to find which ones happen to intersect the event's x/y coordinates. So I figured that this would be the perfect chance to test my understanding of how to set up some event handlers and make a subclass of CCSprite that actually listens for touches without needing to go through CCLayer to know about it. Furthermore, I wanted to be able to assign different behaviors to different CCSprite instances on an ad-hoc basis without explicitly subclassing further, much like Android Buttons don't need to be subclassed just to give them a handler for their touch events.
This is what I came up with on a first pass:
// My touch interface for all touchable CCNode objects.
package com.scriptocalypse.cocos2d;
public interface ITouchable {
boolean onCCTouchesBegan();
boolean onCCTouchesEnded();
boolean onCCTouchesMoved();
}
And now the class that uses the ITouchable interface for its callbacks...
public class CCTouchSprite extends CCSprite implements CCTouchDelegateProtocol {
protected ITouchable mTouchable;
public void setTouchable(ITouchable pTouchable){
mTouchable = pTouchable;
boolean enable = mTouchable != null;
this.setIsTouchEnabled(enable);
}
public void setIsTouchable(boolean pEnabled){
// code to enable and disable touches snipped...
}
/////
// And now implementing the CCTouchDelegateProtocol...
/////
public boolean ccTouchesBegan(MotionEvent event) {
Log.d("hi there", "touch me");
if(mTouchable != null){
mTouchable.onCCTouchesBegan();
}
return CCTouchDispatcher.kEventHandled; // TODO Auto-generated method stub
}
public boolean ccTouchesMoved(MotionEvent event) {
if(mTouchable != null){
mTouchable.onCCTouchesMoved();
}
return CCTouchDispatcher.kEventIgnored; // TODO Auto-generated method stub
}
public boolean ccTouchesEnded(MotionEvent event) {
Log.d("hi there", "not touch me");
if(mTouchable != null){
mTouchable.onCCTouchesEnded();
}
return CCTouchDispatcher.kEventIgnored; // TODO Auto-generated method stub
}
}
And finally, instantiate the class and implement the interface...
final CCTouchSprite sprite = new CCTouchSprite(tex);
sprite.setIsTouchEnabled(true);
sprite.setPosition(CGPoint.ccp(160,240));
sprite.setTouchable(new ITouchable(){
#Override
public boolean onCCTouchesBegan() {
Log.d("SWEET SUCCESS", "I got a touch through my interface!");
return true;
}
#Override
public boolean onCCTouchesEnded() {
Log.d("SWEET SUCCESS", "You stopped touching my interface!");
sprite.runAction(CCRotateBy.action(1, 360));
return false;
}
#Override
public boolean onCCTouchesMoved(){
Log.d("SWEET SUCCESS", "You moved the touch");
return false;
}
});
So all of this works. The subclass does successfully register with the Cocos2D touch dispatcher, which successfully calls those ccTouches functions and pass them MotionEvents, which in turn call my Interface functions if the interface has been instantiated.
Is this the "proper" way to do it (Define "it" as you see fit, ranging from using Interfaces to create event handlers to working with Cocos2D, to writing Java at all)? Are there drawbacks to this that I'm not aware of? Is this somehow worse for performance than iterating through all the CCNode objects that are children of CCLayer? If so, how can that possibly be?
I think you have got the basics for setting up a listener right. There are some things I would change though.
First, the setter setIsTouchable. It's weird. You need a listener object to pass touch events to right? So what is this setter going to do when you pass it true (as your example does)? You snipped the code, but setting a boolean field to true does not seem right here as it would put the sprite object in an inconsistent internal state. I would just drop that setter. The getter can just evaluate whether mTouchable is assigned or null.
Second, why limit yourself to one listener? Change mTouchable to mTouchables, being a list of ITouchables. Then change setTouchable to addTouchable and possibly add removeTouchable and clearTouchables methods. This way you can add multiple listeners for different behaviors having to respond to the same events. This is how most other event systems work as well. You then just change isTouchable to check whether the list is empty or not.
scriptoclypse... I really am not completely understanding your question, but you have not had any response and yes interfaces and events are very similar. At this level I can only respond in C#.

Categories