【问题标题】:How do I release my media player after it is done playing?播放完成后如何释放我的媒体播放器?
【发布时间】:2013-12-24 02:59:16
【问题描述】:

我正在创建一个音板,单击大约 30 种不同的声音后它停止工作;我相信android内存不足。下面是我的代码。如何实现 .release() 以便在播放完声音后释放它?我真的不在乎两件事是否同时播放。为了实现这一点,剪辑太短了。我只想得到我的代码集。

public class soundPageOne extends Activity {
    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        setContentView(R.layout.soundsone);

        final MediaPlayer pg1 = MediaPlayer.create(this, R.raw.peter1);
        Button playSound1 = (Button) this.findViewById(R.id.peter1Button);

        playSound1.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                pg1.start();

        }
    });

我已经做了很多搜索,但由于我缺乏 java/android 知识,我无法得到任何工作。在此先感谢,如果有人需要更多代码,请告诉我。

【问题讨论】:

  • 试试这个方法onCompletion(MediaPlayer mp)在音频完成时很有帮助
  • 是的,我目前正在尝试。当我将它与 mp.release() 一起使用并尝试重播按钮时,类崩溃。有什么想法吗? @Sanket990
  • 实际上 mp.release() 意味着您正在释放媒体播放器对象。你不能重新开始(mp.play())调用播放。
  • 你可以在再次成为对象 mp.prepare() 和 mp.start() 之后应用 oncompletion -onstop() 方法
  • 在 onCompletion() 中设置所有下面的东西添加下面的方法 mp.reset(); mp.setDataSource(MEDIA_PATH); mp.prepare(); mp.start();

标签: java android release android-mediaplayer


【解决方案1】:

我发表了评论,但无论如何我都会发布一个答案来说明我的意思......

这个想法是您可以使用一定数量的MediaPlayer 实例。这样,您永远不会超过最大实例数。该数组应该是您希望能够听到的并发声音数量的长度。如果声音是本地文件,则准备声音所需的时间几乎可以忽略不计,因此在点击处理程序中调用create 不会导致糟糕的性能。我想你的每个按钮都与一个特定的资源相关联,所以我设置了一个辅助方法来以相同的方式为每个按钮创建和播放声音。

public class soundPageOne extends Activity {

    private MediaPlayer[] mPlayers = new MediaPlayer[2];
    private int mNextPlayer = 0;

    @Override
    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        setContentView(R.layout.soundsone);
        Button playSound1 = (Button)this.findViewById(R.id.peter1Button);
        playSound1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startSound(R.raw.peter1);
            }
        });
    }

    public void onDestroy() {
        super.onDestroy(); // <---------------------- This needed to be there
        for (int i = 0; i < mPlayers.length; ++i)
            if (mPlayers[i] != null)
                try {
                    mPlayers[i].release();
                    mPlayers[i] = null;
                }
                catch (Exception ex) {
                    // handle...
                }
    }

    private void startSound(int id) {
        try {
            if (mPlayers[mNextPlayer] != null) {
                mPlayers[mNextPlayer].release();
                mPlayers[mNextPlayer] = null;
            }
            mPlayers[mNextPlayer] = MediaPlayer.create(this, id);
            mPlayers[mNextPlayer].start();
        }
        catch (Exception ex) {
            // handle
        }
        finally {
            ++mNextPlayer;
            mNextPlayer %= mPlayers.length;
        }
    }

}

【讨论】:

  • 必须要有onDestory()方法吗?似乎每当我点击后退按钮返回菜单时,应用程序就会崩溃,并且它与 ondestroy 有关(“没有调用 super.ondestroy”)
  • 已修复。是的,你应该拥有它。
  • 它到底在做什么?我能够让应用程序在没有它的情况下正常运行并且没有任何问题。我知道当当前页面被销毁时它正在做某事,但我不明白它为什么重要
  • 它只是在应用程序被销毁时清理分配的资源。这些资源与 MediaPlayerService 一起使用,因此不应完全泄露,但最好在不再需要时自行解除分配。
【解决方案2】:

创建一个类,比如AudioPlayerSoundPool 变量。设置一个构造函数来初始化AudioPlayer 对象并创建一个Play 方法。 SoundPool 更适合播放多次的短声音,并且不需要您释放。

public class AudioPlayer {

    private SoundPool sPool = new SoundPool(Integer.MAX_VALUE, AudioManager.STREAM_MUSIC, 0);

    public AudioPlayer(Context c, int id){  
        sounds.put("1",sPool.load(c, id, 1));   
    }

    public void play(Context c) {
        sPool.play("1", 1, 1, 1, 0, 1f);
    }
}

所以你的班级应该是这样的

public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
    super.onCreate(savedState);
    setContentView(R.layout.soundsone);

    final AudioPlayer ap = new AudioPlayer(this, R.raw.sound);
    Button playSound1 = (Button) this.findViewById(R.id.peter1Button);

    playSound1.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            ap.play();

    }
});

【讨论】:

  • 那么我是否要为每个文件设置两个单独的 java 文件?
  • 另外,这并不能真正回答我的问题。我不是想成为一个混蛋,这只是我的知识,我不知道如何设置它,这就是为什么我只是要求一种方法来释放我当前的媒体播放器,因为我已经有 180 个使用媒体播放器编程的按钮。如果我找不到原始问题的答案,我可能会尝试一下您的代码。不过谢谢,我真的很感激。
  • 是的 2 个 java 文件。您的原始文件和一个新的 AudioPlayer 文件。这是一种更清洁、更有效的声音播放方式,我建议使用它。但是,我发布了另一个更符合您正在寻找的答案
【解决方案3】:

你能用MediaPlayer.OnCompletionListener吗?

类似:

public class soundPageOne extends Activity implements MediaPlayer.OnCompletionListener {
    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        setContentView(R.layout.soundsone);
        final MediaPlayer pg1 = MediaPlayer.create(this, R.raw.peter1);

        //***set the listener here***
        pg1.setOnCompletionListener(this);

        Button playSound1 = (Button) this.findViewById(R.id.peter1Button);

        playSound1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                pg1.start();
            }   
        });
    }

    //***this code will be executed once the sound finishes playing***
    @Override
    public void onCompletion(MediaPlayer mp) {
        //log messages, other things can go here
        mp.release();
    }

【讨论】:

  • 我不确定;我非常缺乏经验。我会在哪里尝试将其放在我的代码中?什么是“...”?
  • ... 用于在媒体播放器完成时您想要执行的任何其他代码(可能是日志消息?)。我将编辑我的答案以充实代码...
  • 我认为这就是它的用途。我真的不想做任何其他事情(至少我不认为我会这样做)。我只是厌倦了让媒体播放器超载我的应用程序,我需要一种方法来结束它们。但是,是的,我只是不知道将其放在我的代码中的哪个位置,或者在其中更改什么,或者是否有必要对所有按钮重复。抱歉无知,感谢所有帮助@psyren89
  • 好的,这样就可以了,但是一旦我尝试再次播放该按钮,它就会使 soundPageOne 类崩溃。我试图在发布后重置,但这不起作用。有任何想法吗? @psyren89
  • 将您的媒体播放器创建代码(最终的 MediaPlayer pg1... 和 pg1.setOnCompletion...)移动到 onClick() 方法中。
【解决方案4】:

试试这样的

您的活动课程:

public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
    super.onCreate(savedState);
    setContentView(R.layout.soundsone);

    final AudioPlayer pg1 = new AudioPlayer();
    Button playSound1 = (Button) this.findViewById(R.id.peter1Button);

    playSound1.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            pg1.play(this, R.raw.sound);

    }
});

}

这是另一个 Java 类:

public class AudioPlayer {

private MediaPlayer mPlayer;

public void stop() {
    if (mPlayer != null) {
        mPlayer.release();
        mPlayer = null;
    }
}

public void play(Context c, int sound) {

    stop();

    mPlayer = MediaPlayer.create(c, sound);

    mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        public void onCompletion(MediaPlayer mp) {
            stop();
        }
    });

    mPlayer.start();
}

public boolean isPlaying() {
    return mPlayer != null;
}

}

【讨论】:

  • 您的其他答案要好得多。这个看起来总是会崩溃。 pg1 设置为null,然后你调用start。可能缺少一些中间代码?
  • 干杯伙伴,改变它
猜你喜欢
  • 2012-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多