3

I am trying to identify how to route a very short audio stream (a notification) to a bluetooth headphone that is already paired with the device, while the device is ringing.

When I play any audio at any time, it is routed to the bluetooth device, no problem. But if I try to start playing the audio when receiving an android.intent.action.PHONE_STATE, in RINGING state, the audio is not routed as expected.

I can see that the AudioManager's setBluetoothA2dpOn method has became deprecated, but I actually tried it but is seems has no effect.

I have tried the MediaRouter object, but I can see that MediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO) points to the RouteInfo of the Bluetooth device while the device is ringing, and the AudioManager.isBluetoothA2dpOn is true.

So, can any one tell me why the audio route is like this in the ringing moment? is there any way to force the audio to be routed to the Bluetooth device in such case?

[UPDATED] I have tried again today and I have discovered something that may be the cause of the problem. I have created a BroadcaseReceiver to detect the change in the android.intent.action.PHONE_STATE. if an intent is received and the state is currently ringing, check for AudioManager's mode and you will find it is MODE_NORMAL. but few seconds later the phone will start actually ringing and the mode is going to be changed into MODE_RINGTONE. trying to manually set the mode using the method setMode(AudioManager.MODE_NORMAL) is useless then, the state remains MODE_RINGTONE even after setting it to MODE_NORMAL.

Now, I think the cause of the problem is that in the MODE_RINGTONE mode, all the streams are directed to the phone speaker and here there is no way offered by the android system to change the mode.

khalid
  • 69
  • 2
  • 5

3 Answers3

0

I think the Media player realease the bluetooth connection when the phone is ringing. You can try to obtain the bluetooth audio connection and see if Media player now play through your obtained connection. You can use my class at my answer Using the Android RecognizerIntent with a bluetooth headset and see if it works. The audio in the class is Sco only.

Community
  • 1
  • 1
Hoan Nguyen
  • 18,033
  • 3
  • 50
  • 54
  • Thanks for the help, Hoan. I have read the solution but I think it is far from what I needed, and correct me if I am wrong. SCO is not suitable for my target, I think I will need A2DP here. Moreover, the blutooth utility class meant to detect when a bluetooth device is connected and take actions. My problem is not to detect the bluetooth devices connected, it is related to redirected the audio output to the bluetooth headset instead to the phone speaker while the phone is in the ringing mode – khalid Apr 15 '13 at 22:41
  • It all depends on what the Media player does. When a call comes in Media player probably release the audio connection from bluetooth headset, now if you obtain the connection and start playing, media player just may not check and play, the sound then go to the bluetooth audio connection you obtained. – Hoan Nguyen Apr 15 '13 at 22:47
  • The bluetooth utility is to detect when a bluetooth headset is connected and obtain audio connection. If you play really short sound, I don't think quality matter much. Why don't you try, just implement onScoAudioConntected to play the sound. Call the mbluetoothHelper.start() on RINGING. – Hoan Nguyen Apr 15 '13 at 22:53
  • I have tried, the audio starts playing to the phone speaker, not the bluetooth headset – khalid Apr 16 '13 at 19:27
  • I guess the media player do it own checking and choose the speaker. I do not work with media player so I do not know if there is anyway you can force media player to choose bluetooth audio. When the phone is in the Ringing state, I have no problem doing text to speech via bluetooth headset. – Hoan Nguyen Apr 16 '13 at 19:32
  • If you really want to, this probably would work, using my class and text to speech and onScoAudioConnected you call speak with the sound file you want to play. – Hoan Nguyen Apr 16 '13 at 19:42
  • The speak method from TTS object takes a text to be spoken, it is not supposed to play a given sound, right? – khalid Apr 16 '13 at 20:54
  • No you can speak from a sound file – Hoan Nguyen Apr 16 '13 at 21:05
0

As stated in the JavaDoc for the StartBluetoothSco method:

Note that the phone application always has the priority on the usage of the SCO connection for telephony. If this method is called while the phone is in call it will be ignored. Similarly, if a call is received or sent while an application is using the SCO connection, the connection will be lost for the application and NOT returned automatically when the call ends.`

I tried to start sco then play a music clip in normal mode, it played to the Bluetooth headset without problems, although I couldnot stop the microphone that caused the input stream plays to the headset. I then tried to call my target phone from another phone while the music is still playing, I found that the stream has got redirected automatically to the phone speaker. After the ringing mode is finished, the stream did not get redirected again to the Bluetooth headset and I think that behavior is normal according to what is stated in the JavaDoc above.

My guessing is that Android tries to protect the ringing and in-call modes as possible in order not to allow any unwanted interference from applications. In other words, when in ringing mode then no sound is going to be played to the headset until the call is accepted, and you cannot even change the AudioManager mode from ringing to another mode, your call for mode setter will be ignored.

khalid
  • 69
  • 2
  • 5
  • I obtained the bluetooth audio before ringing so I do not know if you can obtain the audio at the ringing state or not. You can speak the sound file, the file just have to satisfied some conditions. You can look up at http://developer.android.com/reference/android/speech/tts/TextToSpeech.html. Also there is some noise from the ringing sound, which I try to eliminate but so far unsuccessful. – Hoan Nguyen Apr 16 '13 at 21:35
0

I have tried the AudioTrack instead of MediaPlayer, but that makes no difference.

I have then tried the TextToSpeech engine like this:

in the main activity, initialize on create:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textToSpeech=new TextToSpeech(this, this);
    textToSpeech.setLanguage(Locale.US);
    textToSpeech.addEarcon("[wwww]", "XXXXXXXXXXXXXXXXXXXXXXX", R.raw.a);
}

in the broadcast receiver class when rining starting the Bluetooth utility class and adding the below to the onScoAudioConnected method

textToSpeech.playEarcon("[wwww]", TextToSpeech.QUEUE_FLUSH, null);

This did not work too.

khalid
  • 69
  • 2
  • 5