m_MediaPlayer = MediaPlayer.create(context, soundFromResource);
m_MediaPlayer.setVolume(0.99f, 0.99f);
m_MediaPlayer.setLooping(true);
m_MediaPlayer.setOnCompletionListener(USoundPlayback.this);
m_MediaPlayer.start();
I've tested it like above, I've also tested it by calling setLooping(true) after start() but with no luck.
I have two Nexus 5 phones, both with Android 5 on them. On one, the looping works, on the other the sound stops after one go, it won't loop.
Any ideas ?!
Apparently there's an issue with Android 5 devices which use the NuPlayer instead of the AwesomePlayer.
You can check it by going in the Developer Options, under the Media section there should be Use NuPlayer (experimental). I've unchecked that and it appears it's alright now.
I haven't been able to figure out how to fix this issue, so I've hacked it a bit. I've set some flags in the code and when it enters onCompletion, if the user hasn't specifically stopped the sound, i restart it there. If there's anyone with a better fix, let me know and i'll update this answer.
Here's the issue: https://code.google.com/p/android-developer-preview/issues/detail?id=1695
After a lot of experimentation with media player, I have found solution to this :
call
m_MediaPlayer.setLoopoing(true)
after
m_MediaPlayer.start()
It is an issue in media player.
I used the next code to fix that:
mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
if (looping) {
mMediaPlayer.seekTo(0);
}
}
});
I solve this using this workaround:
public static void setMpLooping(final MediaPlayer mp, final boolean isLooping) {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP
|| Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1) {
if (isLooping) {
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.start();
}
});
} else {
mp.setOnCompletionListener(null);
}
} else {
mp.setLooping(isLooping);
}
}
But remember, sometimes there is a delay during the transition from end to start of the track on Lollipop
Related
I am trying to play some audio in background using two MediaPlayers inside a Service. Everything works fine if I want to play only one mp3, but If I try to play two at the same time, using two instances of MediaPlayer, only the last one works. It is weird because it works in emulator and some devices, but I am unable to make it work in a Nexus 5. This is the code I am using to create the two MediaPlayer instances:
private void playWithPiano() {
mp1 = initializePlayer(filenameVoz); // filenameVoz is the mp3 file name in raw folder
mp2 = initializePlayer("base_piano");
mp1.start();
mp2.start();
}
private MediaPlayer initializePlayer(String filename) {
int identifier = getResources().getIdentifier(filename,
"raw", getPackageName());
MediaPlayer mp = MediaPlayer.create(this, identifier);
mp.setOnErrorListener(new OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.d(TAG_LOG, "OnErrorListener");
stop();
return false;
}
});
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
stop();
}
});
return mp;
}
If I comment the mp2.start line, then I can listen the mp1 audio. It is like when a MediaPlayer is started, any other instances are stopped I would appreciate any help with this.
I found other posts describing the same problem in Nexus 5 devices, but don't have a solution yet.
https://code.google.com/p/android/issues/detail?id=63099
https://code.google.com/p/android/issues/detail?id=62304
I tried using seekTo(0) like it was suggested in one of those forums, but it didn't work, so I tried another thing that seems like an specific workaround for my case.
I am using this inside a Service, and my second MediaPlayer is only to play some background music, so I started it half second after the first one and it worked.
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
if (mp2 != null) mp2.start();
}
},
500
);
I still don't know why I am having this problem only in the Nexus 5, but I hope this may help somebody.
I'm trying to build a game which plays some sounds effects on click & at the same time music in the background.
I tried implementing this with two MediaPlayer objects.
The first one, which served for the effects on click works great.
The second one however sometimes logs error 100, sometimes error 38. No sound at all.
Variables
private MediaPlayer mEffects;
private MediaPlayer mpSoundBackground;
Implementation of the sound media player:
mpSoundBackground = MediaPlayer.create(MainActivity.this, R.raw.soundbackground1small);
mpSoundBackground.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
Logger.d("prepared");
musicPrepared = true;
}
});
mpSoundBackground.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Logger.d("error "+what);
return false;
}
});
if (musicPrepared) {
mpSoundBackground.start();
Logger.d("music is prepared");
} else {
Logger.d("music is not prepared");
}
Implementation of the effects Media Player:
stopPlaying();
mEffects= MediaPlayer.create(MainActivity.this, R.raw.soundhit);
mEffects.start();
private void stopPlaying() {
if (mEffects!= null) {
mEffects.stop();
mEffects.release();
mEffects= null;
}
}
Update
To add to the confusion: It does seem to work in emulator
(Genymotion), but does not work on my OnePlus One, running Lollipop
You need to use the setOnPreparedListener method for both players. also if you want to play a sound on clicks consider using SoundPool.
Also in the public void onPrepared(MediaPlayer mp) method, you can use mp.start there is no need for that flag, since you can not know for sure that it is prepared once you reach that prepared flag
I couldn't make the errors go away, until I reconverted my soundfile to MP3.
Now it plays both on device & simulator without any problems.
Moral of this story: if you are running into errors, try a few encodings of the same file (possibly a few file sizes too!), it might be the solution.
I want to play a notification sound and my problem it that the sound loops forever, when it should sound only once.
I've tried two ways:
notification.sound = Uri.parse("content://media/internal/audio/media/38");
and
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
mMediaPlayer.setDataSource(this, Uri.parse("content://media/internal/audio/media/38"));
mMediaPlayer.setLooping(false);
mMediaPlayer.prepare();
mMediaPlayer.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
Log.v(Utils.TAG, "onprepared");
mp.start();
}
});
mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
Log.v(Utils.TAG, "end, we should release");
mp.stop();
mp.release();
}
});
In the second case, I never see the trace "end, we should release", the audio is played over and over and over again.
Any idea?
Thank you very much
UPDATE:
I've tried two devices and:
It loops forever on a Galaxy Nexus with ICS 4.0.4
It works fine on a HTC Hero 2.2.1
There are sounds with "built-in" loops which will play for ever. This is different to setting the MediaPlayer to looping. If you start playing a sound with a built-in loop, it will never finish. These are mostly ring tones (as opposed to alarm tones or notification tones). You can set the RingtoneManager to return only notification tones or alarm tones with myringtonemanager.setType(RingtoneManager.TYPE_ALARM|RingtoneManager.TYPE_NOTIFICATION)
which will exclude most looping sounds, but unfortunaley this is not guaranteed to exclude them all on any device. :-(
Therefore the solution of Tiago Almeida is a good work-around (and i've voted it up) though it will also truncate all sounds which have just a few (and no infinite) loops.
Try this:
try {
mp.setDataSource(uri.toString());
mp.setAudioStreamType(AudioManager.STREAM_ALARM);
mp.prepare();
mp.start();
mp.setOnSeekCompleteListener(new OnSeekCompleteListener() {
public void onSeekComplete(MediaPlayer mp) {
mp.stop();
mp.release();
}
});
} catch (Exception e) {
e.printStackTrace();
}
One more workaround for this problem
boolean soundPlayedOnce = true;
if(soundPlayedOnce){
mp.start();
soundPlayedOnce = false;
}
set this boolean to true right before you want to play sound
I have a game in which a sound plays when a level is completed. Everything works fine to start with but after repeating a level 10 or 20 times the logcat suddenly reports:
"MediaPlayer error (-19,0)" and/or "MediaPlayer start called in state 0" and the sounds are no longer made.
I originally had the all sounds in mp3 format but, after reading that ogg may be more reliable, I converted them all to ogg, but the errors appeared just the same.
Any idea how I can fix this problem?
I was getting the same problem, I solved it by adding the following code to release the player:
mp1 = MediaPlayer.create(sound.this, R.raw.pan1);
mp1.start();
mp1.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
};
});
I think you are not releasing the mediaplayers you are using to play the sound..
You need to release() the media players otherwise the resources are not released , and you soon get out of memory (since you allocate them again next time). so,I think you can play twice or even thrice... but not many times without releasing the resources
MediaPlayer is not a good option when you are playing small sound effects as the user can click on multiple buttons very soon and you will have to create a MP object for all of them which doesnt happen synchronously. That is why you are not hearing sounds for every click. Go for the SoundPool Class which allows you to keep smaller sounds loaded in memory and you can play them any time you want without any lag which you would feel in a mediaplayer. http://developer.android.com/reference/android/media/SoundPool.html Here is a nice tutorial : http://www.anddev.org/using_soundpool_instead_of_mediaplayer-t3115.html
I solved both the errors (-19,0) and (-38,0) , by creating a new object of MediaPlayer every time before playing and releasing it after that.
Before :
void play(int resourceID) {
if (getActivity() != null) {
//Using the same object - Problem persists
player = MediaPlayer.create(getActivity(), resourceID);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
player.release();
}
});
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
}
}
After:
void play(int resourceID) {
if (getActivity() != null) {
//Problem Solved
//Creating new MediaPlayer object every time and releasing it after completion
final MediaPlayer player = MediaPlayer.create(getActivity(), resourceID);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
player.release();
}
});
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
}
}
This is a very old question, But this came up first in my search results So other people with the same issue will probably come upon this page eventually.
Unlike what some others have said, you can in fact use MediaPlayer for small sounds without using a lot of memory. I'll put in a little modified snippit from my soundboard app to show you what I'm getting at.
private MediaPlayer mp;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
mp = new MediaPlayer();
}
private void playSound(int soundID){
mp.reset();
AssetFileDescriptor sound = getResources().openRawResourceFd(soundID);
try {
mp.setDataSource(sound.getFileDescriptor(),sound.getStartOffset(),sound.getLength());
mp.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mp.start();
}
with the way I set it up, you create on MediaPlayer object that you reuse everytime you play a sound so that you don't use up too much space.
You call .reset() instead of .release() because .release() is only used if you are disposing of an object, however you want to keep your MediaPlayer Object.
You use an assetfiledescriptor to set a new soundfile for your mediaplayer to play instead of setting a new object to your mediaplayer address because that way you are creating new objects within the method that aren't being handled properly and you will eventually run into the same error as you described.
This is only one of many ways to use MediaPlayer but I personally think it is the most efficient if you are only using it for small sound applications. The only issue with it is that it is relatively restrictive in what you can accomplish, but that shouldn't be much of an issue if you are indeed using it for small sound applications.
i try delete emulator and new create emulator for remove error of (-19,0) media player.
I have an application with a VideoView, in order to make the video play on a loop I use an onCompletionListner to call setVideoPath() again, like this:
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer arg0) {
mVideoView.start();
}
});
mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
//I have a log statment here, so I can see that it is making it this far.
mp.reset(); // <--- I added this recently to try to fix the problem
mVideoView.setVideoPath(file.getAbsolutePath());
}
});
This setup works well on all devices I've come across so far, I never had any trouble with it not repeating.
However the Motorola Xoom that I am testing on was recently upgraded to ICS. Now that it is on ICS this will work for a while and loop the video. But eventually (I've added a counter and some Logs, there does not appear to be any pattern to how many times it successfully loops before stopping) it will quit looping and just sit on a freeze frame of the first frame in the movie.
Does anyone know what could cause this not to loop properly any more? OR does anyone know of another way to get a VideoView to loop properly that does work under ICS still?
If you have only one video to play you can setLooping(true) in your on prepared listener.
myVideoView.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.setLooping(true);
}
});
and you're done.
So far this:
mp.reset();
inside the onComplete callback seems to fix it. Would be very interested if anyone can explain what is going on with it.