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?
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.
Related
Here's my scenario:
I have a timer that counts down from 20 seconds. At 13 seconds, a sound starts playing. At 0 seconds, I stop the current sound, load up a new sound and play that new sound. Once that sounds finishes, I load up the previous sound, set it to loop, and start it.
This is the logic for hitting 0 seconds:
mp.stop();
mp = MediaPlayer.create(mActivity, R.raw.second_sound);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp = MediaPlayer.create(mActivity, R.raw.first_sound);
mp.setLooping(true);
mp.start();
}
});
Once the last sound starts playing, calling mp.release() doesn't stop the player. Any ideas as to how to stop the player?
Note: mp.release() works during the first time I start playing and during the second sound but not during the looping sound.
Solution: My global MediaPlayer is also named "mp". Oops.
You're getting the mp MediaPlayer objects mixed up a little. If mp.release() is being called outside of the onCompletion() method, it is not referring to the looping instance created there. Change the identifiers in onCompletion() to refer to the "outer" mp. For example, if your code is in MainActivity:
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
MainActivity.this.mp = MediaPlayer.create(MainActivity.this, R.raw.chirp);
MainActivity.this.mp.setLooping(true);
MainActivity.this.mp.start();
}
}
);
Why are you creating new media player every time and not releasing old one onCompltion? did you try setDataSource?
I have a number of audio tracks that I need to play in sequence. I'm using MediaPlayer's OnCompletionListener as follows:
public void OnCompletion(MediaPlayer mp)
{
_completed++;
mp.Reset();
if (_completed < _tracks.Length)
{
try
{
AssetFileDescriptor afd = _context.Resources.OpenRawResourceFd(_tracks[_completed]);
if (afd != null)
{
mp.SetDataSource(afd.FileDescriptor, afd.StartOffset, afd.Length);
afd.Close();
mp.Prepare();
mp.Start();
}
}
catch (Exception ex)
{
throw;
}
}
}
This works, but there is a noticeable delay between tracks. I'd like to reduce that period to as close to zero as possible. Is this possible?
MediaPlayer "chaining" was added with API level 16 (Jellybean). The method you'd be interested in is setNextMediaPlayer(MediaPlayer next):
Set the MediaPlayer to start when this MediaPlayer finishes playback (i.e. reaches the end of the stream). The media framework will attempt to transition from this player to the next as seamlessly as possible. The next player can be set at any time before completion. The next player must be prepared by the app, and the application should not call start() on it.
Not with the standard android player though there were many requests to add gapless playback - https://code.google.com/p/android/issues/detail?id=3461
You can try to create and prepare a second instance of MediaPlayer and switch them quickly in the OnCompletion callback.
I want to play two sounds. I'm using this code but there's lag between the two sounds for about 2s. I want to play the second directly when the first sound is finished. How can I do that?
MediaPlayer mp = MediaPlayer.create(getApplicationContext(),R.raw.s83);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp2){
mp2 = MediaPlayer.create(getApplicationContext(),R.raw.ss);
mp2.start();
}
});
Android 4.1 (v16) adds MediaPlayer.setNextMediaPlayer which was added to allow gapless playing as per the feature list. Prior to that, there is always a small delay between onCompletion and starting another MediaPlayer due to buffering. Creating the second MediaPlayer before onCompletion might help as well (and would be required for using setNextMediaPlayer anyways).
Try this:
Make mp2 a MediaPlayer class field and then use this code:
mp2 = MediaPlayer.create(getApplicationContext(),R.raw.ss);
MediaPlayer mp = MediaPlayer.create(getApplicationContext(),R.raw.s83);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp){
YourActivityClass.this.mp2.start();
}
});
It will at least create the second MediaPlayer object and prepare() before the first sound is played, so you gain some time there.
I am displaying a Timer on a screen.
The requirement is I need to play a sound every second when the timer duration is 5 seconds remaining & finally when it reaches 0 (end) , I need to play another sound.
I am using the following code:
public void onTick(long millisUntilFinished) {
long timeLeft = secondsRemaining // I am getting the seconds left here
if (timeLeft <= 5) {
playAlertSound(R.raw.beep);
}
else if(timeLeft == 0){
playAlertSound(R.raw.beep1);
}
public void playAlertSound(int sound) {
MediaPlayer mp = MediaPlayer.create(getBaseContext(), sound);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
The problem I am facing using the above code , though the each beep sound duration is less than 1 second , I am getting a continuation of the sound. I want to have separate beep sound for every second starting from the remaining 5 seconds till it reaches zero.
Also , the volume of the sound is too low.
Kindly provide your inputs , whether I need to follow any other logic ?
Thanks in advance.
Warm Regards,
CB
You should make sure looping is disabled using the setLooping function and for the volume issue, you can set the playback volume using: the setVolume function.
But, for your appliction you may want to look into using the SoundPool class instead of the MediaPlayer because it's more suitable for situations like yours when you want to play the same short sound more than once.
With your sample code, I would also reverse the order of the setting the onCompleteListener and starting playback, like this:
MediaPlayer mp = MediaPlayer.create(getBaseContext(), sound);
// move the mp.start() from here..
mp.setOnCompletionListener(new OnCompletionListener() {
// your handler logic here..
});
// and add the setLooping and setVolume calls here..
mp.setLooping(false);
mp.setVolume(1.0, 1.0);
mp.start(); // to here..
I tried this code without the OnCompletionListener, and it worked fine with no looping? I guess I'm not understanding your problem. Also... setVolume(1.0,1.0) isn't correct, you need (float,float) not doubles.
I have followed the steps to create my media player object but I cant understand why it is not playing the music track. I used the following code:
mp = new MediaPlayer();
mp.create(this, R.raw.testmed);
mp.setVolume(100, 100);
mp.start();
but no sound is playing through the emulator, and furthermore when i check the method mp.isPlaying() it returns false. What have I missed?!
Many thanks
You have to call all methods necessary to actually start the player. Take a look at Android Media Player state diagram
I think you need to prepare the player before starting. When the player is prepared, it can be started. This is done through a onPreparedListener:
mp = new MediaPlayer();
mp.create(this, R.raw.testmed);
mp.setVolume(100, 100);
mp.setOnPreparedListener(this);
mp.prepare();
Then you will need to define this and it should work:
public void onPrepared(MediaPlayer player) {
mp.start();
}