简体   繁体   中英

Android - Play audio from earpiece

I'd like to play audio from a file into the phone's earpiece (or headset of that is connected) using the android MediaPlayer . I tried using the MODE_IN_CALL hack as suggested in this thread - Android - Getting audio to play through earpiece but that did not help. The app also has the android.permission.MODIFY_AUDIO_SETTINGS permission, but any call to m_amAudioManager.setSpeakerphoneOn(false); is ignored.

private AudioManager m_amAudioManager;  
m_amAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);  
m_amAudioManager.setMode(AudioManager.MODE_IN_CALL); 
m_amAudioManager.setSpeakerphoneOn(false); 

A call to setMode(AudioManager.STREAM_VOICE_CALL); on the MediaPlayer did not help either.

mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
mediaPlayer.setDataSource(path);
mediaPlayer.prepare();

Has something changed since android 2.3 to break this code ? I tried the code on Android ICS without any success. Can someone point me in the right direction ? The audio always plays from the speaker phone so far.

It turns out the right way to do this is through the following code.

Play through the ear piece

mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);

Play through the speaker phone

mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

That is it. Any other solution (Including the one posted here -> Android - Getting audio to play through earpiece ) does not work consistently across devices. In fact using MODE_IN_CALL ensures that your audio will never play on certain devices.

Note: You will need to re-prepare the media player to change streams.

i just wanted to add a complete example for Deepak Bala's Answer. It works when not using the MediaPlayer.create() method:

    this.player = new MediaPlayer(); 
    this.player.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);

    try {
        this.player.setDataSource(getContext(), Uri.fromFile(new File(m.localFileUrl)));
        this.player.prepare();
    } catch (IllegalStateException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

Ok in my case the issue was solved by using the below code

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

    mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
    mAudioManager.setSpeakerphoneOn(false);

The following code works fine for me and I have tested in on multiple devices:

1- creating instances:

MediaPlayer mPlayer = MediaPlayer.create(MainActivity.this, R.raw.skype_call_dialing);
AudioManager mAudioManager = ((AudioManager).getSystemService(Context.AUDIO_SERVICE));

2- if you want to set volume to max (optional)

 int maxVolumeMusic = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, maxVolumeMusic, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
 mAudioManager.setMode(AudioManager.STREAM_MUSIC);

3- set audio to play from earpiece:

mAudioManager.setSpeakerphoneOn(false);

4- play:

mPlayer.setLooping(true);
mPlayer.start();

Done!!!! But there is some tips I am going to share with you:

1- in step 2, if you set Audiomanager.setMode() before AudioManager.setStreamVolume() then the volume would not set to max!

2- if you add mPlayer.prepare() before mPlayer.setLooping(true); it would lead to crash!, you should not use mPlayer.prepare() while mPlayer is initializing like this:

MediaPlayer mPlayer = MediaPlayer.create(MainActivity.this, R.raw.skype_call_dialing);

3- in step 2, mAudioManager.setMode() I used AudioManager.STREAM_MUSIC, when I try other modes, in many cases I was not able to switch on and off speaker!

This method is working fine for me.

You need to set audio manager mode too. and then using audiomgr.setSpeakerphoneOn(false) api you can toggle.

AudioManager audiomgr = (AudioManager) 
    context.getSystemService(Context.AUDIO_SERVICE);
audiomgr.setMode(AudioManager.MODE_IN_COMMUNICATION);
audiomgr.setSpeakerphoneOn(false);

How about this then:

// Make sure that streams following the PHONE routing strategy aren't forced
// to play in the speaker.
Class audioSystemClass = Class.forName("android.media.AudioSystem");
Method setForceUse = audioSystemClass.getMethod("setForceUse",
    int.class,
    int.class);
// First 0 == FOR_COMMUNICATION, second 0 == FORCE_NONE.
setForceUse.invoke(null, 0, 0);

Then use STREAM_VOICE_CALL for your MediaPlayer.

If the setForceUse call succeeds and the audio from your MediaPlayer still plays in the loudspeaker, then I'd say something is messed up in the AudioPolicyManager implementation on the phone/tablet that you're testing this on.

I found i needed to set both the mediaplayer and Audiomanager

private MediaPlayer mp = new MediaPlayer();
AudioManager mAudioManager = (AudioManager) v.getContext()
                                .getSystemService(Context.AUDIO_SERVICE);
                        mAudioManager.setSpeakerphoneOn(false);
                        mp.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);

Audio Manager speaker phone issue is resolved by this way only :

AudioManager audiomgr = (AudioManager) 
    context.getSystemService(Context.AUDIO_SERVICE);
audiomgr.setMode(AudioManager.MODE_IN_COMMUNICATION);
audiomgr.setSpeakerphoneOn(false);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM