上一节实现了播放的功能,下面实现播放音乐时底部显示对应歌曲信息的功能。
【效果图】
【开发步骤】
1、xml 界面
2、当点击 ListView 中的 item 时,把播放列表和 position 存入 application
3、每当 service 开始播放音乐时,发送自定义广播
4、在Activity 中编写广播接收器接受该广播,获取当前正在播放的歌曲信息,更新界面(注意在 onCreate 及 onDestroy中注册以及取消注册)
5、更新 UI 时,我们需要通过 path 路径,获取 Bitmap
BitmapUtils.loadBitmap(String path,Callback){
异步发送http请求
调用 callback 回调方法 执行后续业务
}
按照开发步骤写代码:
主要布局中 activity_test.xml 中增加
这里的圆形头像用的是 CircleImageView
需要在 build.gradle 中引入依赖
implementation 'de.hdodenhof:circleimageview:3.1.0'
在点击播放歌曲后,底部显示对应歌曲信息,需要知道当前播放的歌曲是哪一首,我们可以存歌曲列表和点击的 position 来确定歌曲,可以用Application 实现
创建 MusicApplication
public class MusicApplication extends Application {
private List musicList;
private int position;
public static MusicApplication app;
@Override
public void onCreate() {
super.onCreate();
app = this;
}
public static MusicApplication getApp() {
return app;
}
public List getMusicList() {
return musicList;
}
public void setMusicList(List musicList) {
this.musicList = musicList;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public MusicItem getCurrentMusic() {
return musicList.get(position);
}
}
AndroidManifest 中注册
......
NewMusicListFragment 中,在点击 listview 时,在 application 中存入音乐播放列表和 position
private void setListeners() {
listView.setOnItemClickListener((adapterView, view, i, l) -> {
final MusicItem music = musics.get(i);
String songId = music.id;
Toast.makeText(getActivity(), "position:" + i, Toast.LENGTH_SHORT).show();
//执行业务层 加载这首歌曲的基本信息
model.loadMusicInfoBySongId(songId, new MusicInfoCallback() {
@Override
public void onMusicInfoLoaded(MusicItem musicItem) {
music.url = musicItem.url;
Log.d("TTT", music.url);
//把当前播放列表和position都存入application
MusicApplication app = MusicApplication.getApp();
app.setMusicList(musics);
app.setPosition(i);
//准备通过url地址执行播放业务
//播放音乐
binder.playMusic(music.url);
}
});
});
}
当音乐播放开始时,service 通知 activity 播放开始,因此我们需要发送广播,PlayMusicService 中修改:
@Override
public void onCreate() {
super.onCreate();
//给mediaPlayer加监听
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
//音乐已经准备好
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
//发送广播,通知activity音乐已经开始播放
Intent intent = new Intent (Globalconsts.ACTION_MUSIC_STARTED);
sendBroadcast(intent);
}
});
}
创建常量类 GlobalConsts
public class Globalconsts {
//音乐开始播放 广播action
public static final String ACTION_MUSIC_STARTED = "ACTION_MUSIC_STARTED";
}
BitmapUtils 中增加根据图片路径加载 bitmap 的方法
public static void loadBitmap(final String path, final BitmapCallback bitmapCallback){
AsyncTask task = new AsyncTask() {
@Override
protected Bitmap doInBackground(String... strings) {
try {
//先从内存缓存中读
//再从文件中读
String filename = path.substring(path.lastIndexOf("/")+1);
File file = new File(MusicApplication.getApp().getCacheDir(),"images/"+filename);
Bitmap b = bitmap(file);
if(b!=null){
return b;
}
InputStream is = HttpUtils.getInputStream(path);
b = BitmapFactory.decodeStream(is);
//下载下来的图片,存入缓存中
save(b,file);
return b;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//主线程中执行回调方法
@Override
protected void onPostExecute(Bitmap bitmap) {
bitmapCallback.onBitmapLoaded(bitmap);
}
};
task.execute();
}
增加接口 BitmapCallback
public interface BitmapCallback {
void onBitmapLoaded(Bitmap bitmap);
}
Activity 中注册接收器
MusicInfoBroadCastReceiver receiver;
private ImageView imgMusicThumb;
private TextView tvMusicTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
......
//绑定Service
bindMusicService();
//注册广播接收器
registMusicReceiver();
}
private void setViews() {
......
viewPager = findViewById(R.id.viewpager);
imgMusicThumb = findViewById(R.id.img_music_thumb);
tvMusicTitle = findViewById(R.id.tv_music_title);
}
private void registMusicReceiver() {
receiver = new MusicInfoBroadCastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Globalconsts.ACTION_MUSIC_STARTED);
this.registerReceiver(receiver,intentFilter);
}
class MusicInfoBroadCastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(Globalconsts.ACTION_MUSIC_STARTED)){
//开始播放音乐,获取当前音乐对象
MusicApplication app = MusicApplication.getApp();
MusicItem music = app.getCurrentMusic();
String pic = music.albumPic;
final String title = music.name;
BitmapUtils.loadBitmap(pic, new BitmapCallback() {
@Override
public void onBitmapLoaded(Bitmap bitmap) {
if(bitmap != null){
imgMusicThumb.setImageBitmap(bitmap);
}
}
});
tvMusicTitle.setText(title);
}
}
}
@Override
protected void onDestroy() {
this.unbindService(conn);
this.unregisterReceiver(receiver);
super.onDestroy();
}
现在让图片转起来,MusicInfoBroadCastReceiver 中在设置完图片后,设置动画:
BitmapUtils.loadBitmap(pic, new BitmapCallback() {
@Override
public void onBitmapLoaded(Bitmap bitmap) {
if(bitmap != null){
imgMusicThumb.setImageBitmap(bitmap);
//执行旋转动画
RotateAnimation animation = new RotateAnimation(0,360,imgMusicThumb.getWidth()/2,imgMusicThumb.getWidth()/2);
animation.setDuration(10000);
animation.setRepeatCount(Animation.INFINITE);
animation.setInterpolator(new LinearInterpolator());//匀速旋转
imgMusicThumb.startAnimation(animation);
}
tvMusicTitle.setText(title);
}
});



