23

I play a file through media player and I want to give options like speaker on/off, play though headset, bluetooth ,etc. I tried the below code which works well for android 2.2 but I want something that can also work for 2.2 and 4.0 both. Can you help me to programmatically turn the speaker on/off and playing via headphones?

AudioManager audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
    if(isOn){
        audioManager.setMode(AudioManager.MODE_IN_CALL);    
        audioManager.setMode(AudioManager.MODE_NORMAL); 
    }else{
        //Seems that this back and forth somehow resets the audio channel
        audioManager.setMode(AudioManager.MODE_NORMAL);     
        audioManager.setMode(AudioManager.MODE_IN_CALL);        
    }
    audioManager.setSpeakerphoneOn(isOn);

P.S: I have given this permission in manifest:

android.permission.MODIFY_AUDIO_SETTINGS 
Athira
  • 1,177
  • 3
  • 13
  • 35
Mayuri Khinvasara
  • 1,437
  • 1
  • 16
  • 12

8 Answers8

27

Something like this might work on some devices (I've only tested in on an XPeria P):

final static int FOR_MEDIA = 1;
final static int FORCE_NONE = 0;
final static int FORCE_SPEAKER = 1;

Class audioSystemClass = Class.forName("android.media.AudioSystem");
Method setForceUse = audioSystemClass.getMethod("setForceUse", int.class, int.class);
setForceUse.invoke(null, FOR_MEDIA, FORCE_SPEAKER);
// To get back to the default behaviour, use the combination FOR_MEDIA,FORCE_NONE.

The combination FOR_MEDIA, FORCE_SPEAKER is typically only used internally to route the FM-radio audio to the loudspeaker (since the FM-radio requires you to have a wired headset / headphone plugged in to act as an antenna). Devices that don't have FM-radio functionality (or uses an alternative implementation) might ignore this combination of parameters, so this method would not work on such a device.

Michael
  • 57,169
  • 9
  • 80
  • 125
  • 2
    This works on my Galaxy S2 and android 4.0.4. How did you come up with this idea? This is like a miracle – Uriel Frankel Mar 27 '13 at 15:17
  • 5
    `setForceUse` is the method used internally to force certain audio types to a given device. The reason I know that is that I work with Android audio for a living. – Michael Mar 27 '13 at 15:34
  • I dislike hacks like this because they are almost certain to be broken by a future release of the Android framework. But this is the only way I have found that actually allows output via the speaker when the headset is plugged in. Works on a Huawei Y300 running Android-4.1.1 – William Sep 15 '13 at 05:20
  • Hey Michael, when we have to set back the default behaviour, that is, let it play through earpeice, do we do setForceUse.invoke(null, 1, 0); ? – SoulRayder Jan 07 '14 at 09:22
  • 2
    Its not working in Android Pie device, any idea why? – gkondati Oct 03 '18 at 22:19
  • How can I force a webview to play audio via earpiece? – Sujith S Manjavana Sep 29 '21 at 05:06
6
AudioManager mAudioMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); 

Button mVolumeButton = (Button)findViewById(R.id.btn_Volume);
        mVolumeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mAudioMgr.isWiredHeadsetOn()){
                    mAudioMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
                    mAudioMgr.setWiredHeadsetOn(false);
                    mAudioMgr.setSpeakerphoneOn(true);
                    mAudioMgr.setMode(AudioManager.MODE_IN_COMMUNICATION);

                    Toast.makeText(getApplicationContext(), "SpeakerPhone On", Toast.LENGTH_LONG).show();
                }else{
                    mAudioMgr.setMode(AudioManager.MODE_IN_COMMUNICATION);
                    mAudioMgr.setSpeakerphoneOn(false);
                    mAudioMgr.setWiredHeadsetOn(true);
                    Toast.makeText(getApplicationContext(), "Wired Headset On", Toast.LENGTH_LONG).show();
                }
            }
        });
Jatinkumar Patel
  • 1,094
  • 2
  • 17
  • 34
5

You can acquire either a rear speaker or a front earpiece at time.

If no accessory connected;

Use audioManager.setMode(AudioManager.MODE_IN_CALL); & audioManager.setSpeakerphoneOn(false); to use front speaker/earpiece. But this would play audio in earpiece not on speaker. To use rear speaker, use audioManager.setMode(AudioManager.MODE_NORMAL); & audioManager.setSpeakerphoneOn(true);

If accessory connected; Use audioManager.setMode(AudioManager.MODE_IN_CALL); & audioManager.setSpeakerphoneOn(false); to use front speaker/earpiece. But this would play audio in earpiece not on speaker. To use rear speaker, use audioManager.setMode(AudioManager.MODE_IN_CALL); & audioManager.setSpeakerphoneOn(true);

Note: Make sure audioManager.setWiredHeadsetOn(boolean on) and audioManager.setBluetoothScoOn(boolean on) set to false to route audio via earpiece . And set either to true to route audio accordingly.

Jayesh Tembhekar
  • 516
  • 7
  • 13
4

try follow code snippet:

//for speakerphone on
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.setSpeakerphoneOn(true);

//for headphone on
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.setSpeakerphoneOn(false);

BTW,I tested in Android 7.0(Redmi 4x) and it worked fine.

aolphn
  • 2,950
  • 2
  • 21
  • 30
  • This works for me! Yay! Had been struggling with this for a while. My only issue now is that there is about a second of dead air in the transition from speakerphone to receiver. Not a huge deal but a little annoying. – kjanderson2 Jan 16 '20 at 17:55
  • 1
    audioManager.setMode(AudioManager.MODE_NORMAL); this line code works for me – Mohd Qasim Dec 10 '20 at 14:12
2

Problem solved. For all of you who are still searching for the answer. Well this is not a bug , but just a tricky thing . You need to use the PhoneStateListener

Using this guide : http://danielthat.blogspot.co.il/2013/06/android-make-phone-call-with-speaker-on.html

myna
  • 31
  • 5
2

if u just want to open your speakerphone on u just write this line in oncreate() of your activity.

static AudioManager audioManager =  (AudioManager)getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setSpeakerphoneOn(true);
Sujith Ks
  • 360
  • 2
  • 10
2

Try This.

AudioManager audioManager =(AudioManager)getSystemService(Context.AUDIO_SERVICE);
    if (isOn) {
        isOn = false;
        audioManager.setMode(AudioManager.MODE_IN_CALL);
        audioManager.setMode(AudioManager.MODE_NORMAL);

    } else {
        isOn = true;
        audioManager.setMode(AudioManager.MODE_NORMAL);
        audioManager.setMode(AudioManager.MODE_IN_CALL);

    }
    audioManager.setSpeakerphoneOn(isOn);
-1

Try

AudioManager.speakerphone(true);

Look at this.

Chirag
  • 56,621
  • 29
  • 151
  • 198
  • 1
    I guess you mean `AudioManager.setSpeakerPhoneOn`? (which is what he's already using). There's no speakerphone method in AudioSystem. – Michael Aug 20 '12 at 12:29
  • Look at the link i posted . In that link you can find that method. – Chirag Aug 20 '12 at 12:31
  • You wrote AudioSystem in your answer, but linked to the AudioManager reference. That's why I asked. – Michael Aug 20 '12 at 12:35
  • @chirag : AudioManager.speakerphone(true); This doesn't work. Could you suggest something else which works both for 2.2 and 4.0 – Mayuri Khinvasara Aug 20 '12 at 17:51
  • You must also do: `audioManager.setMode(AudioManager.MODE_IN_CALL);` – Vic Vuci Jan 17 '14 at 18:47
  • With call managers and that type of stuff, you have to implement a check to see if it is android 11+ or below that. Two seperate ways of doing things. Keep that in mind. The same goes for when bringing your activity to the front, so code as if it is two different OS's because in some way it is. – Pierre Jun 29 '14 at 06:22