播放列表功能开发
This commit is contained in:
parent
90564a274c
commit
72bf148ad5
@ -7,7 +7,6 @@
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
|
||||
@ -21,11 +21,36 @@ import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
||||
|
||||
public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayListBinding> {
|
||||
|
||||
private String mCurVideId;
|
||||
|
||||
private String lastVideId;
|
||||
|
||||
private int curMusicPos = 0;
|
||||
private MyMediaControllerManager instance = MyMediaControllerManager.getInstance();
|
||||
|
||||
@Override
|
||||
protected ItemPlayListBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemPlayListBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
public void setCurVideId(String curVideId) {
|
||||
lastVideId = mCurVideId;
|
||||
this.mCurVideId = curVideId;
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
ResponsePlayListInfo listInfo = data.get(i);
|
||||
if (listInfo.getVideoId().equals(curVideId)) {
|
||||
notifyItemChanged(i);
|
||||
}
|
||||
if (listInfo.getVideoId().equals(lastVideId)) {
|
||||
notifyItemChanged(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateCurMusicAnimation(){
|
||||
notifyItemChanged(curMusicPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
@ -40,20 +65,32 @@ public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayL
|
||||
.into(vb.imCovert);
|
||||
vb.songName.setText(listInfo.getSongTitle());
|
||||
vb.artistName.setText(listInfo.getSingerName());
|
||||
MyMediaControllerManager instance = MyMediaControllerManager.getInstance();
|
||||
|
||||
MediaItem currentMediaItem = instance.getMediaController().getCurrentMediaItem();
|
||||
if (currentMediaItem != null && currentMediaItem.mediaId.equals(listInfo.getVideoId())) {
|
||||
vb.lottieAnimationView.setVisibility(View.VISIBLE);
|
||||
vb.viewPlaying.setVisibility(View.VISIBLE);
|
||||
vb.getRoot().setBackgroundColor(CommonUtils.getMyColor(R.color.cur_play_music));
|
||||
if (instance.getMediaController().isPlaying()) {
|
||||
vb.lottieAnimationView.playAnimation();
|
||||
vb.viewPlaying.startAnimating();
|
||||
lastVideId = listInfo.getVideoId();
|
||||
CommonUtils.LogMsg("-------playAnimation");
|
||||
} else {
|
||||
vb.lottieAnimationView.pauseAnimation();
|
||||
vb.viewPlaying.pauseAnimating();
|
||||
CommonUtils.LogMsg("-------pauseAnimation");
|
||||
}
|
||||
} else {
|
||||
vb.lottieAnimationView.setVisibility(View.GONE);
|
||||
CommonUtils.LogMsg("-------GONE");
|
||||
}
|
||||
vb.viewPlaying.setVisibility(View.GONE);
|
||||
// CommonUtils.LogMsg("-------GONE");
|
||||
}
|
||||
|
||||
vb.itemLayout.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
CommonUtils.LogMsg("-------onClick curMusicPos="+itemHolder.getAbsoluteAdapterPosition());
|
||||
setCurVideId(listInfo.getVideoId());
|
||||
instance.playPositionMusic(itemHolder.getAbsoluteAdapterPosition());
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,158 @@
|
||||
package com.hi.music.player.customerview;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class AnimaPlayingView extends View {
|
||||
|
||||
private Paint paint;
|
||||
private int barColor = Color.GREEN; // 音量条的颜色
|
||||
private int numBars = 5; // 音量条的数量
|
||||
private float[] barHeights; // 每个音量条的高度
|
||||
private int maxHeight = CommonUtils.dpToPx(20); // 音量条的最大高度
|
||||
private int minHeight = CommonUtils.dpToPx(4); // 音量条的最小高度
|
||||
|
||||
// 每个柱子的宽度
|
||||
private int barWidth =CommonUtils. dpToPx(4);
|
||||
// 柱子之间的间距
|
||||
private int barSpacing = CommonUtils.dpToPx(2);
|
||||
|
||||
private int cornerRadius = CommonUtils.dpToPx(16);
|
||||
private Random random;
|
||||
|
||||
private ValueAnimator animator;
|
||||
|
||||
public AnimaPlayingView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public AnimaPlayingView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public AnimaPlayingView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
paint = new Paint();
|
||||
paint.setColor(barColor);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
barHeights = new float[numBars];
|
||||
random = new Random();
|
||||
|
||||
// 初始化音量条高度
|
||||
for (int i = 0; i < numBars; i++) {
|
||||
barHeights[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
int height = getHeight();
|
||||
int width = getWidth();
|
||||
|
||||
int barCount = barHeights.length;
|
||||
int totalWidth = barCount * barWidth + (barCount - 1) * barSpacing;
|
||||
int startX = (width - totalWidth) / 2;
|
||||
|
||||
|
||||
for (int i = 0; i < numBars; i++) {
|
||||
|
||||
float left = startX + i * (barWidth + barSpacing);
|
||||
float top = height - barHeights[i];
|
||||
float right = left + barWidth;
|
||||
float bottom = height;
|
||||
|
||||
canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius, paint);
|
||||
}
|
||||
}
|
||||
|
||||
// 启动固定动画,使音量条的高度变化
|
||||
public void startAnimating() {
|
||||
|
||||
for (int i = 0; i < numBars; i++) {
|
||||
animator = ValueAnimator.ofFloat(0, 1);
|
||||
animator.setDuration(1000); // 每0.5秒更新一次
|
||||
animator.setRepeatCount(ValueAnimator.INFINITE);
|
||||
animator.setRepeatMode(ValueAnimator.REVERSE);
|
||||
animator.setInterpolator(new LinearInterpolator());
|
||||
int finalI = i;
|
||||
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
// 更新每个音量条的高度,使其不断变化
|
||||
float animatedValue = (Float) animation.getAnimatedValue();
|
||||
float v = animatedValue * maxHeight;
|
||||
barHeights[finalI] = v;
|
||||
invalidate(); // 重绘视图
|
||||
}
|
||||
});
|
||||
animator.setStartDelay(i* 200L);
|
||||
animator.start();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void pauseAnimating(){
|
||||
if(animator!= null){
|
||||
animator.pause();
|
||||
}
|
||||
for (int i = 0; i < numBars; i++) {
|
||||
barHeights[i] = minHeight;
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 随机生成音量条的高度
|
||||
private float randomHeight() {
|
||||
return minHeight + random.nextFloat() * (maxHeight - minHeight);
|
||||
}
|
||||
|
||||
// 设置音量条的颜色
|
||||
public void setBarColor(int color) {
|
||||
barColor = color;
|
||||
paint.setColor(barColor);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
// 设置音量条的最大高度
|
||||
public void setMaxHeight(int maxHeight) {
|
||||
this.maxHeight = maxHeight;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
// 设置音量条的最小高度
|
||||
public void setMinHeight(int minHeight) {
|
||||
this.minHeight = minHeight;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
// 设置音量条数量
|
||||
public void setNumBars(int numBars) {
|
||||
this.numBars = numBars;
|
||||
barHeights = new float[numBars];
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,13 +6,16 @@ import android.graphics.Color;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.net.Uri;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.palette.graphics.Palette;
|
||||
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.api.onImageColorListener;
|
||||
|
||||
import org.json.JSONException;
|
||||
@ -51,6 +54,7 @@ public class CommonUtils {
|
||||
public static int dpToPx(int dp) {
|
||||
return Math.round(dp * (MusicApplication.myApplication.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
|
||||
}
|
||||
|
||||
public static int pxToDp(int px) {
|
||||
return Math.round(px / (MusicApplication.myApplication.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
|
||||
}
|
||||
@ -75,7 +79,6 @@ public class CommonUtils {
|
||||
}
|
||||
|
||||
|
||||
|
||||
//time 3:45
|
||||
public static long convertToMilliseconds(String time) {
|
||||
String[] parts = time.split(":");
|
||||
@ -92,6 +95,10 @@ public class CommonUtils {
|
||||
return String.format("%d:%02d", minutes, seconds); // 格式化为 mm:ss
|
||||
}
|
||||
|
||||
public static int getMyColor(int resId) {
|
||||
return MusicApplication.myApplication.getColor(resId);
|
||||
}
|
||||
|
||||
|
||||
// 使用 Palette 提取深色主色调
|
||||
public static void getDominantDarkColor1(Drawable imDraw, onImageColorListener listener) {
|
||||
@ -99,7 +106,8 @@ public class CommonUtils {
|
||||
BitmapDrawable drawable = (BitmapDrawable) imDraw;
|
||||
if (drawable != null) {
|
||||
Bitmap bitmap = drawable.getBitmap();
|
||||
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
|
||||
Palette.from(bitmap)
|
||||
.generate(new Palette.PaletteAsyncListener() {
|
||||
@Override
|
||||
public void onGenerated(Palette palette) {
|
||||
// 首先尝试获取深色活力色
|
||||
@ -162,4 +170,34 @@ public class CommonUtils {
|
||||
drawable.setCornerRadii(radii);
|
||||
return drawable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 当前媒体项是否有有效的播放地址
|
||||
* @param mediaItem
|
||||
* @return
|
||||
*/
|
||||
public static boolean hasValidUri(MediaItem mediaItem) {
|
||||
MediaItem.LocalConfiguration localConfiguration = mediaItem.localConfiguration;
|
||||
if(localConfiguration != null){
|
||||
if(CommonUtils.isUriFormat(localConfiguration.uri)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isUriFormat(Uri parsedUri) {
|
||||
// 3. 检查 URI 是否具有正确的格式
|
||||
try {
|
||||
if (parsedUri.getScheme() == null) {
|
||||
LogMsg( "URI has no valid scheme.");
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogMsg( "URI parsing failed: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,5 +13,7 @@ public class MyValue {
|
||||
|
||||
//暂停或者停止
|
||||
public final static int PLAY_STATUS_CODE_PAUSE = -3;
|
||||
|
||||
|
||||
//-----------------------------PlayActivity
|
||||
}
|
||||
|
||||
@ -0,0 +1,169 @@
|
||||
package com.hi.music.player.media3;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.datasource.DataSource;
|
||||
import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.datasource.ResolvingDataSource;
|
||||
import androidx.media3.datasource.cache.CacheDataSource;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionManagerProvider;
|
||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
||||
import androidx.media3.exoplayer.source.MediaSource;
|
||||
import androidx.media3.exoplayer.source.MediaSourceFactory;
|
||||
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
|
||||
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
|
||||
|
||||
import com.hi.music.player.api.RequestListener;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
||||
import com.hi.music.player.network.JsonHelper;
|
||||
import com.hi.music.player.network.RetrofitManager;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
|
||||
public class DynamicMediaSourceFactory implements MediaSource.Factory {
|
||||
// private final CacheDataSource.Factory cacheDataSourceFactory;
|
||||
// private final ExoPlayer player;
|
||||
private DefaultMediaSourceFactory mediaSourceFactory;
|
||||
|
||||
// public DynamicMediaSourceFactory(DefaultMediaSourceFactory factory,CacheDataSource.Factory cacheDataSourceFactory, ExoPlayer exoPlayer) {
|
||||
// this.cacheDataSourceFactory = cacheDataSourceFactory;
|
||||
// this.player = exoPlayer;
|
||||
// this.mediaSourceFactory = factory;
|
||||
// }
|
||||
public DynamicMediaSourceFactory(DefaultMediaSourceFactory factory) {
|
||||
|
||||
this.mediaSourceFactory = factory;
|
||||
}
|
||||
|
||||
|
||||
@UnstableApi
|
||||
@Override
|
||||
public MediaSource.Factory setDrmSessionManagerProvider(DrmSessionManagerProvider drmSessionManagerProvider) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@UnstableApi
|
||||
@Override
|
||||
public MediaSource.Factory setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@UnstableApi
|
||||
@Override
|
||||
public int[] getSupportedTypes() {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
@UnstableApi
|
||||
@Override
|
||||
public MediaSource createMediaSource(MediaItem mediaItem) {
|
||||
|
||||
|
||||
CommonUtils.LogMsg("------createMediaSource----------=" + mediaItem.mediaId + "---------" + mediaItem.mediaMetadata.title);
|
||||
// MediaSource realMediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
|
||||
// .createMediaSource(MediaItem.fromUri(""));
|
||||
// RetrofitManager.getInstance().getPlayUrl(mediaItem.mediaId, new RequestListener<ResponseBody>() {
|
||||
//
|
||||
// @Override
|
||||
// public void onFail(String errorMsg) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(ResponseBody data) {
|
||||
// JSONObject jsonObject = CommonUtils.toJsonObject(data);
|
||||
// if (jsonObject != null) {
|
||||
// ResponsePlayUrl responsePlayUrl = JsonHelper.ResolvePlayUrlJson(jsonObject);
|
||||
// if (responsePlayUrl == null) {
|
||||
// // TODO: 2024/9/27
|
||||
// return;
|
||||
// }
|
||||
// String uri = "";
|
||||
// if (responsePlayUrl.getAudioUrlMedium() != null) {
|
||||
// uri = responsePlayUrl.getAudioUrlMedium();
|
||||
// } else {
|
||||
// uri = responsePlayUrl.getAudioUrlLow();
|
||||
// }
|
||||
// CommonUtils.LogMsg("------createMediaSource----------="+mediaItem.mediaId+"---------"+uri);
|
||||
// ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
|
||||
// .createMediaSource(MediaItem.fromUri(uri));
|
||||
// player.setMediaSource(mediaSource);
|
||||
// player.prepare();
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
// });
|
||||
|
||||
// return new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
|
||||
// .createMediaSource(MediaItem.fromUri(responsePlayUrl.getAudioUrlMedium()));
|
||||
// 可以在这里根据 mediaItem 的 ID 动态生成新的 URI
|
||||
String updatedUri = "https://rr1---sn-tt1e7nlz.googlevideo.com/videoplayback?expire=1727628605&ei=3TD5ZuWFEe-yzN0P27WuqQ4&ip=146.19.167.8&id=o-ANGM0PjEvsfYH7TmYV_DFuD-65tipJeeLe2URDOk90sL&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=xj&mm=31%2C29&mn=sn-tt1e7nlz%2Csn-vgqsknsk&ms=au%2Crdu&mv=m&mvi=1&pl=24&pcm2=no&gcr=us&initcwndbps=7610000&vprv=1&svpuc=1&mime=audio%2Fmp4&rqh=1&gir=yes&clen=5440168&dur=335.973&lmt=1709326903801285&mt=1727606690&fvip=5&keepalive=yes&fexp=51299152&c=ANDROID_MUSIC&txp=2318224&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cpcm2%2Cgcr%2Cvprv%2Csvpuc%2Cmime%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhALmM_S8Cmagr60muB3wDOby0OdcjF-x6f7TcEenixH0KAiAnR0-hmA03MeVzSg2wi5ncJ4Ve5FFlpZnlSoRNGWgGhQ%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=ABPmVW0wRQIhAPv5slfEnf8_E7o6yjEkussQ6JIFFaSY6QtP9HXncTTcAiAjlhMa71t76Wu1R1rcmsHoO6pyxjhGYouio4D0deJqEA%3D%3D";
|
||||
Uri updateUri = null;
|
||||
|
||||
MediaItem.Builder builder = mediaItem.buildUpon();
|
||||
if (mediaItem.localConfiguration != null) {
|
||||
updateUri = mediaItem.localConfiguration.uri;
|
||||
builder.setUri(updateUri);
|
||||
CommonUtils.LogErrorMsg("----updateUri=成功 builder="+mediaItem.mediaId+"--updateUri="+updateUri);
|
||||
}else {
|
||||
CommonUtils.LogErrorMsg("----updateUri=null builder="+mediaItem.mediaId);
|
||||
}
|
||||
|
||||
return mediaSourceFactory.createMediaSource(builder.build());
|
||||
|
||||
}
|
||||
|
||||
// @UnstableApi
|
||||
// @Override
|
||||
// public DataSource createDataSource() {
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//// RetrofitManager.getInstance().getPlayUrl(mediaItem.mediaId, new RequestListener<ResponseBody>() {
|
||||
////
|
||||
//// @Override
|
||||
//// public void onFail(String errorMsg) {
|
||||
////
|
||||
//// }
|
||||
////
|
||||
//// @Override
|
||||
//// public void onSuccess(ResponseBody data) {
|
||||
//// JSONObject jsonObject = CommonUtils.toJsonObject(data);
|
||||
//// if (jsonObject != null) {
|
||||
//// ResponsePlayUrl responsePlayUrl = JsonHelper.ResolvePlayUrlJson(jsonObject);
|
||||
//// if (responsePlayUrl == null) {
|
||||
//// // TODO: 2024/9/27
|
||||
//// return;
|
||||
//// }
|
||||
//// String uri = "";
|
||||
//// if (responsePlayUrl.getAudioUrlMedium() != null) {
|
||||
//// uri = responsePlayUrl.getAudioUrlMedium();
|
||||
//// } else {
|
||||
//// uri = responsePlayUrl.getAudioUrlLow();
|
||||
//// }
|
||||
//// CommonUtils.LogMsg("------createMediaSource----------="+mediaItem.mediaId+"---------"+uri);
|
||||
//// ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
|
||||
//// .createMediaSource(MediaItem.fromUri(uri));
|
||||
//// player.setMediaSource(mediaSource);
|
||||
//// player.prepare();
|
||||
////
|
||||
//// }
|
||||
////
|
||||
////
|
||||
//// }
|
||||
//// });
|
||||
// return null;
|
||||
// }
|
||||
}
|
||||
@ -24,6 +24,7 @@ import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
||||
import com.hi.music.player.network.RetrofitManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@ -61,7 +62,6 @@ public class MyMediaControllerManager {
|
||||
// playerView.setPlayer(controllerFuture.get());
|
||||
try {
|
||||
mediaController = controllerFuture.get();
|
||||
|
||||
statusListener.onMediaControllerComplete(true);
|
||||
CommonUtils.LogMsg("=-----mediaController+" + mediaController);
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
@ -98,19 +98,16 @@ public class MyMediaControllerManager {
|
||||
if (isPlaying) {
|
||||
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PLAYING);
|
||||
// TODO: 2024/9/26 自动播放完成切歌到下一首播放没有触发这里请求下一首
|
||||
// 播放器开始播放
|
||||
MediaItem currentItem = mediaController.getCurrentMediaItem();
|
||||
int currentMediaItemIndex = mediaController.getCurrentMediaItemIndex();
|
||||
if (currentMediaItemIndex < playList.size() - 1) {
|
||||
//代表有下一首
|
||||
if (!mediaController.hasNextMediaItem()) {
|
||||
//没有更新下一首的uri
|
||||
if (mediaController.hasNextMediaItem()) {
|
||||
MediaItem mediaItemAt = mediaController.getMediaItemAt(mediaController.getNextMediaItemIndex());
|
||||
if (!CommonUtils.hasValidUri(mediaItemAt)) {
|
||||
CommonUtils.LogMsg("----0000000000-请求下一首的uri" + mediaController.getMediaItemCount());
|
||||
int nextIndex = currentMediaItemIndex + 1;
|
||||
mListener.onRequestNextUri(playList.get(nextIndex).getVideoId(), nextIndex,false);
|
||||
int nextIndex = mediaController.getNextMediaItemIndex();
|
||||
mListener.onRequestNextUri(mediaController.getMediaItemAt(nextIndex).mediaId, nextIndex, false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// 播放器暂停或停止
|
||||
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PAUSE);
|
||||
@ -119,7 +116,6 @@ public class MyMediaControllerManager {
|
||||
|
||||
@Override
|
||||
public void onPlaybackStateChanged(int playbackState) {
|
||||
CommonUtils.LogMsg("----playbackState" + playbackState + "------------" + mediaController.getMediaItemCount());
|
||||
mListener.onPlayStatus(playbackState);
|
||||
|
||||
}
|
||||
@ -154,32 +150,30 @@ public class MyMediaControllerManager {
|
||||
// *
|
||||
// * @param playUrl
|
||||
// */
|
||||
// public void UpdateAudioUrl(ResponsePlayUrl playUrl) {
|
||||
//
|
||||
// CommonUtils.LogMsg("-------------更新播放列表中的音频 mediaController.getMediaItemCount()=" + mediaController.getMediaItemCount());
|
||||
// for (int i = 0; i < mediaController.getMediaItemCount(); i++) {
|
||||
// MediaItem mediaItemAt = mediaController.getMediaItemAt(i);
|
||||
// if (mediaItemAt.mediaId.equals(playUrl.getVideoId())) {
|
||||
//
|
||||
// MediaItem.Builder builder = mediaItemAt.buildUpon();
|
||||
//// mediaController.removeMediaItem(i);
|
||||
//// MediaItem.Builder builder = new MediaItem.Builder();
|
||||
// builder.setMediaId(playUrl.getVideoId());
|
||||
// if (playUrl.getAudioUrlMedium() != null) {
|
||||
// builder.setUri(playUrl.getAudioUrlMedium());
|
||||
// } else {
|
||||
// builder.setUri(playUrl.getAudioUrlLow());
|
||||
// }
|
||||
// mediaController.replaceMediaItem(i, builder.build());
|
||||
// CharSequence title = mediaController.getMediaItemAt(i).mediaMetadata.title;
|
||||
// CommonUtils.LogMsg("-------------更新播放列表中的音频url= i=" + i + "---title=" + title + "----mediaController.size=" + mediaController.getMediaItemCount() + "---" + mediaController);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
public void UpdateAudioUrl(ResponsePlayUrl playUrl, int index) {
|
||||
CommonUtils.LogMsg("-------------更新播放列表中的音频url= index=" + index);
|
||||
for (int i = 0; i < mediaController.getMediaItemCount(); i++) {
|
||||
MediaItem mediaItemAt = mediaController.getMediaItemAt(i);
|
||||
if (mediaItemAt.mediaId.equals(playUrl.getVideoId())) {
|
||||
|
||||
MediaItem.Builder builder = mediaItemAt.buildUpon();
|
||||
builder.setMediaId(playUrl.getVideoId());
|
||||
if (playUrl.getAudioUrlMedium() != null) {
|
||||
builder.setUri(playUrl.getAudioUrlMedium());
|
||||
} else {
|
||||
builder.setUri(playUrl.getAudioUrlLow());
|
||||
}
|
||||
CharSequence title = mediaController.getMediaItemAt(i).mediaMetadata.title;
|
||||
CommonUtils.LogMsg("-------------更新播放列表中的音频url= i=" + i + "---id=" + playUrl.getVideoId() + "----mediaController.size=" + mediaController.getMediaItemCount());
|
||||
mediaController.replaceMediaItem(i, builder.build());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlayList(List<ResponsePlayListInfo> playList) {
|
||||
this.playList = playList;
|
||||
addMusicPlayList(playList);
|
||||
}
|
||||
|
||||
public List<ResponsePlayListInfo> getPlayList() {
|
||||
@ -192,7 +186,7 @@ public class MyMediaControllerManager {
|
||||
|
||||
/**
|
||||
* 添加播放列表(不带音频url)
|
||||
* 注意没有更新有效uri的不会被实际添加到mediaController
|
||||
* 注意没有setUri的不会被实际添加到mediaController,
|
||||
*
|
||||
* @param playUrl
|
||||
*/
|
||||
@ -214,7 +208,6 @@ public class MyMediaControllerManager {
|
||||
MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
||||
|
||||
MediaMetadata_builder.setArtist(listInfo.getSingerName());
|
||||
|
||||
/**
|
||||
* 这里使用setDescription保存歌曲时长的分秒字符串
|
||||
*/
|
||||
@ -228,49 +221,53 @@ public class MyMediaControllerManager {
|
||||
// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
||||
builder.setMediaMetadata(MediaMetadata_builder.build());
|
||||
mediaController.addMediaItem(builder.build());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 添加播放列表(不带音频url)
|
||||
// * 注意没有更新有效uri的不会被实际添加到mediaController
|
||||
// *
|
||||
// * @param listInfo
|
||||
// */
|
||||
// @OptIn(markerClass = UnstableApi.class)
|
||||
// public void addMusicPlayList(List<ResponsePlayListInfo> listInfo) {
|
||||
// playList = listInfo;
|
||||
// List<MediaItem> mediaItems = new ArrayList<>();
|
||||
// for (int i = 0; i < listInfo.size(); i++) {
|
||||
// ResponsePlayListInfo playInfo = listInfo.get(i);
|
||||
//
|
||||
// MediaItem.Builder builder = new MediaItem.Builder();
|
||||
//
|
||||
// //唯一标识符
|
||||
// builder.setMediaId(playInfo.getVideoId());
|
||||
//
|
||||
// MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
||||
//
|
||||
// MediaMetadata_builder.setArtist(playInfo.getSingerName());
|
||||
// MediaMetadata_builder.setDurationMs(playInfo.getDurationMs());
|
||||
//// MediaMetadata_builder.setArtworkUri(Uri.parse(playInfo.getCovert()));
|
||||
// MediaMetadata_builder.setArtworkUri(Uri.parse("https://t7.baidu.com/it/u=2604797219,1573897854&fm=193&f=GIF"));
|
||||
// MediaMetadata_builder.setTitle(playInfo.getSongTitle());
|
||||
//
|
||||
// CommonUtils.LogMsg("----------添加播放列表 i=" + i + "---" + playInfo.getSongTitle() + "-------VideoId=" + playInfo.getVideoId());
|
||||
//// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
||||
// builder.setMediaMetadata(MediaMetadata_builder.build());
|
||||
// mediaController.addMediaItem(builder.build());
|
||||
//// mediaItems.add(builder.build());
|
||||
// }
|
||||
//// mediaController.setMediaItems(mediaItems);
|
||||
// }
|
||||
/**
|
||||
* 添加播放列表(不带音频url)
|
||||
* 注意没有setUri的不会被实际添加到mediaController(mediaController.getMediaItemCount())
|
||||
* 这里setUri 一个占位
|
||||
*
|
||||
* @param listInfo
|
||||
*/
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
public void addMusicPlayList(List<ResponsePlayListInfo> listInfo) {
|
||||
playList = listInfo;
|
||||
List<MediaItem> mediaItems = new ArrayList<>();
|
||||
for (int i = 0; i < listInfo.size(); i++) {
|
||||
ResponsePlayListInfo playInfo = listInfo.get(i);
|
||||
|
||||
MediaItem.Builder builder = new MediaItem.Builder();
|
||||
|
||||
//唯一标识符
|
||||
builder.setMediaId(playInfo.getVideoId());
|
||||
builder.setUri("-------test-----");
|
||||
MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
||||
|
||||
MediaMetadata_builder.setArtist(playInfo.getSingerName());
|
||||
MediaMetadata_builder.setDescription(playInfo.getDuration());
|
||||
MediaMetadata_builder.setDurationMs(playInfo.getDurationMs());
|
||||
MediaMetadata_builder.setArtworkUri(Uri.parse(playInfo.getCovert()));
|
||||
MediaMetadata_builder.setTitle(playInfo.getSongTitle());
|
||||
|
||||
CommonUtils.LogMsg("----------添加播放列表 i=" + i + "---" + playInfo.getSongTitle() + "-------VideoId=" + playInfo.getVideoId());
|
||||
// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
||||
builder.setMediaMetadata(MediaMetadata_builder.build());
|
||||
mediaController.addMediaItem(builder.build());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void play() {
|
||||
if (!mediaController.isPlaying()) {
|
||||
CommonUtils.LogMsg("-----------prepare");
|
||||
mediaController.prepare();
|
||||
mediaController.play();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -279,21 +276,32 @@ public class MyMediaControllerManager {
|
||||
if (mediaController.isPlaying())
|
||||
mediaController.pause();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (mediaController.isPlaying())
|
||||
mediaController.stop();
|
||||
}
|
||||
|
||||
public void playNext() {
|
||||
if (mediaController.hasNextMediaItem()) {
|
||||
int nextMediaItemIndex = mediaController.getNextMediaItemIndex();
|
||||
MediaItem mediaItemAt = mediaController.getMediaItemAt(nextMediaItemIndex);
|
||||
boolean b = CommonUtils.hasValidUri(mediaItemAt);
|
||||
if (b) {
|
||||
mediaController.seekToNextMediaItem();
|
||||
} else {
|
||||
int currentMediaItemIndex = mediaController.getCurrentMediaItemIndex();
|
||||
if (currentMediaItemIndex < playList.size() - 1) {
|
||||
//应该有下一首,可能是歌曲url请求失败,需要重新请求
|
||||
int nextIndex = currentMediaItemIndex + 1;
|
||||
mListener.onRequestNextUri(playList.get(nextIndex).getVideoId(), nextIndex,true);
|
||||
CommonUtils.LogMsg("-------------应该有下一首,可能是歌曲url请求失败,需要重新请求");
|
||||
return;
|
||||
}
|
||||
CommonUtils.LogMsg("-------------有下一首,但是歌曲url请求失败,需要重新请求");
|
||||
mListener.onRequestNextUri(mediaController.getMediaItemAt(nextMediaItemIndex).mediaId, nextMediaItemIndex, true);
|
||||
|
||||
} else {
|
||||
// int currentMediaItemIndex = mediaController.getCurrentMediaItemIndex();
|
||||
// if (currentMediaItemIndex < playList.size() - 1) {
|
||||
// //应该有下一首,可能是歌曲url请求失败,需要重新请求
|
||||
// int nextIndex = currentMediaItemIndex + 1;
|
||||
// mListener.onRequestNextUri(playList.get(nextIndex).getVideoId(), nextIndex, true);
|
||||
// CommonUtils.LogMsg("-------------应该有下一首,可能是歌曲url请求失败,需要重新请求");
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -305,4 +313,29 @@ public class MyMediaControllerManager {
|
||||
mediaController.play();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 播放指定播放列表位置的歌曲
|
||||
*
|
||||
* @param index
|
||||
*/
|
||||
public void playPositionMusic(int index) {
|
||||
if (index >= mediaController.getMediaItemCount()) {
|
||||
CommonUtils.LogErrorMsg("-------------数组越界");
|
||||
return;
|
||||
}
|
||||
|
||||
stop();
|
||||
mediaController.prepare();
|
||||
mediaController.seekTo(index);
|
||||
|
||||
MediaItem mediaItemAt = mediaController.getMediaItemAt(index);
|
||||
boolean b = CommonUtils.hasValidUri(mediaItemAt);
|
||||
if (!b) {
|
||||
CommonUtils.LogMsg("-------------播放指定播放列表位置的歌曲,需要重新请求");
|
||||
mListener.onRequestNextUri(mediaItemAt.mediaId, index, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,48 +5,59 @@ import android.content.Intent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.AudioAttributes;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.MediaMetadata;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.database.StandaloneDatabaseProvider;
|
||||
import androidx.media3.datasource.DataSource;
|
||||
import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.datasource.DefaultDataSource;
|
||||
import androidx.media3.datasource.DefaultHttpDataSource;
|
||||
import androidx.media3.datasource.ResolvingDataSource;
|
||||
import androidx.media3.datasource.cache.CacheDataSource;
|
||||
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor;
|
||||
import androidx.media3.datasource.cache.SimpleCache;
|
||||
import androidx.media3.exoplayer.DefaultLoadControl;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
|
||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
||||
import androidx.media3.exoplayer.source.MediaSource;
|
||||
import androidx.media3.extractor.ExtractorsFactory;
|
||||
import androidx.media3.extractor.mkv.MatroskaExtractor;
|
||||
import androidx.media3.session.MediaSession;
|
||||
import androidx.media3.session.MediaSessionService;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PlaybackService extends MediaSessionService {
|
||||
private MediaSession mediaSession = null;
|
||||
private ExoPlayer player;
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
player = new ExoPlayer.Builder(this).build();
|
||||
|
||||
DynamicMediaSourceFactory customMediaSourceFactory = new DynamicMediaSourceFactory(new DefaultMediaSourceFactory(new DefaultHttpDataSource.Factory()));
|
||||
|
||||
DefaultMediaSourceFactory defaultMediaSourceFactory1 = new DefaultMediaSourceFactory(getUrlFactory());
|
||||
|
||||
|
||||
// 创建 DefaultLoadControl,配置缓冲参数
|
||||
DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
|
||||
.setBufferDurationsMs(10000, // minBufferMs: 播放前的最小缓冲时间(毫秒)
|
||||
60000, // maxBufferMs: 最大缓冲时间(毫秒)
|
||||
10000, // bufferForPlaybackMs: 播放时的目标缓冲时间(毫秒)
|
||||
5000) // bufferForPlaybackAfterRebufferMs: 重新缓冲后的缓冲时间(毫秒)
|
||||
.build();
|
||||
player = new ExoPlayer.Builder(this)
|
||||
// .setMediaSourceFactory(customMediaSourceFactory)
|
||||
// .setLoadControl(loadControl)
|
||||
.build();
|
||||
mediaSession = new MediaSession.Builder(this, player)
|
||||
.setCallback(new MediaSession.Callback() {
|
||||
@Override
|
||||
public ListenableFuture<List<MediaItem>> onAddMediaItems(MediaSession mediaSession, MediaSession.ControllerInfo controller, List<MediaItem> mediaItems) {
|
||||
|
||||
CommonUtils.LogMsg("--------实际添加的媒体项="+mediaItems.size()+"----"+mediaSession.getPlayer().getMediaItemCount());
|
||||
return MediaSession.Callback.super.onAddMediaItems(mediaSession, controller, mediaItems);
|
||||
}
|
||||
|
||||
|
||||
|
||||
})
|
||||
.build();
|
||||
|
||||
// player = new ExoPlayer.Builder(this)
|
||||
@ -69,12 +80,39 @@ public class PlaybackService extends MediaSessionService {
|
||||
// .build();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private DataSource.Factory getUrlFactory() {
|
||||
CommonUtils.LogMsg("--------getUrlFactory");
|
||||
return new ResolvingDataSource.Factory(getCacheDataSource(), new ResolvingDataSource.Resolver() {
|
||||
@Override
|
||||
public DataSpec resolveDataSpec(DataSpec dataSpec) {
|
||||
|
||||
CommonUtils.LogMsg("--------resolveDataSpec=" + dataSpec.key);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private CacheDataSource.Factory getCacheDataSource() {
|
||||
// 1. 创建缓存对象
|
||||
SimpleCache simpleCache = new SimpleCache(
|
||||
new File(MusicApplication.myApplication.getCacheDir(), "media3_cache"), // 设置缓存目录
|
||||
new LeastRecentlyUsedCacheEvictor(100 * 1024 * 1024), // 设置最大缓存大小(例如 100MB)
|
||||
new StandaloneDatabaseProvider(MusicApplication.myApplication));
|
||||
|
||||
// 2. 创建 DataSource.Factory,用于加载媒体资源
|
||||
DataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(MusicApplication.myApplication);
|
||||
|
||||
// 3. 创建 CacheDataSource.Factory,包含缓存功能
|
||||
return new CacheDataSource.Factory()
|
||||
.setCache(simpleCache)
|
||||
.setUpstreamDataSourceFactory(dataSourceFactory) // 用于从网络加载的工厂
|
||||
.setCacheWriteDataSinkFactory(null); // 默认写入缓存
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
||||
@ -0,0 +1,73 @@
|
||||
package com.hi.music.player.media3;
|
||||
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.datasource.DataSource;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionManagerProvider;
|
||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
||||
import androidx.media3.exoplayer.source.MediaSource;
|
||||
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
|
||||
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
|
||||
|
||||
public class testSourceFactory implements DataSource.Factory {
|
||||
// private final CacheDataSource.Factory cacheDataSourceFactory;
|
||||
// private final ExoPlayer player;
|
||||
private DefaultMediaSourceFactory mediaSourceFactory;
|
||||
|
||||
// public DynamicMediaSourceFactory(DefaultMediaSourceFactory factory,CacheDataSource.Factory cacheDataSourceFactory, ExoPlayer exoPlayer) {
|
||||
// this.cacheDataSourceFactory = cacheDataSourceFactory;
|
||||
// this.player = exoPlayer;
|
||||
// this.mediaSourceFactory = factory;
|
||||
// }
|
||||
public testSourceFactory(DefaultMediaSourceFactory factory) {
|
||||
|
||||
this.mediaSourceFactory = factory;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@UnstableApi
|
||||
@Override
|
||||
public DataSource createDataSource() {
|
||||
|
||||
|
||||
|
||||
|
||||
// RetrofitManager.getInstance().getPlayUrl(mediaItem.mediaId, new RequestListener<ResponseBody>() {
|
||||
//
|
||||
// @Override
|
||||
// public void onFail(String errorMsg) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(ResponseBody data) {
|
||||
// JSONObject jsonObject = CommonUtils.toJsonObject(data);
|
||||
// if (jsonObject != null) {
|
||||
// ResponsePlayUrl responsePlayUrl = JsonHelper.ResolvePlayUrlJson(jsonObject);
|
||||
// if (responsePlayUrl == null) {
|
||||
// // TODO: 2024/9/27
|
||||
// return;
|
||||
// }
|
||||
// String uri = "";
|
||||
// if (responsePlayUrl.getAudioUrlMedium() != null) {
|
||||
// uri = responsePlayUrl.getAudioUrlMedium();
|
||||
// } else {
|
||||
// uri = responsePlayUrl.getAudioUrlLow();
|
||||
// }
|
||||
// CommonUtils.LogMsg("------createMediaSource----------="+mediaItem.mediaId+"---------"+uri);
|
||||
// ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
|
||||
// .createMediaSource(MediaItem.fromUri(uri));
|
||||
// player.setMediaSource(mediaSource);
|
||||
// player.prepare();
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
// });
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -244,7 +244,6 @@ public class JsonHelper {
|
||||
if (mimeType.contains("audio/mp4")) {
|
||||
String url = jsonIndex.getString("url");
|
||||
boolean audioQuality1 = jsonIndex.has("audioQuality");
|
||||
CommonUtils.LogMsg("------------itag="+itag+"---------audioQuality1="+audioQuality1);
|
||||
if (jsonIndex.has("audioQuality")) {
|
||||
String audioQuality = jsonIndex.getString("audioQuality");
|
||||
if (audioQuality.equals("AUDIO_QUALITY_MEDIUM")) {
|
||||
|
||||
@ -15,12 +15,12 @@ public class ObserverWrapper<T> implements Observer<T> {
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
CommonUtils.LogMsg("----------onSubscribe");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(T t) {
|
||||
CommonUtils.LogMsg("----------onNext");
|
||||
|
||||
requestListener.onSuccess(t);
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ public class ObserverWrapper<T> implements Observer<T> {
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
CommonUtils.LogMsg("----------onComplete");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -57,8 +57,6 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
//接口返回的播放列表(没有音频数据)
|
||||
private List<ResponsePlayListInfo> mPlayList;
|
||||
|
||||
//播放列对应的音频数据
|
||||
private List<ResponsePlayUrl> mPlayUrls;
|
||||
|
||||
private ResponsePlayUrl mCurPlayInfo;
|
||||
private ResponsePlayListInfo musicInfo;
|
||||
@ -66,6 +64,8 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
private Runnable mRunnable;
|
||||
private MyMediaControllerManager mediaControllerManager;
|
||||
|
||||
private AdapterPlayList adapterPlayList;
|
||||
|
||||
|
||||
//播放列表ui初始化
|
||||
private boolean initPlayList = false;
|
||||
@ -170,6 +170,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
break;
|
||||
|
||||
case Player.STATE_ENDED:
|
||||
//播放完成
|
||||
vb.btnPlay.setSelected(false);
|
||||
CommonUtils.LogMsg("-------------playStatus=STATE_ENDED 播放完成");
|
||||
mHandler.removeCallbacks(mRunnable); // 停止更新
|
||||
@ -199,7 +200,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
|
||||
@Override
|
||||
public void onChangeMusic(MediaItem mediaItem) {
|
||||
CommonUtils.LogMsg("111111111-------22222---"+mediaItem.mediaMetadata.title +"---id="+mediaItem.mediaId);
|
||||
CommonUtils.LogMsg("歌曲切换-" + mediaItem.mediaMetadata.title + "---id=" + mediaItem.mediaId);
|
||||
loadInfo(mediaItem);
|
||||
}
|
||||
|
||||
@ -250,7 +251,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
private void loadInfo(MediaItem mediaItem) {
|
||||
|
||||
MediaMetadata mediaMetadata = mediaItem.mediaMetadata;
|
||||
CommonUtils.LogMsg("--------------加载当前播放歌曲信息 " + mediaMetadata.description);
|
||||
CommonUtils.LogMsg("--------------加载当前播放歌曲信息 ");
|
||||
if (mediaMetadata.artworkUri != null) {
|
||||
loadCovert(mediaMetadata.artworkUri.toString());
|
||||
}
|
||||
@ -263,7 +264,9 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
vb.playProgress.setMax((int) durationMs);
|
||||
vb.progressBarBuffer.setMax((int) durationMs);
|
||||
}
|
||||
|
||||
if (vb.layoutPlayList.linearLayout.getVisibility() == View.VISIBLE) {
|
||||
updatePlayListUi();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -297,6 +300,11 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
);
|
||||
vb.rootLayout.setBackground(gradientDrawable);
|
||||
|
||||
if (vb.layoutPlayList.linearLayout.getVisibility() == View.VISIBLE) {
|
||||
updatePlayListColor();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@ -355,6 +363,9 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
} else {
|
||||
mediaControllerManager.pause();
|
||||
}
|
||||
if(adapterPlayList!= null){
|
||||
adapterPlayList.updateCurMusicAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -374,52 +385,14 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
|
||||
if (!initPlayList) {
|
||||
List<ResponsePlayListInfo> playList = mediaControllerManager.getPlayList();
|
||||
AdapterPlayList adapterPlayList = new AdapterPlayList();
|
||||
adapterPlayList = new AdapterPlayList();
|
||||
vb.layoutPlayList.recyclerList.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication));
|
||||
adapterPlayList.addData(playList);
|
||||
vb.layoutPlayList.recyclerList.setAdapter(adapterPlayList);
|
||||
vb.layoutPlayList.imPlay.setOnClickListener(this);
|
||||
initPlayList = true;
|
||||
}
|
||||
|
||||
MediaItem currentMediaItem = mediaControllerManager.getMediaController().getCurrentMediaItem();
|
||||
if (currentMediaItem != null) {
|
||||
Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri;
|
||||
vb.layoutPlayList.topSongName.setText(currentMediaItem.mediaMetadata.title);
|
||||
vb.layoutPlayList.topSingerName.setText(currentMediaItem.mediaMetadata.artist);
|
||||
|
||||
|
||||
vb.layoutPlayList.topLayout.setBackgroundColor(darkerColor);
|
||||
GradientDrawable gradientDrawable = new GradientDrawable(
|
||||
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||
new int[]{darkerColor, darkerColor}
|
||||
);
|
||||
vb.rootLayout.setBackground(gradientDrawable);
|
||||
Drawable newDrawable = CommonUtils.getNewDrawable(lighterColor, 24f, 24f, 0, 0);
|
||||
vb.layoutPlayList.listLayout.setBackground(newDrawable);
|
||||
|
||||
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10))))
|
||||
.load(artworkUri)
|
||||
.placeholder(R.mipmap.ic_launcher)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.layoutPlayList.topIm);
|
||||
}
|
||||
vb.layoutPlayList.imPlay.setSelected(mediaControllerManager.getMediaController().isPlaying());
|
||||
updatePlayListUi();
|
||||
|
||||
} else {
|
||||
|
||||
@ -434,6 +407,56 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新播放列表的显示
|
||||
*/
|
||||
private void updatePlayListUi() {
|
||||
CommonUtils.LogMsg("----------更新播放列表的显示");
|
||||
|
||||
MediaItem currentMediaItem = mediaControllerManager.getMediaController().getCurrentMediaItem();
|
||||
if (currentMediaItem != null) {
|
||||
if (adapterPlayList != null) {
|
||||
adapterPlayList.setCurVideId(currentMediaItem.mediaId);
|
||||
}
|
||||
Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri;
|
||||
vb.layoutPlayList.topSongName.setText(currentMediaItem.mediaMetadata.title);
|
||||
vb.layoutPlayList.topSingerName.setText(currentMediaItem.mediaMetadata.artist);
|
||||
updatePlayListColor();
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10))))
|
||||
.load(artworkUri)
|
||||
.placeholder(R.mipmap.ic_launcher)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.layoutPlayList.topIm);
|
||||
}
|
||||
vb.layoutPlayList.imPlay.setSelected(mediaControllerManager.getMediaController().isPlaying());
|
||||
}
|
||||
|
||||
private void updatePlayListColor() {
|
||||
vb.layoutPlayList.topLayout.setBackgroundColor(darkerColor);
|
||||
GradientDrawable gradientDrawable = new GradientDrawable(
|
||||
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||
new int[]{darkerColor, darkerColor}
|
||||
);
|
||||
vb.rootLayout.setBackground(gradientDrawable);
|
||||
Drawable newDrawable = CommonUtils.getNewDrawable(lighterColor, 24f, 24f, 0, 0);
|
||||
vb.layoutPlayList.listLayout.setBackground(newDrawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
@ -37,9 +37,6 @@ public class VMPlay extends ViewModel {
|
||||
String videoId = responseSingle.getVideoId();
|
||||
String params = responseSingle.getParams();
|
||||
String musicVideoType = responseSingle.getMusicVideoType();
|
||||
|
||||
CommonUtils.LogMsg("111111111-------0000---"+responseSingle.getSongTitle() +"---id="+videoId);
|
||||
|
||||
RetrofitManager.getInstance().getPlayList(params, playlistId, videoId, musicVideoType, new RequestListener<ResponseBody>() {
|
||||
|
||||
@Override
|
||||
@ -54,7 +51,6 @@ public class VMPlay extends ViewModel {
|
||||
List<ResponsePlayListInfo> responsePlayListInfos = JsonHelper.ResolvePlayListJson(jsonObject);
|
||||
MyMediaControllerManager.getInstance().setPlayList(responsePlayListInfos);
|
||||
_playList.setValue(responsePlayListInfos);
|
||||
CommonUtils.LogMsg("111111111-------1111----"+responsePlayListInfos.get(0).getSongTitle() +"---id="+responsePlayListInfos.get(0).getVideoId());
|
||||
getPlayUrl(responseSingle.getVideoId(),0,true);
|
||||
} else {
|
||||
_playList.setValue(null);
|
||||
@ -83,7 +79,8 @@ public class VMPlay extends ViewModel {
|
||||
// TODO: 2024/9/27
|
||||
return;
|
||||
}
|
||||
MyMediaControllerManager.getInstance().addMusicToPlayList(responsePlayUrl,playListIndex);
|
||||
MyMediaControllerManager.getInstance().UpdateAudioUrl(responsePlayUrl,playListIndex);
|
||||
// MyMediaControllerManager.getInstance().addMusicToPlayList(responsePlayUrl,playListIndex);
|
||||
customerUrlInfo.setPlayUrl(responsePlayUrl);
|
||||
customerUrlInfo.setPlayMusicIndex(playListIndex);
|
||||
|
||||
|
||||
@ -2,15 +2,15 @@
|
||||
<FrameLayout 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:id="@+id/root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/root_layout"
|
||||
android:background="@color/black"
|
||||
tools:context=".ui.activity.PlayActivity">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/content_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
@ -51,16 +51,6 @@
|
||||
app:show_shuffle_button="true" />
|
||||
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBarLoading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminateTint="@color/white"
|
||||
app:layout_constraintBottom_toBottomOf="@id/im_covert"
|
||||
app:layout_constraintLeft_toLeftOf="@id/im_covert"
|
||||
app:layout_constraintRight_toRightOf="@id/im_covert"
|
||||
app:layout_constraintTop_toTopOf="@id/im_covert" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_song_name"
|
||||
android:layout_width="wrap_content"
|
||||
@ -186,4 +176,13 @@
|
||||
<include
|
||||
android:id="@+id/layout_playList"
|
||||
layout="@layout/dialog_play_list" />
|
||||
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBarLoading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
android:indeterminateTint="@color/white" />
|
||||
</FrameLayout>
|
||||
@ -25,6 +25,7 @@
|
||||
android:id="@+id/top_im"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:scaleType="fitXY"
|
||||
android:layout_marginStart="10dp"
|
||||
android:src="@mipmap/ic_launcher" />
|
||||
|
||||
@ -64,11 +65,11 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/im_play"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="42dp"
|
||||
android:layout_marginEnd="22dp"
|
||||
android:padding="20dp"
|
||||
android:src="@drawable/selector_small_play" />
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
@ -1,39 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="70dp"
|
||||
android:id="@+id/item_layout"
|
||||
android:paddingStart="20dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="60dp"
|
||||
android:id="@+id/im_covert"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_height="60dp" />
|
||||
android:src="@mipmap/ic_launcher" />
|
||||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/lottieAnimationView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="center"
|
||||
android:padding="5dp"
|
||||
android:layout_alignTop="@id/im_covert"
|
||||
android:layout_alignBottom="@id/im_covert"
|
||||
|
||||
<com.hi.music.player.customerview.AnimaPlayingView
|
||||
android:id="@+id/view_playing"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignStart="@id/im_covert"
|
||||
android:layout_alignTop="@id/im_covert"
|
||||
android:layout_alignEnd="@id/im_covert"
|
||||
app:lottie_fileName="music_bounce.json"
|
||||
app:lottie_autoPlay="false"
|
||||
app:lottie_loop="true"/>
|
||||
|
||||
android:layout_alignBottom="@id/im_covert"
|
||||
android:layout_marginBottom="10dp" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/im_covert"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_toEndOf="@id/im_covert"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_name"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
<color name="white_60_color">#99FFFFFF</color>
|
||||
<color name="progress_buffer_color">#59FFFFFF</color>
|
||||
<color name="default_play_list_color">#1A1A1A</color>
|
||||
<color name="cur_play_music">#4DFFFFFF</color>
|
||||
|
||||
<color name="test">#2D9C31</color>
|
||||
</resources>
|
||||
Loading…
Reference in New Issue
Block a user