In an activity I'm using two media players for different sounds, if both sounds are played and the back button is pushed there is no problem, it works fine. the media players stop and release.(mp is set to loop, mps just plays a short sound)
#Override
protected void onPause() {
// TODO Auto-generated method stub
mp.stop();
super.onPause();
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
mp.release();
mps.release();
super.onStop();
}
But, if one and/or both sounds are not played I get a forced close when the back button is pushed and a null pointer exception. How would you write code to check if the mediaplayers were ever used and therefore need to stop and release them?
If you are getting a null pointer in your onPause and onStop you need to check if mp is null.
#Override
protected void onPause() {
if (mp != null)
mp.stop();
super.onPause();
}
#Override
protected void onStop() {
if (mp != null)
mp.release();
if (mps != null)
mps.release();
super.onStop();
}
You can keep a count if you would like to but that means keeping track of another variable when you already have access to the variables you need
could you use a count and add one to it if there has been a play then check if it equals 0 or not.
Related
I have two activities a main activity which has Recyclerview and a detailedActivity which is launched every time the user clicks on one of the items of the Recyclerview. The detailedActivity has a mediaplayer component that is being created everytime a detailedActivity is created. Now in the onDestroy method I always free the resources taken by the mediaPlayer by this code:
#Override
protected void onDestroy() {
if (mMediaPlayer != null) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();}
mMediaPlayer.release();
mMediaPlayer=null;
}
super.onDestroy();
}
The app freezes for a while every time I click the back button while the mediaplayer is still preparing. The message that I get in the logcat is this:
I/Choreographer: Skipped 112 frames! The application may be doing too much work on its main thread.
So this freezing only happens if I destroyed the activity while it is preparing but if it is already in the prepared state it won't happen. I use prepreAsync to fetch the media from the internet.
Thanks. Any help is highly appreciated. I have been stuck in this problem for days!
OK. I've kind of worked around the problem. I am writing this for anyone who might encounter the same situation as I did. I made two boolean flags in the scope of the class like this:
boolean prepared = false;
boolean cancel = false;
After that in the onpreapred method I set prepared to true.
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
prepared = true;
}
});
In the onDestroy method I check whether the mediaplayer is already prepared or not if prepared I release it from the method its self.
#Override
protected void onDestroy() {
if (mMediaPlayer != null) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
}
if (prepared) {
mMediaPlayer.release();
mMediaPlayer = null;
}
cancel = true;
}
super.onDestroy();
}
Otherwise, I set cancel to true and implement on OnBufferingUpdateListener interface and override its method and release the mediaplayer from there.
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
if (cancel) {
mp.reset();
mp.release();
mMediaPlayer = null;
Log.i("msg", " mp released");
}
}
Try to remove rechecking if mediaplayer is running or not.
#Override
protected void onDestroy() {
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
}
super.onDestroy();
}
If it still happens, try to remove checking mediaplayer in your onDestroy().
-- UPDATE --
This could be related with this bug:
https://code.google.com/p/android/issues/detail?id=959
This could be a help:
Android MediaPlayer reset freezes UI
In my application I'm having a method responsible for playing file placed under raw directory. But when Ever I call that function in my onResume() method, sound is played twice. Even I have googled and tried different solutions. even by checking mediaPlayer.isPlaying() and then stopping the MediaPlayer instance but still didn't get any help.
private void EnglishSound(){
if(mediaPlayer1!=null){
if(mediaPlayer1.isPlaying()){
mediaPlayer1.stop();
}
mediaPlayer1.reset();
mediaPlayer1.release();
}
mediaPlayer1 = MediaPlayer.create(this, R.raw.p012);
mediaPlayer1.start();
}
public void onResume() {
super.onResume();
EnglishSound();
}
and EnglishSound() is called no where else in the whole activity. Even have tried debugging but it never enters the if block containing isPlaying().
Try to release onPause()
public void onPause() {
super.onPause();
if(mediaPlayer1 != null)
mediaPlayer1.release();
}
I have a button which leads to open a Preference Screen, hence I have not released Media Player object in onPause().
But this leads to problem of running background music when clicks on Home button in Android Emulator.
take variable before oncreate
boolean pref_clicked=false;
onclick of button just write pref_clicked=true;
and
#Override
public void onPause() {
// TODO Auto-generated method stub
super.onPause();
if(!pref_clicked)
//pause your music player
}
#Override
public void onStop() {
super.onStop();
//pause your music player
}
In my Activity I have the following:
private Set<MediaPlayer> mediaPlayers;
public void onSomeEventInMyActivity()
{
// play sound
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.my_sound);
mediaPlayers.add(mediaPlayer);
mediaPlayer.setOnCompletionListener(new OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
mp.release();
mediaPlayers.remove(mp);
}
});
mediaPlayer.start();
}
#Override
protected void onStart()
{
super.onStart();
mediaPlayers = new HashSet<MediaPlayer>();
}
#Override
protected void onStop()
{
super.onStop();
for (MediaPlayer mediaPlayer : mediaPlayers)
{
if (mediaPlayer.isPlaying())
{
mediaPlayer.stop();
}
mediaPlayer.release();
}
}
Is this code sufficient or will it lead to MediaPlayer leakage? Are my implementations of onStop and onStart necessary, or can I just rely on calling release in onCompletion?
I did my code this way because I assume onStop() could be called while a MediaPlayer is playing, so I need to call release because onCompletion won't be called yet. I'm just guessing that this is right, so correct me if I am wrong.
I also read that onStop is not called in low-memory situations - what to do then?
An onStop() routine is needed if the mediaPlayer is expected to stop when the activity becomes invisible. Otherwise, the mediaPlayer goes on playing. On older OSs, Gingerbread and earlier, the activity can execute onPause() - say, when a phone call arrives - and, in extreme circumstances, be destroyed without ever executing onStop(). I don't know what would happen to a running mediaPlayer then. However, if there is a phone call coming in, it might be an idea to stop the mediaPlayer in onPause()! Later OSs always pass through onStop() before destroying the Activity. Calling mp.release() on the mediaPlayer after stopping it, in either onPause() or onStop(), is correct.
It's also desirable to remove the reference to the player held in mediaPlayers, which doesn't happen in onStop() above. Something like:
#Override public void onCompletion(MediaPlayer mp) {
mp.stop(); // It's always safe to call stop()
mp.release(); // release resources internal to the MediaPlayer
mediaPlayers.remove(mp); // remove reference to MediaPlayer to allow GC
}
and then
#Override public void onPause() {
for (Object mediaPlayer : mediaPlayers.toArray()) {
onCompletion((MediaPlayer) mediaPlayer); // stop, release, and free for GC, each mp.
}
super.onPause();
}
(I originally had for (Object mediaPlayer : mediaPlayers) {} in the above code but omfeddf345mnof32nisd45fgoq2t pointed out that I would be modifying a set while iterating over it. Thanks for the correction!)
Only callback guaranted to be called is onPause(), so you may leak this media player in some situations. In case stopping player on activity pause is not acceptable you should use service, and watch for certain events ( like incoming phone call etc )
OK I got it to work. This will save the file as a ringtone, notification, or alarm based on the context menu. (Only ringtone function is shown due to space conservation)
Need help with:
For some reason no sound plays after awhile.(about 20 or so presses and won't play again until you back out of the app and launch it again) Also I've been told "/sdcard/media/etc" isn't "the correct way" to do it.
If anyone has any suggestions on how to
1.release/pause/stop the sound from playing when the home button is pressed, a text is recieved, or the back button is pressed to exit the app, etc
and
2.the correct way to get the sdcard. I'd appreciate it.
MediaPlayer mp1;
MediaPlayer mp2;
MediaPlayer mp3;
MediaPlayer mp4;
MediaPlayer mp5;
protected void onDestroy() {
super.onDestroy();
if(mp1 != null){
mp1.release();
}
if(mp2 != null){
mp2.release();
}
if(mp3 != null){
mp3.release();
}
if(mp4 != null){
mp4.release();
}
if(mp5 != null){
mp5.release();
}
}
protected void onPause() {
super.onPause();
if(mp1 != null){
mp1.stop();
}
if(mp2 != null){
mp2.stop();
}
if(mp3 != null){
mp3.stop();
}
if(mp4 != null){
mp4.stop();
}
if(mp5 != null){
mp5.stop();
}
}
}
protected void onResume() {
super.onResume();
}
Answer to Q1: Add a onPause method to your activity and call MediaPlayer's stop() method. You should also add a onDestroy method and call release to free the resources used by the mediaplayer.
Answer to Q2: Take a look at this post. For more details read the Android Developers info on Data Storage