安卓媒体播放器会保留应用实例,导致内存泄漏。

5

我是一个带有媒体播放器成员变量的活动。

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

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

一切都运行得很好,然后我重写了活动的onStop方法来释放媒体播放器。
if(mMediaPlayer!=null){
   if(mMediaPlayer.isPlaying()){
       mMediaPlayer.stop();
   }
   mMediaPlayer.release();
   mMediaPlayer=null;
}

但是在活动停止后,我从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.

我有一个扩展了Application的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();
        }

    }



   }

 }

请发布完整的类。 - leonardkraemer
@willermo,你修好了吗? - Sebastian Roth
@SebastianRoth 还没有,我的应用程序仍然因此泄漏内存。 - willermo
1个回答

4

在我的测试中,我发现这种情况发生在HTTP流媒体期间。

当我检查目标(在我的情况下是API19)上的MediaPlayer源代码时,确实设置和分配了StreamProxy实例,但只有在reset方法中而不是release方法中释放。

以下方法对我有效:

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

我已经这样做了,但仍然存在n个MediaPlayer实例。其中0 < n < 无穷大。 - John Glen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接