Controlling the volume of forced-to-speaker audio

Nitrooo picture Nitrooo · Nov 3, 2013 · Viewed 7.7k times · Source

I'm playing an audio clip using OpenSL ES. In my code I have

    audioManager.setMode(AudioManager.MODE_IN_CALL);
    audioManager.setSpeakerphoneOn(true);

to force audio through the speaker while the headset is plugged in. It works fine, but I can't control the volume. Pressing the volume buttons while the clip is playing makes the volume seekbar appear and move, but the volume doesn't change. Calling setVolumeControlStream(AudioManager.STREAM_VOICE_CALL) or setVolumeControlStream(AudioManager.STREAM_MUSIC) before playing doesn't seem to help. Changing any of the volumes outside of my app (e.g. in the Android settings) doesn't affect the playing volume. Volume control works well on both headset and speaker when no routing is applied.

I've also tried routing the audio to the speaker using this code I found in another answer

    Class audioSystemClass = Class.forName("android.media.AudioSystem");
    Method setForceUse = audioSystemClass.getMethod("setForceUse", int.class, int.class);
    // First 1 == FOR_MEDIA, second 1 == FORCE_SPEAKER. To go back to the default
    // behavior, use FORCE_NONE (0).
    setForceUse.invoke(null, 1, 1);

but it doesn't work on my Android 4.3 Nexus 4. I need the most compatible way to to that anyway.

Any ideas? Thanks.

Answer

Kevin I. Wu picture Kevin I. Wu · Nov 3, 2013

Here is a couple ideas:

  1. MODE_IN_CALL sets all sorts of priority/policy on STREAM_VOICE_CALL. During this time, other STREAM may loose volume control focus. See if your audio clip is played over STREAM_VOICE_CALL.

  2. MODE_IN_COMMUNICATION (for VoIP) may be a better fit for you. MODE_IN_CALL is for cellular call and can degrade your audio quality.

  3. You may want to try grab audio focus and see if that helps. http://developer.android.com/training/managing-audio/audio-focus.html