MediaPlayer - 声音停止播放

MediaPlayer - Sounds Stop Playing

我正在创建一个 class 加载一些声音。但是,isPlaying 会在一段时间后继续抛出异常,然后永久停止播放该特定声音,而其他声音继续正常播放。

public class MySound {
   int m_IdMyId;
   int m_ResId;
   boolean m_IsLoaded;
   MediaPlayer m_Media;

   public MySound(int idMyId, int resId){
       m_IdMyId = idMyId;
       m_ResId = resId;
       m_IsLoaded = false;
       m_Media = null;
   }
}

这里m_IdMyId只是我游戏的一个id。 m_ResId 类似于 R.raw.mysound1m_IsLoaded 我认为在同步加载时会自动设置为 truem_MediaMediaPlayer 对象。

我经常打电话给 stop(),因为这是一场比赛,我需要每隔一秒左右检查一次,以确保某些声音已停止。正是在这里,它在调用 snd.m_Media.isPlaying() 时抛出异常。

我似乎无法访问 e 以查看错误是什么。

我也想知道如何正确设置 m_IsLoaded。我如何知道声音何时已完全加载并可以使用?

这是我的管理class:

public class MySoundManager {
    MainActivity m_Context;
    ArrayList<MySound> mySounds;

    public MySoundManager(MainActivity context) {
        m_Context = context;
        mySounds = new ArrayList<MySound>();
        mySounds.add(new MySound(8, R.raw.mysound1));
        mySounds.add(new MySound(10, R.raw.mysound2));
        mySounds.add(new MySound(22, R.raw.mysound3));
        mySounds.add(new MySound(100, R.raw.click));
        mySounds.add(new MySound(101, R.raw.error));

       for(MySound mysound : mySounds) {
           mysound.m_Media = MediaPlayer.create(m_Context, mysound.m_ResId); // no need to call prepare(); create() does that for you
           mysound.m_IsLoaded = true;
        }
    }

    // I call this when the main thread calls onResume
    public void onResume(){
        for(MySound mysound : mySounds) {
            if(mysound.m_Media == null) {
                mysound.m_Media = MediaPlayer.create(m_Context, mysound.m_ResId); // no need to call prepare(); create() does that for you
                mysound.m_IsLoaded = true;
            }
        }
    }

    // I call this when the main thread calls onPause
    public void onPause(){
        for(MySound mysound : mySounds) {
            if(mysound.m_Media != null) {
                mysound.m_Media.stop();
                mysound.m_Media.release();
                mysound.m_Media = null;
            }
        }
    }

    public boolean IsAllLoaded(){
        for(MySound mysound : mySounds) {
            if(!mysound.m_IsLoaded) return false;
        }
        return true;
    }

    public MySound FindMySoundByIdMyId(int idMyId){
        try {
            for(MySound mysound : mySounds) {
                if (mysound.m_IdMyId == idMyId) return mysound;
            }
        }catch(Exception e) {
            MySound snd;
            snd = null; // ToDo
        }
        return null;
    }

    public void play(int idMyId){
        MySound snd;
        try{
            if((snd = FindMySoundByIdMyId(idMyId)) != null)
                snd.m_Media.start();
        }catch(IllegalStateException e) {
            snd = null; // ToDo
        }
    }

    public void pause(int idMyId){
        MySound snd;
        try{
            if((snd = FindMySoundByIdMyId(idMyId)) != null &&
                    snd.m_Media.isPlaying())
               snd.m_Media.pause();
        }catch(IllegalStateException e) {
            snd = null; // ToDo
        }
    }

    public void pauseAll(){
        try{
            for (MySound mysound : mySounds) {
                if(mysound.m_Media.isPlaying())
                    mysound.m_Media.pause();
            }
        }catch(IllegalStateException e) {
            MySound snd;
            snd = null; // ToDo
        }
    }

    public boolean isPlaying(int idMyId, MySound[] fill){
        MySound snd;

        fill[0] = null;
        try{
            if((snd = FindMySoundByIdMyId(idMyId)) != null){
                fill[0] = snd;
                return snd.m_Media.isPlaying();
            }
        }catch(IllegalStateException e) {
            snd = null; // ToDo
        }
        return false;
    }

    public void stop(int idMyId){
        MySound snd;
        try{
            if((snd = FindMySoundByIdMyId(idMyId)) != null &&
                    snd.m_Media.isPlaying())
                snd.m_Media.stop();
        }catch(IllegalStateException e) {
            snd = null; // ToDo
        }
    }

    // The str is in the format
    // number id, 1 = on 0 = off,dont play if this id playing;
    public void PlaySound(String str) {
        boolean isplaying;
        int i, len, id, idDontPlay, milliNow;
        String[] strARR = str.split(";");
        String[] strARR2;
        Integer[] tmpIntARR;
        ArrayList<Integer[]> onARR = new ArrayList<Integer[]>();
        ArrayList<Integer> offARR = new ArrayList<Integer>();
        MySound snd;

        for (i = 0, len = strARR.length; i < len; i++) {
            if(strARR[i].length() <= 0) continue;
            if((strARR2 = strARR[i].split(",")) != null &&
                strARR2.length >= 3 &&
                strARR2[0].length() > 0 &&
                strARR2[1].length() > 0 &&
                strARR2[2].length() > 0){
                id = Integer.parseInt(strARR2[0]);
                idDontPlay = Integer.parseInt(strARR2[2]);
                tmpIntARR = new Integer[2];
                tmpIntARR[0] = id;
                tmpIntARR[1] = idDontPlay;
                if(Integer.parseInt(strARR2[1]) == 1){
                    onARR.add(tmpIntARR);
                } else offARR.add(id);
            }
        }

        // Turn off all sounds that need to be turned off
        for (i=0,len=offARR.size();i<len;i++) {
           id = offARR.get(i);
           stop(id);
        }

        // Turn all sounds that need to be turned on,
        // but only if the sound that blocks a new sound is not playing
        for (i=0,len=onARR.size();i<len;i++) {
            tmpIntARR = onARR.get(i);
            id = tmpIntARR[0];
            idDontPlay = tmpIntARR[1];

            // We dont play if the idDontPlay sound is already playing
            if((snd = FindMySoundByIdMyId(idDontPlay)) != null &&
                    snd.m_Media.isPlaying())
                continue;
            if((snd = FindMySoundByIdMyId(id)) != null){
                isplaying = snd.m_Media.isPlaying();
                milliNow = snd.m_Media.getCurrentPosition();
                if(milliNow > (snd.m_Media.getDuration() - 1000) ||
                    (!isplaying && milliNow > 0)){
                    snd.m_Media.seekTo(0); // Half a second inside
                }

                if(!isplaying) snd.m_Media.start();
            }
        }
    }
}

为每个声音创建一个 MediaPlayer 实例并不是获得低延迟的好做法,尤其是对于短片。 MediaPlayer 适用于较长的剪辑,例如它使用大缓冲区的音乐文件,因此,较大的缓冲区意味着高延迟。还有AudioFocus mechanism on Android that may interfere your sound playing session. So, I strongly recommend you to use SoundPool播放游戏音效等短片