26

I've tried the recommended

setSpeakerphoneOn(true) 

and the unrecommended

AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_SPEAKER);

but neither has worked.

I've tried

setWiredHeadsetOn(false)

but that doesn't work either, and is deprecated.

Interestingly,

isSpeakerphoneOn()

reports true, as does

isWiredHeadsetOn()

Additionally, the following permission is set

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
secureboot
  • 1,776
  • 4
  • 20
  • 32
  • 5
    I don't know - but if you figure it out, be very careful with this. You'll piss off a lot of users if this starts happening to them unexpectedly. – Michael Burr Jul 26 '11 at 18:39

5 Answers5

28

The answer turned out to be the following, with tips from Android - Getting audio to play through earpiece

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

Ignore setRouting, it does nothing in APK > 10. Ignore comments about setMode. Ignore comments about setWiredHeadsetOn. Make sure you have MODIFY_AUDIO permissions.

Community
  • 1
  • 1
secureboot
  • 1,776
  • 4
  • 20
  • 32
  • 3
    This forces audio streams from all applications to speaker, is there any way to stream only audio from my application to speaker? – marioc64 Jul 11 '14 at 12:18
2

Thanks to some comments here, and after some search I finally found out how to do this.

My code below is called when I press a button. It sets up audio for activating speakers while calling, then calls the number.

Pay attention to the comments in my code regarding permissions.

buttonRep.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        //1) we need to detect once the call has been established
        //Note : this requires READ_PHONE_STATE permission in your manifest

        final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

        tm.listen(new PhoneStateListener()
        {
            @SuppressWarnings("unused")
            @Override
            public void onCallStateChanged (int state, String incomingNumber)
            {
                if(state == TelephonyManager.CALL_STATE_OFFHOOK) //Here we are
                {
                    //2) we switch sound to speakers
                    //Note : this requires MODIFY_AUDIO_SETTINGS permission in your manifest
                    AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
                    am.setMode(AudioManager.MODE_IN_CALL);
                    am.setSpeakerphoneOn(true);
                    int i = state;

                    //3) we don't need this call listener anymore so we "destroy it"
                    tm.listen(this, PhoneStateListener.LISTEN_NONE);
                }
            }
        }

        , PhoneStateListener.LISTEN_CALL_STATE);

        //4) we are ready to place our call  now
        //Note : this requires CALL_PHONE permission in your manifest
        Intent action = new Intent();
        action.setAction(Intent.ACTION_CALL);
        action.setData(Uri.parse("tel:660")); //660 is my answering-machine number :)
        MainActivity.this.startActivity(action);
    }
});
honk
  • 9,137
  • 11
  • 75
  • 83
Giova
  • 846
  • 1
  • 10
  • 13
2

Try this:

    AudioManager mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);

    IntentFilter iFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
    Intent iStatus = getApplicationContext().registerReceiver(null, iFilter);
    boolean isHeadsetOn = false;

    if (iStatus != null) {
        isHeadsetOn = iStatus.getIntExtra("state", 0) == 1;
    }
    if(mAudioManager.isWiredHeadsetOn() || isHeadsetOn)
    {
        //When headphones are plugged
        mAudioManager.setMode(AudioManager.MODE_CURRENT);
        mAudioManager.setSpeakerphoneOn(true);
    }else { 
        //When headphones are not plugged
        mAudioManager.setMode(AudioManager.MODE_IN_CALL);
        mAudioManager.setSpeakerphoneOn(true);
    }
mangu23
  • 884
  • 9
  • 13
1

Try doing this:

AudioManager manager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
if(manager.isWiredHeadsetOn())
{
    manager.setWiredHeadsetOn(false);
    manager.setSpeakerphoneOn(true); 
    manager.setRouting(AudioManager.MODE_CURRENT, AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL);  
    manager.setMode(AudioManager.MODE_CURRENT); 
}

You will need this permission:

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
A. Abiri
  • 10,750
  • 4
  • 30
  • 31
  • Should've mentioned that I'm on APK 10 or above, where setRouting doesn't do anything. – secureboot Jul 26 '11 at 20:10
  • This doesn't work for me. setRouting and setMode don't do anything (empty functions in the SDK), and calling isWiredHeadsetOn() right after setSpeakerphoneOn(true) returns true. Music continues to play through the headphones. – secureboot Jul 26 '11 at 20:32
  • 2
    Try just setting `manager.setSpeakerphoneOn(true)` in the constructor and see if that works. Also, take a look at the answer of @Donal Rafferty in [this](http://stackoverflow.com/questions/2119060/android-getting-audio-to-play-through-earpiece) question. I think he has got it figured out. – A. Abiri Jul 27 '11 at 06:56
  • setWiredHeadsetOn, setWiredHeadsetOn, setRouting, ROUTE_SPEAKER, ROUTE_ALL are all deprecated, alos it doesn't need that MODIFY_AUDIO_SETTINGS permission, works without it. – Shirish Herwade Jul 15 '14 at 06:13
  • `.setWiredHeadsetOn()` is deprecated. – Nilesh Deokar Oct 21 '17 at 08:18
0

This worked for me

First, I added permissions in Manifest.xml

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

Then, I used this:

AudioManager m_amAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);

m_amAudioManager.setMode(AudioManager.MODE_RINGTONE | AudioManager.MODE_IN_CALL);
m_amAudioManager.setSpeakerphoneOn(true);
  • 1
    `AudioManager.MODE_*` is not a bitfield and can't be used that way. `AudioManager.MODE_RINGTONE` is 1 (binary `01`) and `AudioManager.MODE_IN_CALL` is 2 (binary `10`), the resulting value is binary `11` which is 3, so your code is the same as calling `audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION)` which is the recommended value for VoIP as per the official documentation. – aberaud Aug 11 '21 at 19:46