问题
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
- Create class interface
OnBackPressedListener
OnBackPressedListener.java
public interface OnBackPressedListener {
void goBack();
}
- in your
MainActivityCreate the listener and make a setter for it and use it inside theonBackPressed()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();
}
}
- In the
Fragment you should implement theOnBackPressedListener` 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
fragment1name to beFragment1with uppercasedF
回答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