My Android tutorial states that I can explicitly tell the TTS engine which stream to use:
For music playback:
params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_MUSIC));
And for phone calls:
params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_VOICE_CALL));
My understanding is that audio routing to a Bluetooth headset works such that STREAM_MUSIC
goes to A2DP
(aka "media audio" in Android Bluetooth settings) and STREAM_VOICE_CALL
goes to HSP
(aka "phone audio" in Android Bluetooth settings).
But regardless whether I use STREAM_MUSIC
or STREAM_VOICE_CALL
in my little application, the audio always goes for some reason to A2DP
.
What am I am doing wrong? Is there a way to route TTS output to headset's HSP
profile?
I got this working for the most part, on most devices. Here is the part that starts the TTS on the voice call stream using Bluetooth SCO instead of A2DP.
if (mTtsReady) {
myHash = new HashMap<String, String>();
myHash.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "A2DP_Vol");
OLD_AUDIO_MODE = am2.getMode();
if(SMSstream == 1){
if (am2.isBluetoothScoAvailableOffCall()) {
am2.startBluetoothSco();
}
if(!am2.isSpeakerphoneOn()){
speakerPhoneWasOn = false;
am2.setSpeakerphoneOn(true);
}
myHash.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
String.valueOf(AudioManager.STREAM_VOICE_CALL));
am2.requestAudioFocus(null, AudioManager.STREAM_VOICE_CALL,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
}
else{
am2.requestAudioFocus(null, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
myHash.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
String.valueOf(AudioManager.STREAM_MUSIC));
}
new CountDownTimer(SMS_DELAY, SMS_DELAY/2) {
@Override
public void onFinish() {
try {
mTts.speak(str, TextToSpeech.QUEUE_ADD,
myHash);
} catch (Exception e) {
Toast.makeText(application,
R.string.TTSNotReady,
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
@Override
public void onTick(long arg0) {
}
}.start();
}
Now I just have a problem getting the stream to revert back when done. It all works fine to read TTS. It will pause any music, play the TTS, and then resume music fine. However, when I exit the app later the stream for media now plays through the phone earpiece until I reboot. I posted that question here: Audio stream stays on earpiece after using AudioManager
You can see my whole project here: http://code.google.com/p/a2dpvolume/
If your headset is compatible with the a2dp profile, then using AudioManager.STREAM_MUSIC
and hence playing audio through the stream should get the job done.
I would also add, that if you are currently in a call, and you play audio through the voice stream, then any headset (a2dp or otherwise) can hear the audio. Unfortunately, you need to be in a call.
Unfortunately I have found that setting the mode to MODE_IN_CALL
does nothing.
To sum it up:
If all that you are trying to do is play music (when not in a call), then use the AudioManager.STREAM_MUSIC
and if the headset is A2DP compatible, then it will hear the music.
Also, take a look at AudioManager.isBluetoothA2dpOn()
, to make sure that the system thinks that your headeset is plugged in.
Yes it is possible to play the TTS (text-to-speech) output through a non A2DP headset like jroal says by using SCO.
Use AudioManager startBluetoothSco to enable SCO. Then listen for AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED broadcast with the EXTRA_SCO_AUDIO_STATE set to SCO_AUDIO_STATE_CONNECTED.
If you now do TextToSpeech to the STREAM_VOICE_CALL stream, it will end up in the headset (even the cheap non A2DP devices).
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