3

I'm playing a sound through STREAM_ALARM:

MediaPlayer mp = new MediaPlayer();
mp.setDataSource(context, notificationSoundUri);
mp.setAudioStreamType(AudioManager.STREAM_ALARM);
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }
});
mp.prepare();

It worked ok until I tried on Android 6. On Android 6 sound doesn't play from beginning, so if I play short sounds, no sound is heard. I tried using seekTo(0) and initializing MediaPlayer in other ways. It only happens in Android 6 when using STREAM_ALARM (other streams work well).

Any help?

EDIT: I realized that sound actually starts playing from start, but at very low volume, and after about 2 seconds volume increases... do you know how to deactivate this behavior?

Scott Johnson
  • 288
  • 2
  • 12
Sergio Viudes
  • 2,714
  • 5
  • 26
  • 44

1 Answers1

1

It sounds like an equalization problem (maybe this audio stream comes with an audioSessionId which is already handled by the system equalizer?)

I will try the following trick before the MediaPlayer initialization:

1) Change the STREAM_ALARM volume

AudioManager mAudioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM);
mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, maxVolume, 0 /*flags*/);

2) Set volume after prepare()

//...
mp.prepare();
mp.setVolume(1.0f, 1.0f);

3) Change the audioSessionId

//...
mp.setAudioStreamType(AudioManager.STREAM_ALARM);
mp.setAudioSessionId(CUSTOM_ID); //manually assign an ID here
//...

UPDATE

4) Try to use the SoundPool API instead of MediaPlayer and see if the problem persists (I also suspect that this is a device-dependent issue).

5) Try to call start() ==> pause() ==> start() on MediaPlayer

@Override
public void onPrepared(MediaPlayer mp) {
    mp.start();
    mp.pause();
    mp.start();
}

6) Try to trick the initial "low volume" period using the following logic:

  • before play, set volume to 0
  • play
  • after 2 seconds of playback, seek to position 0 (this may consume the silent period)
  • set the volume to max
  • play again

In this way, you may be able to do a normal playback, with an initial delay of few seconds.


Let us know your progress, I'll update this answer accordingly with more information and suggestions.

bonnyz
  • 13,458
  • 5
  • 46
  • 70
  • I tried what you suggested: set alarm volume, set mp volume, and setAudioStreamType, but it doesn't make any difference :( – Sergio Viudes Oct 19 '15 at 17:26
  • @SergioViudes :( I've updated my answer with more tips, let me know – bonnyz Oct 19 '15 at 18:12
  • Hi. Thanks, but it doesn't work. It seems that Nexus 6 does it when a sound is played through STREAM_ALARM... – Sergio Viudes Oct 20 '15 at 07:46
  • @SergioViudes Do you tried on other 6.0 device or emualtor? – bonnyz Oct 20 '15 at 07:53
  • No. But although it works on emulator, I would like to have it working on my device, to be sure it works on all devices. – Sergio Viudes Oct 20 '15 at 07:59
  • @SergioViudes Yea, but it really sounds like a device-dependent issue. This is a typical equalizer problem, which exists on many devices (not just 6.0 ones). – bonnyz Oct 20 '15 at 08:00
  • I think it's by design, because it has sense that an alarm sound starts playing from low volume. But would be great to change this behavior if we like. – Sergio Viudes Oct 20 '15 at 08:07
  • @SergioViudes Updated again with my last workaround ;) – bonnyz Oct 20 '15 at 08:23
  • Thanks for your last workaround, but I need to play notification sounds, that usually are very short (less than 2 seconds). – Sergio Viudes Oct 20 '15 at 08:46
  • @SergioViudes Ok I understand, but if you don't need that to trigger instantly (you can always set your alarm two seconds before), you can use this workaround (e.g. wait in pause for one second) – bonnyz Oct 20 '15 at 08:57
  • Maybe it works but... what about if other devices need 3 seconds instead of 2? It's a smart solution, but I think is not the definitive one – Sergio Viudes Oct 20 '15 at 09:03
  • Yea I agree. Best thing you can do at the moment imho is to create a method to do this *play - wait - seek* with a global parameter containing the number of seconds to wait; thus tune your alarms and notifications using this logic. After that you will only need to change the global parameter to 2, 3 or 4 seconds without changing any other codes. Note that if you set a wait time higher then the necessay, this won't impact the user experience since you will be already consindering the artificial delay in your alarm. That's to say, set this param to 6 seconds and sleep well ;) – bonnyz Oct 20 '15 at 09:10