我的应用程序似乎工作正常,但我收到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 警告。