英文:
How to make media player stop when pressing device back button from a fragment back to activity
问题
问题是媒体播放器在按下设备的返回按钮时仍然在播放。如何在按下设备的返回按钮时完全销毁片段、媒体播放器以及其中的所有内容,以便在屏幕上不可见?
我对编程还很陌生,所以对于如何改进代码的所有建议和评论都欢迎。谢谢!
活动(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 {
// ...(你的代码继续)
}
片段(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 {
// ...(你的代码继续)
}
编辑:
我尝试了提供的解决方案,但是某种方式片段中的媒体播放器仍然没有被销毁。当我返回到片段时,其中的 seekbar 被重置,但音频文件仍在播放。当我再次点击播放时,它会在之前的音频文件上叠加播放,导致同时播放两个文件。
英文:
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
得分: 2
每个片段都有一个 onDestroy()
回调函数,用于在片段从返回堆栈中弹出并销毁时调用。您可以在该方法中调用 stopPlayer()
。
@Override
public void onDestroy() {
super.onDestroy();
stopPlayer();
}
英文:
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
得分: 0
很遗憾,没有直接的方法来做到这一点,因为该片段没有onBackPressed()
方法,您需要创建一个回调并在片段中实现它才能使其正常工作。
首先,您需要创建一个接口和一个实现接口的类,以拥有一个通用方法。
- 创建接口类
OnBackPressedListener
OnBackPressedListener.java
public interface OnBackPressedListener {
void goBack();
}
- 在您的
MainActivity
中创建监听器并为其创建一个设置器,在重写onBackPressed()
方法后在其中使用它。
您的 MainActivity
应该如下所示:
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();
}
}
- 在
Fragment
中实现OnBackPressedListener
接口,并在其中使用它来停止播放器。
Fragment1.java
public class Fragment1 extends Fragment implements OnBackPressedListener {
@Override
public void goBack() {
stopPlayer();
}
}
附注
- 考虑将您的
fragment1
改为以大写字母F
开头的Fragment1
。
英文:
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
MainActivity
Create 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 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 beFragment1
with uppercasedF
答案3
得分: 0
@Override
public void onDestroy() {
stopPlayer();
super.onDestroy();
}
在片段中,重写 onDestroy
函数。在调用 super.onDestroy()
之前,停止播放器。
英文:
@Override
public void onDestroy() {
stopPlayer();
super.onDestroy();
}
In Fragment, override the OnDestroy function. and stop the player before calling super.onDestroy()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论