1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > Android MediaPlayer 实现音乐播放器

Android MediaPlayer 实现音乐播放器

时间:2021-11-15 15:59:52

相关推荐

Android MediaPlayer 实现音乐播放器

效果图:

在写代码之前,我先告诉你们一个坑点,我在实现这个功能的时候,在导入raw文件时遇到了一个坑,找不到这个文件夹,如果你们也遇到了这种情况,参考我之前写的一篇博客,即可解决问题:/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; // 进度条线程等待状态控制@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();// 初始化控件initJian();// 添加监听事件seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {// 进度条的监听事件@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {pause(); // 进度条开始前,调用 pause()}@Overridepublic 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)@Overridepublic 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() {// 监听播放结束事件(停止、暂停、播放完了一首音乐)@Overridepublic 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="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><SeekBarandroid:id="@+id/seekBar"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="50dp"/><LinearLayoutandroid:id="@+id/ly_main"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="200dp"><Buttonandroid:id="@+id/btn_Start"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:textSize="18dp"android:text="播放"/><Buttonandroid:id="@+id/btn_Stop"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:textSize="18dp"android:text="重播"/><Buttonandroid:id="@+id/btn_Pause"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:textSize="18dp"android:text="暂停"/><Buttonandroid: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

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。