Search code examples
androidaudioandroid-mediaplayerandroid-audiomanager

Android - some devices not playing audio through earpiece


There seems to be an issue while trying to play audio files on earpiece in some android devices. Expected behaviour is it should play the audio file in earpiece but in some devices like Samsung galaxy note 2 ( Android version 4.4.2) and Sony Xperia XA ( Android version 6.0) it plays them through speakers.

However in devices like Motorola moto g (android version 6.0) and nexus 5X (android version 7.0) it works fine.

The app also has the android.permission.MODIFY_AUDIO_SETTINGS permission.

Please find the details of this issue below.

Before playing an audio I set the following properties:

audioManager = (AudioManager)configService.getContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setSpeakerphoneOn(isEnabled);
player = new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
player.setDataSource(path);

I have tried setting mode to MODE_IN_CALL, but that didn't work either: audioManager.setMode(android.media.AudioManager.MODE_IN_CALL);

I have also tried solutions from other posts asking similar questions but they didn't help much.

It would be helpful to know whether this issue is device specific and how to fix the same. Thanks for the help.


Solution

  • Finally i found the solution. When registering for intent ACTION_HEADSET_PLUG in BroadcastReceiver, it was broadcasting sticky intent for the headset unplugged event which was saved from the past event. This was causing the callback to fire which played the audio through speaker only.

    Refer to the following stack overflow post for further details: link

    To fix the issue i used isInitialStickyBroadcast() method to filter out the past events.

    public void onReceive(Context context, Intent intent) {
        switch (intent.getIntExtra("state", -1)) {
            case 0:
                if (!isInitialStickyBroadcast()) {
                    // headset unplugged
                }
                break;
            case 1: 
                // headset plugged in
                break;
            default:
                break;
        }
    }