2

我的应用程序似乎工作正常,但我收到MediaPlayer finalized without being released警告,我不确定为什么会收到警告。奇怪的是,它们只在我MediaPlayer.create(ctxt, resid)用来播放资源文件 (.ogg) 时出现,而不是在我setDataSource(path)用来播放 SD 卡中的文件时出现。

我查看了 Stack Overflow 上的许多其他帖子,查看了开发人员文档,并尝试了不同的组合(太多无法列出),但似乎没有什么能摆脱错误。不知道这是一个错误还是我正在做的事情。

我正在使用带有 FragmentStatePagerAdapter 的 ViewPager,基本上,当您点击页面时,它会播放声音。当您滑动到下一页时,它会停止播放声音(如果仍在播放)。这是该部分的代码,但我在测试期间已将其删除,它似乎没有什么不同,但我想我会包括它以防万一:

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

这是片段的相关代码:

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();
}

同样,上述工作正常,似乎没有引起任何问题。如果我在一个页面上并点击它几次,它会开始播放声音,然后随着每次新的点击停止/播放。看起来当它破坏页面然后 GC 运行时会出现警告。每次播放音频文件时都会出现一个警告。

我想知道为什么MediaPlayer finalized without being released只有在播放资源文件而不是从 SD 卡播放文件时才会收到警告。据我所知,它应该始终在 GC 之前完成。有任何想法吗?

更新:我又做了一些测试,试图看看我是否能查明发生了什么“奇怪”的事情,但我唯一能真正看到的是它只影响 res/raw 文件夹中的文件。这是我可以添加的内容:

  • 生成警告的文件位于 res/raw 文件夹中。
  • 如果我将文件(.ogg 和 .wav 测试)移动到资产文件夹并从那里播放,MediaPlayer 不会生成任何警告。
  • 我用 .mp3、.wav 和 .mp4 音频文件替换了 res/raw 中的一些文件,它们都生成了警告,就像原始 .ogg 文件一样。
  • 我成功播放了 SD 卡中的 .mp3、.wav 和 .mp4 文件,但它们没有生成 MediaPlayer 警告。
  • 澄清一下:从用户的角度来看,所有文件都可以正常播放,没有任何问题。我想弄清楚的是为什么 MediaPlayer 会为 res/raw 中的音频文件生成警告。

看起来问题与 MediaPlayer 如何处理 res/raw 文件夹中的资源有关,但我不知道“问题”是什么或它为什么会生成 MediaPlayer 警告。

4

1 回答 1

1

不使用时释放媒体播放器mp.release();。它会解决你的问题。

例如。

mp.setOnCompletionListener(new OnCompletionListener() {
    public void onCompletion(MediaPlayer mp) {    
        mp.release();
    }
});
于 2015-01-07T12:58:26.790 回答