Missing languages in TTS android - java

I am working on an android application that uses the TextToSpeech functionality provided by google and have followed this example:
TTS Example from Google
I want to know with this line:
int result = mTts.setLanguage(Locale.US);
if (result == TextToSpeech.LANG_MISSING_DATA ||
result == TextToSpeech.LANG_NOT_SUPPORTED) {
// Lanuage data is missing or the language is not supported.
}
What can I do if the Language data is missing off the users device? The app will not continue if the data is not there? Is there a way to allow the user to get the language on their device? I have a test device that seems to not have any languages on it at all.

From http://developer.android.com/resources/articles/tts.html:
// missing data, install it
Intent installIntent = new Intent();
installIntent.setAction(
TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
No good way to know exactly what happens if the language they want simply doesn't exist at all, but....that is the recommended way of dealing with it.

Related

Android multiple language support to dynamic content

I want to support my app to multiple languages.I implemented for static strings through localization but what i want is if user change app language from English to any other and input Edit text with google voice then that string will b shown in user selected language rather than English language. As in google translate app happens,i input text by voice and what result is found that string is in that selected language.
Can anyone please help me??
There is limited supported language but you need to invoke Speech Recognition by putting extra intent parameter
private void listen() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
//Specify language
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.SIMPLIFIED_CHINESE)
// Specify language model
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
// Specify how many results to receive
intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 5);
// Start listening
startActivityForResult(intent, SR_CODE);
}
check full answer

How to use QAndroidJniObject to call a Intent from Java

I want to use the rtl_tcp Driver for my App in Android to read Raw data from a usb Tv tuner.
I found this source code https://github.com/martinmarinov/rtl_tcp_andro- and the guy has an App as driver at google play and anyone can call this App and can read raw data via tcp port.
This is the App https://play.google.com/store/apps/details?id=marto.rtl_tcp_andro&hl=en
Now, i would like to call this drivers from my App, but i use QT. I found the classes QAndroidJNIObject to call java code.
I found also at github.com/demantz/RFAnalyzer/blob/master/app/src/main/java/com/mantz_it/rfanalyzer/MainActivity.java an example in java.
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("iqsrc://-a 127.0.0.1 -p 1234 -n 1"));
startActivityForResult(intent, RTL2832U_RESULT_CODE);
}
catch (ActivityNotFoundException e)
{
Log.e(LOGTAG, "createSource: RTL2832U is not installed");
...
}
But i cannot find a way to write the right code in C++/Qt to make the equal call like the example in Java. I am not sure if this java code is correct or missing something.
Can someone help me ?
Also i want to ask if i can have a tcp connection with anet.h libs from Qt code?
You need to use QJniAndroidObject class to create JNI objects and manipulate them. It's not always obvious but it works in the end. Your 9-line of Java will most likely end up to be a 50-line C++ code. I recommend that you transcode each line one by one and always check objects are valid (QJniAndroidObject::isValid()).
Here is an example creating an Intent and starting an activity:
startActivity on Qt, nothing displays
Try to write some code and post another SO question if it fails (syntax to create and manipulate QJniAndroidObject is not always obvious for C++ developers not familiar with Java).

Opening apps on buttons

Im trying to open. Google Search on my application. But the problem is. when I click the button. the COMPLETE ACTION USING windows is popping up instead of the google search.. search the net for more than an hour but it seems I cant find the solution.. here is my code..
#Override
public void onClick(View view) {
Intent intent = new Intent("android.intent.action.MAIN");
intent.setComponent(ComponentName.unflattenFromString("com.google.android.googlequicksearchbox"));
intent.addCategory("android.intent.category.LAUNCHER");
startActivity(intent);
This is due to Android's nature to allow users to make their own decisions. If, for instance, they have Bing installed and prefer it as a search engine over Google, they will have the option to select it. As far as I know, there is no way to open a specific app this way. If the user selects Google and makes it the default app for this action, it will auto-open in successive times, but they must make that conscious decision first.
have you probably tried to follow this guide..?
It describes well about what you might need..
hope it helps..
List<ResolveInfo> resolveInfoList = getPackageManager().queryIntentActivities(intent, 0);
for(int i = 0; i < resolveInfoList.size(); i++) {
ResolveInfo info = resolveInfoList.get(i);
if (info.activityInfo.packageName.equals("com.google.android.googlequicksearchbox") {
// that's the one you want
}
}
I don't have Eclipse available right now to test it, but this should help you get there. Also check out the documentation for queryIntentActivities()
PS: I'm not sure about that packageName for google search
Try this. This code will search the meaning of value of query variable on google.
String url = "http://www.google.com/search?q=" + "Meaning of " +query;
Intent intentSearch = new Intent(Intent.ACTION_VIEW);
intentSearch.setData(Uri.parse(url));
startActivity(intentSearch);

Android Text To Speech Male Voice

I have a working text to speech but I was wondering instead of a female voice when the app calls it to be played it will do a male voice instead?
It is now possible to use male/female voice and change it from App UI dynamically. Define TTS like this (add google tts engine in constructor):
tts = new TextToSpeech(context, this, "com.google.android.tts");
contex = activity/app
this= TextToSpeech.OnInitListener
From tts.getVoices() list, chose your desired voice by it's name like this:
for (Voice tmpVoice : tts.getVoices()) {
if (tmpVoice.getName().equals(_voiceName)) {
return tmpVoice;
break;
}
}
N.B: U need to set _voiceName by getting hard coded voice_name from tts.getVoices(). e.g: for English male it would be: "en-us-x-sfg#male_1-local"
It is possible to change voice into male
here is my code,hope it will help you!
//onCreate
T2S= new TextToSpeech(testApp.getInstance().getApplicationContext(), this, "com.google.android.tts");
Set<String> a=new HashSet<>();
a.add("male");//here you can give male if you want to select male voice.
Voice v=new Voice("en-us-x-sfg#male_2-local",new Locale("en","US"),400,200,true,a);
T2S.setVoice(v);
T2S.setSpeechRate(0.8f);
implements TextToSpeech.OnInitListener on Activity.
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
Set<String> a=new HashSet<>();
a.add("male");//here you can give male if you want to select male voice.
//Voice v=new Voice("en-us-x-sfg#female_2-local",new Locale("en","US"),400,200,true,a);
Voice v=new Voice("en-us-x-sfg#male_2-local",new Locale("en","US"),400,200,true,a);
T2S.setVoice(v);
T2S.setSpeechRate(0.8f);
// int result = T2S.setLanguage(Locale.US);
int result = T2S.setVoice(v);
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "This Language is not supported");
} else {
// btnSpeak.setEnabled(true);
speakOut(mMessageVoice);
}
} else {
Log.e("TTS", "Initilization Failed!");
}
}
And add this function also:
private void speakOut(String message) {
t1.speak(message, TextToSpeech.QUEUE_FLUSH, null);
}
You cannot make the Android TextToSpeech sounds like a male. If you change the TextToSpeech.setPitch() value to something low, like 0.1, it will sound very bad.
Your only option is to try another Text-to-Speech engine, or live with the female sounding voice.
That depends on the underlying TTS engine. Some are configurable and have different voices (male, female, etc.), some only have one voice. In any case, you cannot control this from your app, the user has to change the TTS engine settings from the Settings app. You could only instruct them to install a particular engine, and setup your app to use it.
Contrary to some previous answers, gender is not a parameter (or even a "feature") of a Voice object.
As you can see... as of 5/2021, there is no "isMale" boolean parameter.
There is a "features" Set<String> parameter, but what those strings actually contain is engine dependent and extremely poorly documented and/or implemented... and no engines describe gender using this parameter that I know of.
TextToSpeech.setVoice() is designed such that the Voice being set must be an exact match/instance of one of the Voice objects that was previously returned by TextToSpeech.getVoices() -- it is not a way to somehow create/request a new custom Voice or to attempt to mix and match parameters. (That's not to say some engines won't try to make a best approximation of the non-existent new voice you try to send to it).
Even if gender were implemented, Voice parameters are not designed to be independently settable.
Voice objects are a means by which an engine can describe its available voices using getVoices() -- they are not the voices themselves.
As far as I can tell, the Voice class' constructor is really not useful to anyone other than a speech engine developer.
All of this means that unless the authors of a specific engine have chosen to include "male" or "female" as a substring of the voice's name, there is no way for you to determine whether a voice sounds male or female other than listening to it first.
So, in order to control whether speech output "is" male/female, all the following would have to be true:
you already know the unique voice name (String) you are looking for
the engine that contains that voice is installed on the users device (not in your control)
the installed version of that engine is recent enough to contain that voice (not in your control)
the installed version of that engine is not too recent so as to no longer contain that voice (not in your control)
the user has that particular voice installed (not in your control)
if the voice is not installed, the user is connected to the internet (not in your control)
PS - Even if you think you've found a male voice, it could actually be a female that just sounds male to you. :)
PPS - You could use a cloud service instead to remove all the device unpredictability.
It is possible to change voice into male. Set in onCreate(): tts.setEngineByname("com.google.android.tts") and make the google tts service default in text to speech settings and instaling the male voice in google tts service.
Like this you can use any third party android tts services and check the device. Or ask to install.
Either way you can set your android Text-to-Speech to google TTS service by :
tts = new TextToSpeech(context, this, "com.google.android.tts"), or
Install new male ( English ) voice and set it by default in android.
Hope it helps.
I found 3 Male voices in google tts
en-in-x-ene-network
en-in-x-end-network
hi-in-x-hie-local
Use these in the following way:
textToSpeechEngine.voice = Voice("hi-in-x-hie-local", Locale("hi_IN"), 400, 200, false, HashMap<String>())

How to support multiple android version in your code?

Take accessing contacts in android
android.jar for versions 1.6 has People.CONTENT_URI for invoking contacts related info whereas in later versions we need to have api support for RawContacts.CONTENT_URI.
Same thing is true for accessing calendar for instance as its URI is changed in android 2.2.
Is there a best practice to manage all different changes without adding additional application or build separately for each version of changes?
For my money, a very good answer is at http://android-developers.blogspot.co.uk/2010/07/how-to-have-your-cupcake-and-eat-it-too.html. However, the example there is a little more complicated than need be, so based on that, here is an example of how to cope with it when building notifications. The underlying reason this works is a consequence of how java engines interpret classes: it only looks at them when needed, so if you wrap version specific code up in a class and only create it when you know you are using that version, it all works ...
There are, as far as I can tell, two generations of approaches to creating notification, and a naming change along the way in the second. So that gives three ways to do it. For each way, create a class with the notification generation in it:
The first approach (used through to Gingerbread):
public class MyNotificationBuilderToGingerBread {
Notification notification = null;
MyNotificationBuilderToGingerBread(Context myContext, int icon, String ticker, String title, String info, Long timeStamp, PendingIntent pendingIntent, int flags) {
notification = new Notification(R.drawable.ic_sb, ticker, timeStamp);
notification.setLatestEventInfo(myContext, title, info, pendingIntent);
notification.flags |= flags;
}
Notification get() {
return notification;
}
}
The second approach, Honeycomb to IceCreamSandwich:
public class MyNotificationBuilderHoneyCombToIceCreamSandwich {
Notification.Builder mb = null;
MyNotificationBuilderHoneyCombToIceCreamSandwich(Context myContext, int icon, String ticker, String title, String info, Long timeStamp, PendingIntent pendingIntent, boolean onGoing) {
mb = new Notification.Builder(myContext);
mb.setSmallIcon(icon);
mb.setContentIntent(pendingIntent);
mb.setContentTitle(title);
mb.setContentText(info);
mb.setWhen(timeStamp);
if (ticker != null) mb.setTicker(ticker);
mb.setOngoing(onGoing);
}
Notification get() {
return mb.getNotification();
}
}
The second generation, with the name change, Jellybean (onwards, so far ...):
public class MyNotificationBuilderJellyBean {
Notification.Builder mb = null;
MyNotificationBuilderJellyBean(Context myContext, int icon, String ticker, String title, String info, Long timeStamp, PendingIntent pendingIntent, boolean onGoing) {
mb = new Notification.Builder(myContext);
mb.setSmallIcon(icon);
mb.setContentIntent(pendingIntent);
mb.setContentTitle(title);
mb.setContentText(info);
mb.setWhen(timeStamp);
if (ticker != null) mb.setTicker(ticker);
mb.setOngoing(onGoing);
}
Notification get() {
return mb.build();
}
}
Then, you just need to pick which class to instantiate on the fly:
// System information
private final int sdkVersion = Build.VERSION.SDK_INT;
// If you want to go really old:
// (actually, there is a question about how this issue should be handled
// systematically. Suggestions welcome.)
// final int sdkVersion = Integer.parseInt(Build.VERSION.SDK);
// This is for a permanent notification. Change the final argument (flags or boolean) if it isn't meant ot be
// For meaning of other variable, see notification documentation on the android website.
if (sdkVersion < Build.VERSION_CODES.HONEYCOMB) {
MyNotificationBuilderToGingerBread mnb = new MyNotificationBuilderToGingerBread(myContext, R.drawable.notification_icon, ticketText, title, infoText, timeStampMillis, pendingIntentForTapOnFullNotitifcation, Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR);
notification = mnb.get();
}
else if (sdkVersion < Build.VERSION_CODES.JELLY_BEAN) {
MyNotificationBuilderHoneyCombToIceCreamSandwich mnb = new MyNotificationBuilderHoneyCombToIceCreamSandwich(myContext, R.drawable.notification_icon, ticketText, title, infoText, timeStampMillis, pendingIntentForTapOnFullNotitifcation, true);
notification = mnb.get();
}
else {
MyNotificationBuilderJellyBean mnb = new MyNotificationBuilderJellyBean(myContext, R.drawable.notification_icon, ticketText, title, infoText, timeStampMillis, pendingIntentForTapOnFullNotitifcation, true);
notification = mnb.get();
}
// Send the notification.
notificationManager.notify(idForNotificationManager, notification);
Hope this helps!
There are many resources for you to utilize to help support multiple versions of android.
Read this blog post here and
then read this one here, they
will help you address API level
version support issues.
Read this blog post on multiple
screen support, especially how the
asset hierarchy in parsed in res
folder. This will help you
understand and design how to do
asset folder structure to support
different screen size/densities and
android versions.
Lastly write your own custom ant build
scripts so that you can compile with
all versions of android.
Quite Honestly, it's a pain.
I usually, just isolate parts of code that are different and access them using abstract classes. So technically creating different version for different OS.
But there are other ways. The best one i've seen involves using reflection.
If you don't really need the new functionnalities, and really have to support old Android versions, drop it. Build your app for the oldest version, and don't bother with this kind of thing.
In the other case, you can detect the version using Build, and use reflection to load the classes you need. An example of that can be found in the source code of the K9Mail app
There's a nice article on android.com about it:
http://developer.android.com/resources/articles/backward-compatibility.html
Personally I would suggest the wrapper class or wrapper library solution. But in small cases the reflection should be fine (and in case performance is not a problem for you).
If you need more info, ask in comments.
This is a great article for when you have to do reflection in Android (to support multiple API levels).
And when you have to have different resources for different API Levels, this is the reference to use (see the section on "Platform Version (API level)").
If on Eclipse, from ADT version 17 you can specify code to run with some version simply as described in Lint API Check.
The code word is #TargetAPI(XX)
Hope it helps
Best practice (though not for Android, but for J2ME) to my knowledge is to use preprocessing C/C++ styled statements, like:
//#if S40
...
//#else
...
//#endif
Some IDE's support these kind of preprocessing, e.g. Netbeans. To my knowledge Eclipse has some plugins to enable preprocessing also. I don't really know are they applicable to Android development. Try to google yourself.

Categories