简体   繁体   中英

MediaPlayer won't stop playing even if programmed to

I made a simple class that handles everything related to sound. Has an add, play, stop, release and releaseAll. How it works is that you have to add a song and then call play passing the name of the song you added. Anytime you need to stop, just call the stop function and pass the song's name as parameter and it should stop. My issue is that it isn't stopping even though it goes through stop() .

Sound class:

public class Sound
{
    private Map<String, MediaPlayer> songs = new HashMap<String, MediaPlayer>();

    private MediaPlayer currentlyPlayingSong;

    public Sound() {}

    public void Add(int songId, String songName, Context context)
    {
        MediaPlayer song = MediaPlayer.create(context, songId);

        songs.put(songName, song);
    }

    public void Play(String name, boolean shouldLoop)
    {
        MediaPlayer songToPlay = songs.get(name);

        if ( songToPlay != currentlyPlayingSong && songToPlay != null) 
    {
        currentlyPlayingSong = songToPlay;

        currentlyPlayingSong.start();

        currentlyPlayingSong.setLooping(shouldLoop);
    }
    }

    public void Stop(String name)
    {
        MediaPlayer songToStop = songs.get(name);
        if (songToStop != null)
        {
            songToStop.setLooping(false);

            songToStop.stop();
        }
    }

    public void Release(String name)
    {
        songs.get(name).release();
    }

    public void ReleaseAll()
    {
       LinkedList<MediaPlayer> _songs;

        _songs = (LinkedList)songs.values();

        for (int i = 0; i < _songs.size(); i++)
        {
            _songs.get(i).release();
        }
    }
}

On the activity's OnCreate I call Add then Play . Everything is fine until I try to call Stop from a fragment. Runs without any errors or exceptions, it simply doesn't stop.

Activity:

public class Main extends ActionBarActivity
{
   private Sound sound = new Sound();

   private static boolean isSoundOn = true;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        isSoundOn = true;

        sound.Add(R.raw.drajamainmenueddited, "mainMenuSong", this);

        //endregion

        //Hide upper action bar
        getSupportActionBar().hide();

            if (isSoundOn)
                sound.Play("mainMenuSong", true);
    }


    public void SetIsSoundOn(Boolean isOn)
    {
        isSoundOn = isOn;
    }

    public boolean GetIsSoundOn()
    {
       return isSoundOn;
    }

    public Sound GetSoundObj()
    {
        return sound;
    }
}

Fragment:

public class MainMenuFragment extends Fragment {

    private ImageButton soundImgBtn;

    private FragmentConfig fragmentConfig;

    public MainMenuFragment()
    {
        fragmentConfig = new FragmentConfig();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState)
    {
        //region Initiators
        View  view = inflater.inflate(R.layout.fragment_main_menu, container, false);

        soundImgBtn = (ImageButton)view.findViewById(R.id.soundImgBtn);
        //endregion

        //region Listeners

        soundImgBtn.setOnClickListener(
                new View.OnClickListener()
                {
                    @Override
                    public void onClick(View v)
                    {
                        SoundImgBtnClick(v);
                    }
                }
        );
        //endregion

        //Changes audio img
        if (((Main)getActivity()).GetIsSoundOn())
            soundImgBtn.setImageResource(android.R.drawable.ic_lock_silent_mode_off);

        else
            soundImgBtn.setImageResource(android.R.drawable.ic_lock_silent_mode);

        // Inflate the layout for this fragment
        return view;
    }

    private void SoundImgBtnClick(View v)
    {
        //if sound is on and clicked, turn off
        if (((Main)getActivity()).GetIsSoundOn())
        {
            ((Main)getActivity()).SetIsSoundOn(false);

            ((Main)getActivity()).GetSoundObj().Stop("mainMenuSong");

            soundImgBtn.setImageResource(android.R.drawable.ic_lock_silent_mode);
        }

        else
        {
            ((Main)getActivity()).SetIsSoundOn(true);

            ((Main)getActivity()).GetSoundObj().Play("mainMenuSong", true);

            soundImgBtn.setImageResource(android.R.drawable.ic_lock_silent_mode_off);
        }
    }

}

What I'm trying to do is emulate a mute button. Once clicked all sounds should be muted.

This is pretty much all I've coded, so far.

Cheers.

I suspect you're using different instances of MediaPlayer. You are allowed to do that BUT you must stop the song within the same instance. About the code in Add():

MediaPlayer song = MediaPlayer.create(context, songId);

In Stop():

MediaPlayer songToStop = songs.get(name)

Note :

  • The above codes tell me you're using different instances of the MediaPlayer for one same song. The object song needs to be declared on a higher scope for you to access it and to stop the song.
  • Need to call release() method after stop() to free up resources.

试试 songToStop.release() 代替

Got it to stop. My class had to be able to handle one song at a time and many fx at the same time. This is what I came up with.

Sound:

public class Sound
{
    private static MediaPlayer currentlyPlayingSong,
    currentlyPlayingFX;

    public Sound() {}

    public void PlayFX(int fxId, Context context, boolean shouldLoop)
    {
        MediaPlayer fx = MediaPlayer.create(context, fxId);

        if (currentlyPlayingFX != fx)
        {
            StopFX();

            currentlyPlayingFX = fx;

            currentlyPlayingFX.start();

            currentlyPlayingFX.setLooping(shouldLoop);
        }
    }

    public void PlaySong(int songId, boolean shouldLoop, Context context)
    {
        MediaPlayer song = MediaPlayer.create(context, songId);

        if (currentlyPlayingSong != song)
        {
            StopSong();

            currentlyPlayingSong = song;

            currentlyPlayingSong.start();

            currentlyPlayingSong.setLooping(shouldLoop);
        }
    }

    public void StopFX()
    {
        if (currentlyPlayingFX != null)
        {
            currentlyPlayingFX.stop();

            currentlyPlayingFX.release();

            currentlyPlayingFX = null;
        }
    }

    public void StopSong()
    {
        if (currentlyPlayingSong != null)
        {
            currentlyPlayingSong.stop();

            currentlyPlayingSong.release();

            currentlyPlayingSong = null;
        }
    }
}

This is was based of what @The Original Android answered. Keep it on a single instance.

Thanks for the help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM