How to make media player stop when pressing device back button from a fragment back to activity

半腔热情 提交于 2021-02-17 06:21:25

问题


My problem is that media player keeps playing when i press device back button. How to completely destroy the fragment and the media player and everything in it when pressing device back button so that it is not visible on the screen?

I'm new to programming so all advice and comments on how to improve the code are welcome. Thank you

Activity:

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    Button button1;
    Button button2;
    Button button3;

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

        setContentView(R.layout.activity_main);

        button1 = findViewById(R.id.button1);
        button2 = findViewById(R.id.button2);
        button3 = findViewById(R.id.button3);

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FragmentManager fm= getSupportFragmentManager();
                fragment1 fragment = new fragment1();
                fm.beginTransaction()
                        .replace(R.id.container,fragment)
                        .addToBackStack(null)
                        .commit();
            }
        });

        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FragmentManager fm= getSupportFragmentManager();
                fragment2 fragment= new fragment2();
                fm.beginTransaction()
                        .replace(R.id.container,fragment)
                        .addToBackStack(null)
                        .commit();
            }
        });

        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FragmentManager fm= getSupportFragmentManager();
                fragment3 fragment= new fragment3();
                fm.beginTransaction()
                        .replace(R.id.container,fragment)
                        .addToBackStack(null)
                        .commit();
            }
        });
    }
}

Fragment:

import androidx.fragment.app.Fragment;
import android.media.MediaPlayer;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.Button;
import android.os.Bundle;
import android.widget.SeekBar;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.TextView;
import java.io.IOException;

public class fragment1 extends Fragment {

    MediaPlayer mp;
    Button play;
    SeekBar seekBar;
    TextView elapsedTimeLabel;
    TextView remainingTimeLabel;
    int totalTime;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_fragment1, container, false);

        final MediaPlayer mp = new MediaPlayer();
        try {
            mp.setDataSource("https://firebasestorage.googleapis.com...");
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            mp.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }

        final Button play = rootView.findViewById(R.id.play);
        elapsedTimeLabel = rootView.findViewById(R.id.elapsedTimeLabel);
        remainingTimeLabel = rootView.findViewById(R.id.remainingTimeLabel);
        totalTime = mp.getDuration();
        mp.seekTo(0);
        seekBar = rootView.findViewById(R.id.seekBar);
        seekBar.setMax(totalTime);
        seekBar.setOnSeekBarChangeListener

                (new SeekBar.OnSeekBarChangeListener() {
                     @Override
                     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                         if (fromUser) {
                             mp.seekTo(progress);
                             seekBar.setProgress(progress);
                         }
                     }
                     @Override
                     public void onStartTrackingTouch(SeekBar seekBar) {
                     }
                     @Override
                     public void onStopTrackingTouch(SeekBar seekBar) {
                     }
                 }
                );

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (mp != null) {
                    try {
                        Message msg = new Message();
                        msg.what = mp.getCurrentPosition();
                        handler.sendMessage(msg);
                        Thread.sleep(1000);
                    } catch (InterruptedException ignored) {
                    }
                }
            }
        }).start();

        mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

            public void onCompletion(MediaPlayer sound) {

                play.setBackgroundResource(R.drawable.play);
            }
        });

        play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mp.isPlaying()) {
                    mp.pause();
                    play.setBackgroundResource(R.drawable.play);

                } else {

                    mp.start();
                    play.setBackgroundResource(R.drawable.pause);
                }

            }

        });

        return rootView;
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int currentPosition = msg.what;
            seekBar.setProgress(currentPosition);

            String elapsedTime = createTimeLabel(currentPosition);
            elapsedTimeLabel.setText(elapsedTime);

            String remainingTime;
            remainingTime = createTimeLabel(totalTime - currentPosition);
            remainingTimeLabel.setText("-" + remainingTime);
        }
    };

    public String createTimeLabel(int time) {
        String timelabel;
        int min = time / 1000 / 60;
        int sec = time / 1000 % 60;

        timelabel = min + ":";
        if (sec < 10) timelabel += "0";
        timelabel += sec;
        return timelabel;

    }


    public void play(View view) {
        if (mp == null) {
            mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    stopPlayer();
                }
            });
        }

        mp.start();
    }

    public void pause(View view) {
        if (mp != null) {
            mp.pause();
        }
    }

    private void stopPlayer() {
        if (mp != null) {
            mp.release();
            mp = null;

        }
    }
}

EDIT:

I tried the provided solutions but somehow the mediaplayer in the fragment doesnt get destroyed. When I go back to the fragment the seekbar in it is reset but the audio file is still playing. When I press play again it starts to play again on top of the previous one so that theres 2 files playing on the same time


回答1:


Each Fragment has an onDestroy() callback for when the fragment is popped off the back stack and destroyed. You can call your stopPlayer() from that method.

@Override
public void onDestroy() {
    super.onDestroy();
    stopPlayer();
}



回答2:


Unfortunately, there is no direct way to do that Since the fragment doesn't have an onBackPressed() method, you will have to make a callback and implement it in the fragment to make it work.

First, you need to create an interface and class which implements its interface to have a generic method

  1. Create class interface OnBackPressedListener

OnBackPressedListener.java

public interface OnBackPressedListener {
    void goBack();
}
  1. in your MainActivity Create the listener and make a setter for it and use it inside the onBackPressed() method after overriding it.

Your MainActivity should be something like this

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private OnBackPressedListener onBackPressedListener;

    public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
        this.onBackPressedListener = onBackPressedListener;
    }
    
    @Override
    public void onBackPressed() {
        if (onBackPressedListener != null){
            onBackPressedListener.goBack();
        }
        super.onBackPressed();
    }
}
  1. In the Fragment you should implement the OnBackPressedListener` interface and use it to stop the player

Fragment1.java

public class fragment1 extends Fragment implements OnBackPressedListener {
    
    @Override
    public void goBack() {
        stopPlayer();
    }
}

Side note

  • Consider refactoring your fragment1 name to be Fragment1 with uppercased F



回答3:


@Override
public void onDestroy() {
    stopPlayer();
    super.onDestroy();
}

In Fragment, override the OnDestroy function. and stop the player before calling super.onDestroy()



来源:https://stackoverflow.com/questions/64201460/how-to-make-media-player-stop-when-pressing-device-back-button-from-a-fragment-b

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!