1、功能简介

实现将手机中的音乐播放出来
实现进度条随音乐播放滚动同步
获得当前音乐播放的时间与音乐的总时间

示例图如下:

Android 拖动 android 拖动条和音乐同步_Android 拖动

Android 拖动 android 拖动条和音乐同步_音乐播放_02

2、实现过程

新建一个MusicActivity,在MusicActivity的layout中写出页面的布局
xml代码:

<RelativeLayout 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"
    tools:context="com.lenovo.liu.practice.MusicActivity">
//界面的背景图片
    <ImageView 
        android:id="@+id/music_img"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@mipmap/ic_launcher" />
//上方歌手的的布局
    <RelativeLayout
        android:id="@+id/music_up1"
        android:layout_width="match_parent"
        android:layout_height="60dp">

        <ImageView
            android:id="@+id/music_putdown"
            android:layout_width="40dp"
            android:layout_height="30dp"
            android:layout_margin="15dp"
            android:src="@mipmap/ic_arrow_down" />

        <TextView
            android:id="@+id/music_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:layout_toRightOf="@id/music_putdown"
            android:text="音乐"
            android:textColor="#ffffff"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/music_auther"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/music_title"
            android:layout_toRightOf="@id/music_putdown"
            android:text="作者-专辑"
            android:textColor="#ffffff"
            android:textSize="15sp" />
    </RelativeLayout>
//指针上面的一条横线
    <View
        android:id="@+id/music_divider"
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:layout_below="@+id/music_up1"
        android:background="#999999"></View>

//中间的黑圈
    <ImageView
        android:id="@+id/music_disc"
        android:layout_width="280dp"
        android:layout_height="280dp"
        android:layout_centerInParent="true" />
//指针
    <ImageView
        android:id="@+id/music_needle"
        android:layout_width="180dp"
        android:layout_height="180dp"
        android:layout_below="@id/music_divider"
        android:layout_centerHorizontal="true"
        android:src="@mipmap/play_page_needle" />
//界面下方的几个按钮
    <LinearLayout
        android:id="@+id/music_bottom"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_alignParentBottom="true">

        <ImageView
            android:id="@+id/music_round"
            android:layout_width="0dp"  //运用权重将几个按钮平均分布
            android:layout_height="60dp"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:src="@mipmap/ic_play_btn_loop_pressed" />

        <ImageView
            android:id="@+id/music_prevbtn"
            android:layout_width="0dp"
            android:layout_height="60dp"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:src="@mipmap/ic_play_btn_prev" />

        <ImageView
            android:id="@+id/music_pressbtn"
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:src="@mipmap/ic_play_btn_pause_pressed" />

        <ImageView
            android:id="@+id/music_nextbtn"
            android:layout_width="0dp"
            android:layout_height="60dp"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:src="@mipmap/ic_play_btn_next" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/music_bottom"
        android:orientation="horizontal"
        android:paddingLeft="10dp"
        android:paddingRight="10dp">
//音乐当前时间
        <TextView
            android:id="@+id/music_firsttime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="00:00"
            android:textColor="#ffffff"
            android:textSize="20sp" />
//用SeekBar来将进度条实现出来
        <SeekBar
            android:id="@+id/playSeekBar"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:layout_marginLeft="3dp"
            android:layout_marginTop="5dp"
            android:layout_toRightOf="@id/music_firsttime" />
//音乐的总时长
        <TextView
            android:id="@+id/music_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="10dp"
            android:text="00:00"
            android:textColor="#ffffff"
            android:textSize="20sp" />
    </LinearLayout>
</RelativeLayout>

在Android中音乐播放器的实现是用MediaPlay的方法实现的

Activity代码实现

//接入监听接口 
public class MusicActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView titleTV;//歌名
    private TextView autherTV;//歌手
    private ImageView imageView;//背景图
    private TextView timeTV;//总时长
    private ImageView prveBtn;//上一首歌
    private ImageView nextBtn;//下一首
    private int position;
    private ImageView discBtn;
    private ImageView needleBtn;
    private MediaPlayer mediaPlayer;//定义MediaPlayer 
    private ImageView pressBtn;
    private ImageView putBtn;
    private SeekBar seekBar;//进度条
    private Thread thread;//线程
    private boolean isStop;//线程标志位
    private TextView currentime;//当前时间
    private int totalTime;

//运用Handler中的handleMessage方法接收子线程传递的信息
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            // 将SeekBar位置设置到当前播放位置
            seekBar.setProgress(msg.what);
            //获得音乐的当前播放时间
            currentime.setText(formatime(msg.what));
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_music);
//绑定监听事件的id
        bindID();
//设置点击事件
        prveBtn.setOnClickListener(this);
        nextBtn.setOnClickListener(this);
        pressBtn.setOnClickListener(this);
        putBtn.setOnClickListener(this);

//得到之前界面的传值
        final Intent intent = getIntent();
        position = intent.getIntExtra("position", 0);
//实例化MediaPlayer
        mediaPlayer = new MediaPlayer();

        play();

//监听滚动条事件
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                //参数 : fromUser即b 是用来标识是否来自用户的手动操作  true 用户动过手动方式更改的进度条
                if (b){

                    //seekto方法是异步方法
                    //seekto方法的参数是毫秒,而不是秒
                    mediaPlayer.seekTo(i);
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

    }


    private void play() {
        isStop = false;
        //Common是自己定义的一个工具类,里面获得的是本地音乐的信息
        Music music = Common.musicList.get(position);
        titleTV.setText(music.title);
        autherTV.setText(music.auther + "-" + music.album);
        pressBtn.setImageResource(R.mipmap.ic_play_btn_pause_pressed);
        timeTV.setText(formatime(music.lengrh));
        //获得音乐时长
        totalTime=music.lengrh;
         //将专辑图片放入黑圈中
        Bitmap discBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.play_page_disc);
        if (music.albumbtm != null) {

            //       imageView.setImageBitmap(music.albumbtm);
            Bitmap bgbm = BlurUtil.doBlur(music.albumbtm, 15, 10);
            imageView.setImageBitmap(bgbm);
            Bitmap albumdiscBit = MergeImage.mergeThumbnailBitmap(discBitmap, music.albumbtm);
            discBtn.setImageBitmap(albumdiscBit);

        } else {
            Bitmap bm = BitmapFactory.decodeResource(getResources(), R.mipmap.play_page_default_cover);
            imageView.setImageBitmap(BlurUtil.doBlur(bm, 10, 5));
            Bitmap albumdiscBit = MergeImage.mergeThumbnailBitmap(discBitmap, bm);
            discBtn.setImageBitmap(albumdiscBit);
        }
        //重置,当切换音乐时不会放前一首歌的歌曲
        mediaPlayer.reset();
        try {
         // 设置音乐播放源
            mediaPlayer.setDataSource(music.path);
             // 准备
            mediaPlayer.prepare();
            // 启动
            mediaPlayer.start();

        } catch (IOException e) {
            e.printStackTrace();
        }
       // 设置seekbar的最大值
        seekBar.setMax(mediaPlayer.getDuration());
        // 创建一个线程
       thread = new Thread(new MuiscThread());
        // 启动线程
          thread.start();


    }
  //时间转换类,将得到的音乐时间毫秒转换为时分秒格式
    private String formatime(int lengrh) {
        Date date = new Date(lengrh);
        SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
        String totalTime = sdf.format(date);
        return totalTime;
    }
//绑定id的类
    private void bindID() {
        titleTV = findViewById(R.id.music_title);
        autherTV = findViewById(R.id.music_auther);
        imageView = findViewById(R.id.music_img);
        timeTV = findViewById(R.id.music_time);
        prveBtn = findViewById(R.id.music_prevbtn);
        nextBtn = findViewById(R.id.music_nextbtn);
        discBtn = findViewById(R.id.music_disc);
        needleBtn=findViewById(R.id.music_needle);
        pressBtn = findViewById(R.id.music_pressbtn);
        putBtn = findViewById(R.id.music_putdown);
        currentime=findViewById(R.id.music_firsttime);
        seekBar = findViewById(R.id.playSeekBar);
    }

//点击事件
    @Override
    public void onClick(View view) {

        switch (view.getId()) {
            case R.id.music_prevbtn://点击上一首歌曲
                position--;
                if (position == -1) {
                    position = Common.musicList.size() - 1;
                }
                play();
                break;
            case R.id.music_nextbtn://点击下一首歌曲
                position++;
                if (position == Common.musicList.size()) {
                    position = 0;
                }
                play();
                break;
            case R.id.music_pressbtn:
            //用if语句判断音乐播放的的状态
                if (mediaPlayer.isPlaying()) {
                    mediaPlayer.pause();
                    pressBtn.setImageResource(R.mipmap.ic_status_bar_play_light_pressed);
                } else {
                    mediaPlayer.start();
                    //点击下一首时会继续出现暂停的按钮
                    pressBtn.setImageResource(R.mipmap.ic_play_btn_pause_pressed);

                }
                break;
            case R.id.music_putdown:
                this.finish();
                break;
            default:
                break;

        }
    }

    //销毁时所做的工作
    protected void onDestroy() {
        super.onDestroy();
        mediaPlayer.reset();
    }


    //建立一个子线程实现Runnable接口
      class MuiscThread implements Runnable {

        @Override
        //实现run方法
        public void run() {
        //判断音乐的状态,在不停止与不暂停的情况下向总线程发出信息
            while (mediaPlayer != null && isStop == false) {

                try {
                    // 每100毫秒更新一次位置
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //发出的信息
                handler.sendEmptyMessage(mediaPlayer.getCurrentPosition());
            }

        }

    }



}
进度条的实现用SeekBar,若是想实现进度条不出现卡顿现象就要加上seekBar.setMax(mediaPlayer.getDuration());这句,获取seekbar的最大值,同时,要想获得音乐播放的当前时间就必须运用Handler的方法
    在最后一定要判断当前音乐的播放状态,否则当前时间就可能会在按下暂停或开始的按钮时停止工作