I need to instantiate a TextToSpeech object and set a given language (which is set programmatically and may vary). I know I can use setLanguage() but that will only work if
Here is the setup I use for debugging - You could use elements of it in production:
// Container Class
public class ContainerVoiceEngine {
private String label;
private String packageName;
private ArrayList voices;
private Intent intent;
public ContainerVoiceEngine() {
}
public ContainerVoiceEngine(final String label, final String packageName, final ArrayList voices, final Intent intent) {
this.label = label;
this.packageName = packageName;
this.voices = voices;
this.intent = intent;
}
public Intent getIntent() {
return intent;
}
public void setIntent(final Intent intent) {
this.intent = intent;
}
public String getLabel() {
return label;
}
public void setLabel(final String label) {
this.label = label;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(final String packageName) {
this.packageName = packageName;
}
public ArrayList getVoices() {
return voices;
}
public void setVoices(final ArrayList voices) {
this.voices = voices;
}
}
// Usage within an Activity - Debugging only!
private ArrayList containerVEArray;
private int requestCount;
private void getEngines() {
requestCount = 0;
final Intent ttsIntent = new Intent();
ttsIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
final PackageManager pm = getPackageManager();
final List list = pm.queryIntentActivities(ttsIntent, PackageManager.GET_META_DATA);
containerVEArray = new ArrayList(list.size());
for (int i = 0; i < list.size(); i++) {
final ContainerVoiceEngine cve = new ContainerVoiceEngine();
cve.setLabel(list.get(i).loadLabel(pm).toString());
cve.setPackageName(list.get(i).activityInfo.applicationInfo.packageName);
final Intent getIntent = new Intent();
getIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
getIntent.setPackage(cve.getPackageName());
getIntent.getStringArrayListExtra(TextToSpeech.Engine.EXTRA_AVAILABLE_VOICES);
getIntent.getStringArrayListExtra(TextToSpeech.Engine.EXTRA_UNAVAILABLE_VOICES);
cve.setIntent(getIntent);
containerVEArray.add(cve);
}
Log.d("TAG", "containerVEArray: " + containerVEArray.size());
for (int i = 0; i < containerVEArray.size(); i++) {
startActivityForResult(containerVEArray.get(i).getIntent(), i);
}
}
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
Log.i("TAG", "onActivityResult: requestCount: " + " - requestCode: " + requestCode);
requestCount++;
try {
if (data != null) {
final Bundle bundle = data.getExtras();
if (bundle != null) {
Log.d("TAG", containerVEArray.get(requestCode).getLabel() + " - Bundle Data");
final Set keys = bundle.keySet();
final Iterator it = keys.iterator();
while (it.hasNext()) {
final String key = it.next();
Log.d("TAG", "Key: " + key + " = " + bundle.get(key));
}
}
if (data.hasExtra("availableVoices")) {
containerVEArray.get(requestCode).setVoices(data.getStringArrayListExtra("availableVoices"));
} else {
containerVEArray.get(requestCode).setVoices(new ArrayList());
}
}
if (requestCount == containerVEArray.size()) {
for (int i = 0; i < containerVEArray.size(); i++) {
Log.v("TAG", "cve: " + containerVEArray.get(i).getLabel() + " - "
+ containerVEArray.get(i).getVoices().size() + " - " + containerVEArray.get(i).getVoices().toString());
}
}
} catch (final IndexOutOfBoundsException e) {
Log.e("TAG", "IndexOutOfBoundsException");
e.printStackTrace();
} catch (final NullPointerException e) {
Log.e("TAG", "NullPointerException");
e.printStackTrace();
} catch (final Exception e) {
Log.e("TAG", "Exception");
e.printStackTrace();
}
}
Hope that helps.
Edit
Further to your comment, these 'voices' are in actual fact the languages, in the sense that they return a representative Locale in their structure. Be aware though, the Locale is in a different format to the System Locale, which is really annoying and needs to be sorted in a future Android update.
Take a look at my answer here regarding the pitfalls with using tts.setLanguage(Locale). The question also deals with creating a Locale - Locale loc = new Locale(String).
You can use a loop for the ArrayList of available languages to try and construct a Locale from each, for each Engine.
Hope that helps.