【发布时间】:2013-10-01 00:01:35
【问题描述】:
我的应用程序似乎运行良好,但我收到了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 中的文件/原始文件夹。以下是我可以添加的内容:
- 生成警告的文件位于 res/raw 文件夹中。
- 如果我将文件(.ogg 并且还使用 .wav 测试过)移动到 assets 文件夹并从那里播放它们, MediaPlayer 不会产生任何警告。
- 我将 res/raw 中的一些文件替换为 .mp3、.wav 和 .mp4 音频文件,它们都生成警告,就像原始文件一样 .ogg 文件。
- 我成功播放了 SD 卡中的 .mp3、.wav 和 .mp4 文件,但它们没有 生成 MediaPlayer 警告。
- 澄清:所有文件都可以正常播放,没有任何问题 用户视角。我想弄清楚为什么 MediaPlayer 为 res/raw 中的音频文件生成警告。
看起来问题与 MediaPlayer 如何处理 res/raw 文件夹中的资源有关,但我不知道“问题”是什么或它为什么会生成 MediaPlayer 警告。
【问题讨论】:
-
有没有理由先调用reset然后release,我很确定你只是想用release?
-
对于不同的设备,这将有不同的工作方式,因为媒体播放器只是原生 OEM 的包装器,而原生服务完全依赖于设备。同样的事情也适用于相机。即使您修复了托管代码以删除这些警告,它们也可能出现在另一台设备上
-
@RSenApps 感谢您的评论。我想说如果我只是调用 release() 而之前没有调用 reset() 的话,我曾经遇到过一些问题,但我不记得了。无论如何,我认为在 release() 之前调用 reset() 并没有什么坏处,因为 reset() 将 MediaPlayer 设置为未初始化状态,并且 release() 释放与引用的 MediaPlayer 对象关联的资源。但是,你说得对,developer guide 表示你真的只需要释放然后设置为null。
-
@PulkitSethi,谢谢。我用相同的代码测试了三台设备(GS3 (4.1.2)、Xoom (CM 4.2.2) 和 Nexus 7 2012 (4.3)),它们都产生完全相同的结果/警告。我不确定我是否真的可以做任何其他事情来“修复”我的代码,所以我想我将不得不忍受这些警告并将其归结为可以安全忽略的警告。
-
我也很沮丧,这似乎是一个类似的问题。还使用 FragmentStatePagerAdapter 的片段和 ViewPager。目前我只收到针对一种特定 ogg 音效的这些警告,我有几个。我已经尝试了释放和重置的所有组合。我收到警告,因为声音不是在完成时才开始。将 on completionListener 与 release 一起使用没有任何区别。我可以忽略警告吗?
标签: android android-mediaplayer