【问题标题】:How to make media player stop when pressing device back button from a fragment back to activity当按设备返回按钮从片段返回活动时如何使媒体播放器停止
【发布时间】:2020-10-05 01:33:55
【问题描述】:

我的问题是当我按下设备后退按钮时媒体播放器一直在播放。按下设备后退按钮时如何完全破坏片段和媒体播放器以及其中的所有内容,使其在屏幕上不可见?

我是编程新手,因此欢迎所有关于如何改进代码的建议和 cmets。谢谢

活动:

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();
            }
        });
    }
}

片段:

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;

        }
    }
}

编辑:

我尝试了提供的解决方案,但不知何故片段中的媒体播放器没有被破坏。当我回到片段时,其中的搜索栏被重置,但音频文件仍在播放。当我再次按下播放时,它开始在前一个文件的顶部再次播放,以便同时播放 2 个文件

【问题讨论】:

    标签: java android


    【解决方案1】:

    每个 Fragment 都有一个 onDestroy() 回调,用于将 Fragment 从返回堆栈中弹出并销毁。您可以通过该方法调用您的stopPlayer()

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

    【讨论】:

    • 什么“没用”?如果您实际上是从后台堆栈中弹出片段,则将调用 onDestroy()onDestroy() 是在您第一次转到片段时被调用,然后点击系统返回按钮吗?
    • 当我按下返回时,媒体仍在播放。对不起,我不能更具体。我将您的答案粘贴在片段中,但媒体仍在播放。我在原始问题中给出了整个代码。还是谢谢你回答
    【解决方案2】:

    不幸的是,没有直接的方法可以做到这一点由于片段没有onBackPressed() 方法,您必须进行回调并在片段中实现它才能使其工作。

    首先,您需要创建一个接口和实现其接口的类以拥有一个泛型方法

    1. 创建类接口OnBackPressedListener

    OnBackPressedListener.java

    public interface OnBackPressedListener {
        void goBack();
    }
    
    1. 在您的MainActivity 中创建侦听器并为其创建一个setter,并在覆盖它后在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();
        }
    }
    
    1. Fragment you should implement the OnBackPressedListener`接口中并使用它来停止播放器

    Fragment1.java

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

    旁注

    • 考虑将您的fragment1 名称重构为Fragment1,并使用大写的F

    【讨论】:

    • 您还必须删除侦听器以避免内存泄漏。在MainActivity 中创建一个新函数,将其命名为removeOnBackPressedListener,并将侦听器设置为null。当你从Fragment 回来时,你必须调用它
    • 请注意,现在不再是这种情况了 - any 组件,包括一个 Fragment,可以按照 the documentation 注册一个 OnBackPressedCallback 并拦截返回按钮的句柄.
    • Hamza Sharuf 和 ianhanniballake,我尝试了你们的两种解决方案,当我按下回击时,媒体仍在播放
    • 我的错,我认为这只是用于喷气背包导航组件。反正。 @sks 我的解决方案与其他解决方案完全一样。最好遵循 Ian 的解决方案,而忽略此解决方法。
    【解决方案3】:
    @Override
    public void onDestroy() {
        stopPlayer();
        super.onDestroy();
    }
    

    在 Fragment 中,重写 OnDestroy 函数。并在调用 super.onDestroy()

    之前停止播放器

    【讨论】:

    • 您使用的是哪个媒体播放器?
    • 默认的?媒体播放器类
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多