Android Media player 保留应用程序实例并导致内存泄漏

标签 android memory-leaks android-mediaplayer leakcanary

我有一个将媒体播放器作为成员变量的 Activity 。

我的媒体播放器是这样初始化的:

mMediaPlayer = new MediaPlayer(); 
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setDataSource(MyActivity.this, URL); 
mMediaPlayer.prepareAsync(); 
//i set a on Prepared Listener to start playing on Prepared

一切正常,然后我覆盖我的 Activity onStop 方法以释放媒体播放器。

if(mMediaPlayer!=null){
   if(mMediaPlayer.isPlaying()){
       mMediaPlayer.stop();
   }
   mMediaPlayer.release();
   mMediaPlayer=null;
}

但是在 Activity 停止后,我从 LeakCanary 收到了内存泄漏报告。

报告是这样的:

MyApp.Instance->

MyApp.mLoadedApk->

LoadedApk.mReceivers->

ArrayMap.mArray->

arrayObject[].[3]->

ArrayMap.mArray->

arrayObject[][0]->

MediaPlayer.mProxyReceiver->

MediaPlayer.mProxyContext->

leaks MyActivity instance.

MyApp.Instance->

MyApp.mLoadedApk->

LoadedApk.mReceivers->

ArrayMap.mArray->

arrayObject[].[3]->

ArrayMap.mArray->

arrayObject[][0]->

MediaPlayer.mProxyReceiver->

MediaPlayer.mProxyContext->

leaks MyActivity instance.

是的,我有一个扩展应用程序的 MyApp 类,我在静态字段中持有对 MyApp 实例的引用,但我从未在我的 Activity 中使用该引用,我该如何解决此泄漏?

[编辑]

这是我的 Activity 代码:

public class PlayActivity extends ActionBarActivity {

private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_play);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
protected void onStop() {
    super.onStop();
    if(mediaPlayer!=null){
        if(mediaPlayer.isPlaying()){
            mediaPlayer.stop();
        }
        mediaPlayer.release();
        mediaPlayer=null;
    }
}

public void playIt(View view){
    if(mediaPlayer==null){
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.start();
            }
        });


    }
    if(!mediaPlayer.isPlaying()){
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        try {
            mediaPlayer.setDataSource(PlayActivity.this, Uri.parse("http://www.noiseaddicts.com/samples_1w72b820/142.mp3"));
            mediaPlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }



   }

 }

最佳答案

在我的测试中,我发现这种情况发生在 HTTP 流式传输期间。

当我在目标上检查 MediaPlayer 的源代码时(在我的例子中是 API19),确实有一个 StreamProxy 实例被设置和分配,但没有在 release 方法中释放,但只有在 reset 方法中。

这对我有用:

if (mediaPlayer != null) {
    mediaPlayer.reset();
    mediaPlayer.release();
    mediaPlayer = null;
}

关于Android Media player 保留应用程序实例并导致内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33221516/

相关文章:

c# - 在运行时将网格转换为 STL/obj/fbx

android - 如何在android中的同一个 Activity 中打开三个html页面

c++ - 如何在源代码中查找内存泄漏

c - blkid_get_cache 似乎泄漏内存

OpenGL GPU内存清理,需要吗?

java - 查看当前正在播放的音乐 [Android]

android - 如何从android URI获取绝对音频路径

android - 文件不从 Android 中的内部存储播放

android - 当应用程序在后台时,React Native 处理套接字连接的事件?

android - Broadcast Receiver 类和 registerReceiver 方法