简体   繁体   中英

MediaPlayer finalized without being released

My application seems to work fine, but I get MediaPlayer finalized without being released warnings and I'm not sure why I'm getting them. The weird thing is that they only show up when I use MediaPlayer.create(ctxt, resid) to play resource files (.ogg) and not when I use setDataSource(path) to play files from the SD card.

I've looked at a lot of the other post on Stack Overflow, check out the developer docs, and tried different combinations of things (too many to list), but nothing seems to get rid of the error. Not sure if it's a bug or something I'm doing.

I'm using a ViewPager with FragmentStatePagerAdapter and basically, when you tap on the page it plays the sound. When you swipe to the next page it stops the sound from playing (if it's still playing). Here's the code for that part, but I've removed it during tests and it doesn't seem to make a difference, but I figured I'd include it just in case:

public void stopAudioInFragment() {
    ViewPageFragment page = (ViewPageFragment)
            getSupportFragmentManager().findFragmentById(R.id.pager);
    if (page != null) {
        page.stopAudio();
    }
}

Here's the relevant code for the fragment:

public static MediaPlayer mPlayer;
private int mAudioId;
private boolean mIsAudioFile = false;

public void playAudio() {
    // Setup media player to play audio
    mIsAudioFile = false;

    stopAudio();
    mPlayer = new MediaPlayer();

    if (!mIsAudioFile && mAudioId != -1 && mPlayer != null) {
        // Play local resource audio
        mPlayer = MediaPlayer.create(mContext, mAudioId);
        mPlayer.setOnCompletionListener(new OnCompletionListener() {

            public void onCompletion(MediaPlayer mp) {
                stopAudio();
            }
        });

    } else if (mAudioId != -1 && mPlayer != null) {
        // Play audio file on SD card
        try {
            mPlayer.setDataSource(audio_file_path);
            mPlayer.setOnCompletionListener(new OnCompletionListener() {

                public void onCompletion(MediaPlayer mp) {
                    stopAudio();
                }
            });

        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            mPlayer.prepare();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    mPlayer.start();
}

public void stopAudio() {
    if (mPlayer != null) {
        if (mPlayer.isPlaying()) {
            mPlayer.stop();
        }
        mPlayer.reset(); // Might not be necessary, since release() is called right after, but it doesn't seem to hurt/cause issues
        mPlayer.release();
        mPlayer = null;
    }
}


@Override
public void onDestroy() {
    stopAudio();
    super.onDestroy();
}

Again, the above works fine and doesn't seem to cause any problems. If I'm on a page and tap it several times, it starts to play the sound and then stops/plays with each new tap. It looks like the warnings show up when it destroys the page and then GC runs. There's one warning for each time I've played the audio file.

I'd like to know why I get MediaPlayer finalized without being released warnings only when it plays resource files and not when it plays files from the SD card. As far as I can tell, it should always be finalized before it's GC'd. Any ideas?

Update: I did a few more tests to try to see if I could pinpoint anything "weird" going on, but the only thing I can really see is that it only affects files in the res/raw folder. Here's what I can add:

  • The files that are generating the warnings are in the res/raw folder.
  • If I move the files (.ogg and also tested with .wav) to the assets folder and play them from there, the MediaPlayer DOES NOT generate any warnings.
  • I replaced some of the files in res/raw with .mp3, .wav and .mp4 audio files and they ALL GENERATED WARNINGS, just like the original .ogg files did.
  • I successfully played .mp3, .wav and .mp4 files from the SD card and they DID NOT generate the MediaPlayer warnings.
  • To clarify: all files play correctly without any problems from a users perspective. What I'm trying to figure out is why the MediaPlayer generates warnings for audio files in res/raw.

Looks like the problem has to do with how the MediaPlayer handles resources in the res/raw folder, but I have no idea what the "issue" is or why it generates the MediaPlayer warnings.

Release media player when no use by mp.release(); . It will solve your problem.

For ex.

mp.setOnCompletionListener(new OnCompletionListener() {
    public void onCompletion(MediaPlayer mp) {    
        mp.release();
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM