I save the current volume both STREAM_RING
and STREAM_MUSIC
before sTts.get().speak(s, TextToSpeech.QUEUE_ADD, null)
, I hope the TextToSpeech
can speak a text with max volume,
but in fact I find the TextToSpeech
speak the text with current volume, it seems that sTts.get().speak
is asynchronous.
How can I make TextToSpeech
to speak a text with max volume and restore original volume after speak end? Thanks!
public class SpeechTxt {
private static SoftReference<TextToSpeech> sTts;
public static void SpeakOut(final Context context, final String s) {
final Context appContext = context.getApplicationContext();
if (sTts == null) {
sTts = new SoftReference<TextToSpeech>(new TextToSpeech(appContext,
new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
speak(appContext, s);
} else {
}
}
}));
} else {
speak(appContext, s);
}
}
private static void speak(Context context, String s) {
if (sTts != null) {
switch (sTts.get().setLanguage(Locale.getDefault())) {
case TextToSpeech.LANG_COUNTRY_AVAILABLE:
case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
case TextToSpeech.LANG_AVAILABLE: {
sTts.get().setPitch((float) 0.6);
sTts.get().setSpeechRate((float) 0.8);
int currentRing=PublicParFun.GetCurrentVol(context, AudioManager.STREAM_RING);
int currentPlay=PublicParFun.GetCurrentVol(context, AudioManager.STREAM_MUSIC);
PublicParFun.SetRingVol(context, 0);
PublicParFun.SetPlayVol(context,1000000);
sTts.get().speak(s, TextToSpeech.QUEUE_ADD, null);
PublicParFun.SetRingVol(context, currentRing);
PublicParFun.SetPlayVol(context,currentPlay);
break;
}
case TextToSpeech.LANG_MISSING_DATA: {
break;
}
case TextToSpeech.LANG_NOT_SUPPORTED: // not much to do here
}
}
}
public static int GetCurrentVol(Context myContext,int streamType){
AudioManager mAudioManager = (AudioManager)myContext.getSystemService(Context.AUDIO_SERVICE);
int current = mAudioManager.getStreamVolume( streamType);
return current;
}
public static void SetRingVol(Context myContext,int vol){
SetVol(myContext,AudioManager.STREAM_RING, vol);
}
public static void SetPlayVol(Context myContext,int vol){
SetVol(myContext,AudioManager.STREAM_MUSIC, vol);
}
private static void SetVol(Context myContext,int streamType,int vol){
AudioManager mAudioManager = (AudioManager)myContext.getSystemService(Context.AUDIO_SERVICE);
int max = mAudioManager.getStreamMaxVolume(streamType);
if (vol>max){
vol=max;
}
mAudioManager.setStreamVolume(streamType,vol, 0);
}
}
Edit
Is the following code right? I fixed my original code by your thinking.
I can't understand why the code need to add HashMap, I think sTts.get().setOnUtteranceProgressListener
and sTts.get().setOnUtteranceCompletedListener
don't need HashMap, right?
HashMap ttsParameters = new HashMap(); ttsParameters.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"stringId");
package bll;
public class SpeechTxt {
private static SoftReference sTts;
public static void SpeakOut(final Context context, final String s) {
final Context appContext = context.getApplicationContext();
if (sTts == null) {
sTts = new SoftReference<TextToSpeech>(new TextToSpeech(appContext,
new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
speak(appContext, s);
} else {
}
}
}));
} else {
speak(appContext, s);
}
}
private static void speak(Context context, String s) {
if (sTts != null) {
switch (sTts.get().setLanguage(Locale.getDefault())) {
case TextToSpeech.LANG_COUNTRY_AVAILABLE:
case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
case TextToSpeech.LANG_AVAILABLE: {
sTts.get().setPitch((float) 0.6);
sTts.get().setSpeechRate((float) 0.8);
final int currentRing=PublicParFun.GetCurrentVol(context, AudioManager.STREAM_RING);
final int currentPlay=PublicParFun.GetCurrentVol(context, AudioManager.STREAM_MUSIC);
PublicParFun.SetRingVol(context, 0);
PublicParFun.SetPlayVol(context,1000000);
final Context myContext=context;
HashMap<String, String> ttsParameters = new HashMap<String, String>();
ttsParameters.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"stringId");
if (android.os.Build.VERSION.SDK_INT >=15){
sTts.get().setOnUtteranceProgressListener(new UtteranceProgressListener()
{
@Override
public void onDone(String utteranceId)
{
PublicParFun.SetRingVol(myContext, currentRing);
PublicParFun.SetPlayVol(myContext,currentPlay);
}
@Override
public void onError(String utteranceId)
{
//also, set the volume back
}
@Override
public void onStart(String utteranceId)
{
// set the volume to max
}
});
}else{
sTts.get().setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {
@Override
public void onUtteranceCompleted(String utteranceId) {
PublicParFun.SetRingVol(myContext, currentRing);
PublicParFun.SetPlayVol(myContext,currentPlay);
}
});
}
sTts.get().speak(s, TextToSpeech.QUEUE_ADD, ttsParameters);
break;
}
case TextToSpeech.LANG_MISSING_DATA: {
break;
}
case TextToSpeech.LANG_NOT_SUPPORTED: // not much to do here
}
}
}
}
Edit Again
I test many times, when sTts.get().speak(s, TextToSpeech.QUEUE_ADD, ttsParameters) speak a short string, the sTts.get().setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() is invoked correctly.
but if sTts.get().speak(s, TextToSpeech.QUEUE_ADD, ttsParameters) speak a long string (about 15 seconds), it seems that sTts.get().setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() is not be invoked. Why?
sTts.get().setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {
@Override
public void onUtteranceCompleted(String utteranceId) {
PublicParFun.SetRingVol(myContext, currentRing);
PublicParFun.SetPlayVol(myContext,currentPlay);
}
});
The problem could be, that You set the currentRingVolume directly safter You started the TTS. The code will not wait until the speech has ended. For setting the volume back to the current volume, do it after speech has finished with an UtteranceProgressListener (or onUtteranceCompletetListener < API 15. this depends on which API You are developing):
//first set the HashMap to Your tts
HashMap<String, String> ttsParameters = new HashMap<String, String>();
ttsParameters.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"stringId");
tts.speak("Say Hello",TextToSpeech.QUEUE_FLUSH, ttsParameters );
Set onUtteranceProgressListener:
int result = tts.setOnUtteranceProgressListener(new UtteranceProgressListener()
{
@Override
public void onDone(String utteranceId)
{
//here set the volume back
}
@Override
public void onError(String utteranceId)
{
//also, set the volume back
}
@Override
public void onStart(String utteranceId)
{
// set the volume to max
}
});
and for API < 15:
tts.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {
@Override
public void onUtteranceCompleted(String utteranceId) {
//set volume back
}
});
To find out what version is installed:
if (android.os.Build.VERSION.SDK_INT >=8){
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With