效果图:

在写代码之前,我先告诉你们一个坑点,我在实现这个功能的时候,在导入raw文件时遇到了一个坑,找不到这个文件夹,如果你们也遇到了这种情况,参考我之前写的一篇博客,即可解决问题:https://blog.csdn.net/qq_27494201/article/details/96334284

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private Button btnStart,btnStop,btnPause,btnReplay;     //  播放器按钮    private SeekBar seekBar;                    //  进度条    private MediaPlayer mediaPlayer = null;     //  音乐播放控制对象,可以操控暂停、停止、播放、重置等等    private Object obj = new Object();      //  对象锁,播放线程暂停时,让进度条线程进入等待状态    private Thread seekThread;            //    线程    private boolean isRun = false;      //  进度条线程控制    private boolean suspended = false;  //  进度条线程等待状态控制    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();     //  初始化控件        initJian();     //  添加监听事件        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {              //  进度条的监听事件            @Override            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {            }            @Override            public void onStartTrackingTouch(SeekBar seekBar) {                pause();        //  进度条开始前,调用 pause()            }            @Override            public void onStopTrackingTouch(SeekBar seekBar) {              //  进度条开始后,调用 pause()                if (mediaPlayer != null && !mediaPlayer.isPlaying()){                    int progress2 = seekBar.getProgress();                    int currentPosition2 = mediaPlayer.getDuration()*progress2/100;                    continuePlay(progress2,currentPosition2);                }            }        });    }    private void initJian() {        btnStart.setOnClickListener(this);        btnStop.setOnClickListener(this);        btnReplay.setOnClickListener(this);        btnPause.setOnClickListener(this);    }    private void initView() {        btnStart = findViewById(R.id.btn_Start);        btnStop = findViewById(R.id.btn_Stop);        btnPause = findViewById(R.id.btn_Pause);        btnReplay = findViewById(R.id.btn_Replay);        seekBar = findViewById(R.id.seekBar);    }    @RequiresApi(api = Build.VERSION_CODES.M)    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.btn_Start:                                //  播放                if (mediaPlayer == null){           //  如果没有暂停                    play();     //  调用 play 方法进行播放                }else{                    if (!mediaPlayer.isPlaying()){             //   如果处于暂停状态                        int progress = seekBar.getProgress();   //  得到 SeekBar 的进度                        int currentPosition = mediaPlayer.getCurrentPosition();     //  获取当前位置                        continuePlay(progress,currentPosition);      //  在从暂停状态恢复播放时使用,除了继续播放音乐,还需要唤醒等待中的进度条绘制线程                    }                }                break;            case R.id.btn_Pause:                            //  暂停                pause();                break;            case R.id.btn_Replay:                           //  停止                if (mediaPlayer == null){          //   播放器对象还未创建或者已经销毁                    play();                }else{                    if (!mediaPlayer.isPlaying()){      //  暂停状态                        continuePlay(0,0);      //  进度条为0,第二个参数是:当前播放的位置,因为停止了,所以回到0                    }else{                     //   正在播放状态不需要唤醒线程的操作,并且这种情况是点了一次停止以后再点停止就会变成播放的作用                        mediaPlayer.seekTo(0);      //  从0开始播放                        mediaPlayer.start();                //  开始播放                    }                }                break;            case R.id.btn_Stop:                             //  重播                stop();                 //  这里重播相当于停止                break;        }    }    /*  线程用来根据音乐播放进度绘制进度条   */    class SeekThread extends  Thread{        int duration = mediaPlayer.getDuration();   //当前音乐总长度        int currentPosition = 0;        public void run(){            while (isRun){                currentPosition = mediaPlayer.getCurrentPosition(); //  获取当前音乐播放到了哪里                seekBar.setProgress(currentPosition*100 / duration);                try {                    Thread.sleep(300);                } catch (InterruptedException e) {                    e.printStackTrace();                }                synchronized (obj){                    while (suspended){                        try {                            obj.wait();     //  音乐暂停时让进度条线程也暂停                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                    }                }            }        }    }        /*  初始化播放,一个是音乐播放,一个线程控制的进度条绘制  */    @RequiresApi(api = Build.VERSION_CODES.M)    private void play() {        mediaPlayer = MediaPlayer.create(MainActivity.this,R.raw.music_bgw);    //  直接理解为拿到音频资源文件就行        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {    //  监听播放结束事件(停止、暂停、播放完了一首音乐)            @Override            public void onCompletion(MediaPlayer mp) {                if (mediaPlayer != null){           //  如果是暂停的情况                    stop();             //  调用暂停方法                }            }        });        isRun = true;                 //  进度条线程控制,ture为暂停进度条线程的绘制        seekThread = new SeekThread();  //  实例化一个线程对象,开始发挥作用        mediaPlayer.start();            //  开始播放音乐        seekThread.start();             //  启动线程    }    private void stop() {        if (mediaPlayer != null){        //     只要有资源            seekBar.setProgress(0);      //     进度条回到0的位置            isRun = false;               //     线程            mediaPlayer.stop();          //     停止播放音乐            mediaPlayer.release();       //     释放资源            mediaPlayer = null;          //     销毁音乐对象            seekThread = null;           //     销毁线程        }    }    private void pause() {        if (mediaPlayer != null && mediaPlayer.isPlaying()){    //  如果音乐对象是有资源 并且 音乐正在播放的状态下            mediaPlayer.pause();         //     暂停            suspended = true;           //  进度条线程等待状态控制        }    }    //  在从暂停状态恢复播放时使用,除了继续播放音乐,还需要唤醒等待中的进度条绘制线程    private void continuePlay(int progress, int currentPosition) {        mediaPlayer.seekTo(currentPosition);           //   跳转到对应时间进行播放        mediaPlayer.start();                //  开始(暂停也是一种开始,跟播放一样,只是暂停是要回到之前的位置继续播放)        seekBar.setProgress(progress);      //  设置回到之前的位置,这个progress是之前播放到的进度!        suspended = false;               //  进度条线程等待状态控制        synchronized (obj){           //  对象锁,播放线程暂停时,让进度条线程进入等待状态            obj.notify();       //  唤醒线程,开始绘制进度条        }    }    }

activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".MainActivity">    <SeekBar        android:id="@+id/seekBar"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="50dp"/>    <LinearLayout        android:id="@+id/ly_main"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="200dp">    <Button        android:id="@+id/btn_Start"        android:layout_width="0dp"        android:layout_height="wrap_content"        android:layout_weight="1"        android:textSize="18dp"        android:text="播放"/>    <Button        android:id="@+id/btn_Stop"        android:layout_width="0dp"        android:layout_height="wrap_content"        android:layout_weight="1"        android:textSize="18dp"        android:text="重播"/>            <Button        android:id="@+id/btn_Pause"        android:layout_width="0dp"        android:layout_height="wrap_content"        android:layout_weight="1"        android:textSize="18dp"        android:text="暂停"/>    <Button        android:id="@+id/btn_Replay"        android:layout_width="0dp"        android:layout_height="wrap_content"        android:layout_weight="1"        android:textSize="18dp"        android:text="停止"/>    LinearLayout>LinearLayout>

总结:

在本例启动了一个用来绘制进度条的线程 SeekThread,不断获取当前播放的进度,根据进度比例绘制进度条,当音乐播放暂停时,由对象锁 obj 让进度条线程进入等待状态,自爱此播放时唤醒线程,让进度条继续绘制。

如果有问题,可以联系我qq:1787424177

最后,我真诚的希望能评论一句嘛,让我知道你来过,我会很开心的

更多相关文章

  1. android 播放 优酷视频
  2. android第四天晚:绘图和handle
  3. Work 工作子线程更新UI控件--解决Only the original thread that
  4. Android中多线程的用法
  5. RTSP/RTMP/HLS/HTTP流媒体播放器EasyPlayer
  6. Android(安卓)Handler, Looper浅析
  7. Android异步下载网络图片(其三)
  8. Handler: 更新UI的方法
  9. Android(安卓)AsyncTask 源码解析

随机推荐

  1. 网络配置 - 定制APN
  2. Android输入法原理和疑云
  3. android 分享到不同的开放平台
  4. AQuery简介:jQuery for Android
  5. 基于Android的MediaPlayer的音乐播放器的
  6. Android入门篇五:使用全局变量在Activity
  7. Android(安卓)8.0 SystemUI下拉状态栏快
  8. Android 之 zygote 与进程创建
  9. 收藏老罗的----------Android应用程序组
  10. Android(二) 基于 eclipse 的 Android配置