文章目录
- 效果图
- 更新进度条
- 上一曲、下一曲
- 显示标题和专辑
效果图
更新进度条
要更新进度条,需要 PlayMusicService 中发送广播,每秒发送广播,广播中携带播放进度信息,因此在 PlayMusicService 的 onCreate 方法中开启一个线程,写在 onCreate 中保证只起一条线程
private boolean isLoop = true;
/**
* 当service实例创建时执行
*/
public void onCreate() {
super.onCreate();
//给mediaPlayer加监听
......
//启动工作线程,每隔1s发送一次更新进度的广播
new updateProgressThread().start();
}
/**
* 更新进度的线程
* 每秒发送广播,广播中携带播放进度信息
*/
class updateProgressThread extends Thread{
public void run() {
while (isLoop){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//发送自定义广播
if(mediaPlayer.isPlaying()){
int total = mediaPlayer.getDuration();
int currentPosition = mediaPlayer.getCurrentPosition();
Intent intent = new Intent(Globalconsts.ACTION_UPDATE_MUSIC_PROGRESS);
intent.putExtra("total",total);
intent.putExtra("current",currentPosition);
sendBroadcast(intent);
}
}
}
}
Activity 中修改广播接收器的代码
private SeekBar seekBar;
private TextView tv_play_music_total_time;
private TextView tv_play_music_current_time;
private void setViews() {
......
seekBar = findViewById(R.id.sk_play_music_progress);
tv_play_music_total_time = findViewById(R.id.tv_play_music_total_time);
tv_play_music_current_time = findViewById(R.id.tv_play_music_current_time);
}
/**
* 注册广播接收器
*/
private void registMusicReceiver() {
receiver = new MusicInfoBroadCastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Globalconsts.ACTION_MUSIC_STARTED);
intentFilter.addAction(Globalconsts.ACTION_UPDATE_MUSIC_PROGRESS);
this.registerReceiver(receiver, intentFilter);
}
......
/**
* 接收音乐信息的广播接收器
*/
class MusicInfoBroadCastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Globalconsts.ACTION_UPDATE_MUSIC_PROGRESS)) {
//获取广播中的total\current
int total = intent.getIntExtra("total", 0);
int current = intent.getIntExtra("current", 0);
//更新seekbar
seekBar.setMax(total);
seekBar.setProgress(current);
String totalStr = Globalconsts.FORMAT.format(new Date(total));
String currentStr = Globalconsts.FORMAT.format(new Date(current));
tv_play_music_total_time.setText(totalStr);
tv_play_music_current_time.setText(currentStr);
} else if (action.equals(Globalconsts.ACTION_MUSIC_STARTED)) {
......
}
}
}
同时,Globalconsts 增加
public static final SimpleDateFormat FORMAT = new SimpleDateFormat("mm:ss");
//音乐开始播放 广播action
public static final String ACTION_MUSIC_STARTED = "ACTION_MUSIC_STARTED";
给进度条增加拖拽事件,MainActivity 中修改 bindMusicService() 中的 binder 对象为全局变量
private PlayMusicService.MusicBinder binder;
private void setListeners() {
//给seekbar加监听
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {//由用户引起
//seekto
binder.seekTo(progress);
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
......
}
PlayMusicService 中 MusicBinder 里增加 seekTo方法
public class MusicBinder extends Binder{
//定义供客户端调用的方法
/**
* 跳转到相应位置 继续播放/暂停
*/
public void seekTo(int position){
mediaPlayer.seekTo(position);
}
......
}
上一曲、下一曲
实现上一曲和下一曲,首先给三个图片(上一首,下一首,暂停图片)增加点击事件,同时在
MusicBinder 中 MusicBinder 中增加播放或暂停的方法
首先给 MusicBinder 中的 MusicBinder 中增加播放或暂停的方法
//暂停或开始播放
public void playOrPause(){
if(mediaPlayer.isPlaying()){
mediaPlayer.pause();
}else {
mediaPlayer.start();
}
}
Activity 给三个图片(上一首,下一首,暂停图片)增加点击事件
public class TestActivity extends AppCompatActivity implements View.OnClickListener {
......
private MusicApplication app;
private ImageView img_pre_music;
private ImageView img_pause_music;
private ImageView img_next_music;
private MusicModel musicModel = new MusicModel();
......
private void setViews() {
......
img_pre_music = findViewById(R.id.img_pre_music);
img_pause_music = findViewById(R.id.img_pause_music);
img_next_music = findViewById(R.id.img_next_music);
}
......
private void setListeners() {
......
imgMusicThumb.setOnClickListener(this);
img_pre_music.setOnClickListener(this);
img_pause_music.setOnClickListener(this);
img_next_music.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
......
case R.id.img_pre_music:
app.setPosition(app.getPosition() == 0 ? 0 : app.getPosition() - 1);
//这里会出空指针,当前歌曲只有在点击播放后才能拿到currentmusic的信息
final MusicItem music = app.getCurrentMusic();
if (music.url != null) {//基本信息已经加载过
//播放音乐
binder.playMusic(music.url);
} else {
//通过songid获取基本信息
musicModel.loadMusicInfoBySongId(music.id, new MusicInfoCallback() {
public void onMusicInfoLoaded(MusicItem musicItem) {
music.url = musicItem.url;
music.id = musicItem.id;
binder.playMusic(musicItem.url);
}
});
}
break;
case R.id.img_pause_music:
binder.playOrPause();
break;
case R.id.img_next_music:
app.setPosition(app.getPosition() == app.getMusicList().size() - 1 ? 0 : app.getPosition() + 1);
final MusicItem music2 = app.getCurrentMusic();
if (music2.url != null) {//基本信息已经加载过
//播放音乐
binder.playMusic(music2.url);
} else {
//通过songid获取基本信息
musicModel.loadMusicInfoBySongId(music2.id, new MusicInfoCallback() {
public void onMusicInfoLoaded(MusicItem musicItem) {
music2.url = musicItem.url;
music2.id = musicItem.id;
binder.playMusic(musicItem.url);
}
});
}
break;
}
}
......
}
解决点击上一曲下一曲按钮时,触发listview的onclick事件,给rlPlayMusic加上onTouch事件,返回true即可
private void setListeners() {
//给rlPlayMusic注册onTouch事件(触摸执行)
rlPlayMusic.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
//如果返回true
return true;
//如果返回false
//return false;
}
});
......
}
显示标题和专辑
这一步很简单,在 Activity 中,广播接收器接收到开始的通知时,显示标题和专辑即可
/**
* 接收音乐信息的广播接收器
*/
class MusicInfoBroadCastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Globalconsts.ACTION_UPDATE_MUSIC_PROGRESS)) {
......
} else if (action.equals(Globalconsts.ACTION_MUSIC_STARTED)) {
//开始播放音乐,获取当前音乐对象
app = MusicApplication.getApp();
MusicItem music = app.getCurrentMusic();
String pic = music.albumPic;
final String title = music.name;
tv_play_music_title.setText(title);
tv_play_music_singer.setText(music.albumName);
......
}
}
}