Search code examples
javaandroidaudioandroid-audiomanager

Weird AudioManager behaviour of setSpeakerphoneOn


When I try to play a sound or Text-To-Speech sound through STREAM_RING and my earphone is plugged in, the sound will be played on both speakerphone and earphone. It seems to be a default behaviour for Android framework, but I'd like to have sounds play only on earphone when it plugged in.

So I try controlling speakerphone state like this before playing sounds.

AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
am.setSpeakerphoneOn(false);

But it's not enough and not working on my Nexus5(Kitkat 4.4.4). After some googling, I found that some solution suggests to use AudioManager#setMode(int). So the code will be like this.

AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
am.setMode(AudioManager.MODE_IN_CALL);
am.setSpeakerphoneOn(false);

Basically this code will work for my requirement, but the sound is unstable and often intermitted. And it turned out that the code below is totally fine and the sound is not intermitted.

AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
am.setMode(AudioManager.MODE_INVALID);
am.setSpeakerphoneOn(false);

I have no idea why MODE_IN_CALL causes unstable sound and MODE_INVALID works well. And to begin with, I have no idea why I should call AudioManager#setMode(int) to turn the speakerphone off.

Does anyone know about this? Android official reference says nothing about these behaviours so that I cannot understand them clearly.
Of course I already declared <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>.


Solution

  • If you are trying to play audio with stream as STREAM_MUSIC and mode as MODE_NORMAL then only audio routing will be handled by the Android framework to speakerphone and headset once you insert and remove the headset. Personally never used setMode(AudioManager.MODE_INVALID) and I guess you should never make use of that MODE. I don't clearly know your stream type from the code above. Find basic audio routing in my Github repo: https://github.com/sauravpradhan/Basic-Audio-Routing You can implement your routing logic as per the code.