1、功能简介
实现将手机中的音乐播放出来
实现进度条随音乐播放滚动同步
获得当前音乐播放的时间与音乐的总时间
示例图如下:
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的方法
在最后一定要判断当前音乐的播放状态,否则当前时间就可能会在按下暂停或开始的按钮时停止工作