播放列表功能开发
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.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
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;
|
import com.hi.music.player.media3.MyMediaControllerManager;
|
||||||
|
|
||||||
public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayListBinding> {
|
public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayListBinding> {
|
||||||
|
|
||||||
|
private String mCurVideId;
|
||||||
|
|
||||||
|
private String lastVideId;
|
||||||
|
|
||||||
|
private int curMusicPos = 0;
|
||||||
|
private MyMediaControllerManager instance = MyMediaControllerManager.getInstance();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ItemPlayListBinding getViewBinding(ViewGroup parent) {
|
protected ItemPlayListBinding getViewBinding(ViewGroup parent) {
|
||||||
return ItemPlayListBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
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
|
@Override
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||||
@ -40,20 +65,32 @@ public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayL
|
|||||||
.into(vb.imCovert);
|
.into(vb.imCovert);
|
||||||
vb.songName.setText(listInfo.getSongTitle());
|
vb.songName.setText(listInfo.getSongTitle());
|
||||||
vb.artistName.setText(listInfo.getSingerName());
|
vb.artistName.setText(listInfo.getSingerName());
|
||||||
MyMediaControllerManager instance = MyMediaControllerManager.getInstance();
|
|
||||||
MediaItem currentMediaItem = instance.getMediaController().getCurrentMediaItem();
|
MediaItem currentMediaItem = instance.getMediaController().getCurrentMediaItem();
|
||||||
if (currentMediaItem != null && currentMediaItem.mediaId.equals(listInfo.getVideoId())) {
|
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()) {
|
if (instance.getMediaController().isPlaying()) {
|
||||||
vb.lottieAnimationView.playAnimation();
|
vb.viewPlaying.startAnimating();
|
||||||
|
lastVideId = listInfo.getVideoId();
|
||||||
CommonUtils.LogMsg("-------playAnimation");
|
CommonUtils.LogMsg("-------playAnimation");
|
||||||
} else {
|
} else {
|
||||||
vb.lottieAnimationView.pauseAnimation();
|
vb.viewPlaying.pauseAnimating();
|
||||||
CommonUtils.LogMsg("-------pauseAnimation");
|
CommonUtils.LogMsg("-------pauseAnimation");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vb.lottieAnimationView.setVisibility(View.GONE);
|
vb.viewPlaying.setVisibility(View.GONE);
|
||||||
CommonUtils.LogMsg("-------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.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.GradientDrawable;
|
import android.graphics.drawable.GradientDrawable;
|
||||||
|
import android.net.Uri;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.palette.graphics.Palette;
|
import androidx.palette.graphics.Palette;
|
||||||
|
|
||||||
import com.hi.music.player.MusicApplication;
|
import com.hi.music.player.MusicApplication;
|
||||||
|
import com.hi.music.player.R;
|
||||||
import com.hi.music.player.api.onImageColorListener;
|
import com.hi.music.player.api.onImageColorListener;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
@ -51,6 +54,7 @@ public class CommonUtils {
|
|||||||
public static int dpToPx(int dp) {
|
public static int dpToPx(int dp) {
|
||||||
return Math.round(dp * (MusicApplication.myApplication.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
|
return Math.round(dp * (MusicApplication.myApplication.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int pxToDp(int px) {
|
public static int pxToDp(int px) {
|
||||||
return Math.round(px / (MusicApplication.myApplication.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
|
return Math.round(px / (MusicApplication.myApplication.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
|
||||||
}
|
}
|
||||||
@ -75,7 +79,6 @@ public class CommonUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//time 3:45
|
//time 3:45
|
||||||
public static long convertToMilliseconds(String time) {
|
public static long convertToMilliseconds(String time) {
|
||||||
String[] parts = time.split(":");
|
String[] parts = time.split(":");
|
||||||
@ -92,6 +95,10 @@ public class CommonUtils {
|
|||||||
return String.format("%d:%02d", minutes, seconds); // 格式化为 mm:ss
|
return String.format("%d:%02d", minutes, seconds); // 格式化为 mm:ss
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getMyColor(int resId) {
|
||||||
|
return MusicApplication.myApplication.getColor(resId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 使用 Palette 提取深色主色调
|
// 使用 Palette 提取深色主色调
|
||||||
public static void getDominantDarkColor1(Drawable imDraw, onImageColorListener listener) {
|
public static void getDominantDarkColor1(Drawable imDraw, onImageColorListener listener) {
|
||||||
@ -99,7 +106,8 @@ public class CommonUtils {
|
|||||||
BitmapDrawable drawable = (BitmapDrawable) imDraw;
|
BitmapDrawable drawable = (BitmapDrawable) imDraw;
|
||||||
if (drawable != null) {
|
if (drawable != null) {
|
||||||
Bitmap bitmap = drawable.getBitmap();
|
Bitmap bitmap = drawable.getBitmap();
|
||||||
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
|
Palette.from(bitmap)
|
||||||
|
.generate(new Palette.PaletteAsyncListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onGenerated(Palette palette) {
|
public void onGenerated(Palette palette) {
|
||||||
// 首先尝试获取深色活力色
|
// 首先尝试获取深色活力色
|
||||||
@ -162,4 +170,34 @@ public class CommonUtils {
|
|||||||
drawable.setCornerRadii(radii);
|
drawable.setCornerRadii(radii);
|
||||||
return drawable;
|
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;
|
public final static int PLAY_STATUS_CODE_PAUSE = -3;
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------PlayActivity
|
//-----------------------------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.javabean.response.ResponsePlayUrl;
|
||||||
import com.hi.music.player.network.RetrofitManager;
|
import com.hi.music.player.network.RetrofitManager;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
@ -61,7 +62,6 @@ public class MyMediaControllerManager {
|
|||||||
// playerView.setPlayer(controllerFuture.get());
|
// playerView.setPlayer(controllerFuture.get());
|
||||||
try {
|
try {
|
||||||
mediaController = controllerFuture.get();
|
mediaController = controllerFuture.get();
|
||||||
|
|
||||||
statusListener.onMediaControllerComplete(true);
|
statusListener.onMediaControllerComplete(true);
|
||||||
CommonUtils.LogMsg("=-----mediaController+" + mediaController);
|
CommonUtils.LogMsg("=-----mediaController+" + mediaController);
|
||||||
} catch (ExecutionException | InterruptedException e) {
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
@ -98,19 +98,16 @@ public class MyMediaControllerManager {
|
|||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PLAYING);
|
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PLAYING);
|
||||||
// TODO: 2024/9/26 自动播放完成切歌到下一首播放没有触发这里请求下一首
|
// TODO: 2024/9/26 自动播放完成切歌到下一首播放没有触发这里请求下一首
|
||||||
// 播放器开始播放
|
if (mediaController.hasNextMediaItem()) {
|
||||||
MediaItem currentItem = mediaController.getCurrentMediaItem();
|
MediaItem mediaItemAt = mediaController.getMediaItemAt(mediaController.getNextMediaItemIndex());
|
||||||
int currentMediaItemIndex = mediaController.getCurrentMediaItemIndex();
|
if (!CommonUtils.hasValidUri(mediaItemAt)) {
|
||||||
if (currentMediaItemIndex < playList.size() - 1) {
|
|
||||||
//代表有下一首
|
|
||||||
if (!mediaController.hasNextMediaItem()) {
|
|
||||||
//没有更新下一首的uri
|
|
||||||
CommonUtils.LogMsg("----0000000000-请求下一首的uri" + mediaController.getMediaItemCount());
|
CommonUtils.LogMsg("----0000000000-请求下一首的uri" + mediaController.getMediaItemCount());
|
||||||
int nextIndex = currentMediaItemIndex + 1;
|
int nextIndex = mediaController.getNextMediaItemIndex();
|
||||||
mListener.onRequestNextUri(playList.get(nextIndex).getVideoId(), nextIndex,false);
|
mListener.onRequestNextUri(mediaController.getMediaItemAt(nextIndex).mediaId, nextIndex, false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// 播放器暂停或停止
|
// 播放器暂停或停止
|
||||||
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PAUSE);
|
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PAUSE);
|
||||||
@ -119,7 +116,6 @@ public class MyMediaControllerManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlaybackStateChanged(int playbackState) {
|
public void onPlaybackStateChanged(int playbackState) {
|
||||||
CommonUtils.LogMsg("----playbackState" + playbackState + "------------" + mediaController.getMediaItemCount());
|
|
||||||
mListener.onPlayStatus(playbackState);
|
mListener.onPlayStatus(playbackState);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -154,32 +150,30 @@ public class MyMediaControllerManager {
|
|||||||
// *
|
// *
|
||||||
// * @param playUrl
|
// * @param playUrl
|
||||||
// */
|
// */
|
||||||
// public void UpdateAudioUrl(ResponsePlayUrl playUrl) {
|
public void UpdateAudioUrl(ResponsePlayUrl playUrl, int index) {
|
||||||
//
|
CommonUtils.LogMsg("-------------更新播放列表中的音频url= index=" + index);
|
||||||
// CommonUtils.LogMsg("-------------更新播放列表中的音频 mediaController.getMediaItemCount()=" + mediaController.getMediaItemCount());
|
for (int i = 0; i < mediaController.getMediaItemCount(); i++) {
|
||||||
// for (int i = 0; i < mediaController.getMediaItemCount(); i++) {
|
MediaItem mediaItemAt = mediaController.getMediaItemAt(i);
|
||||||
// MediaItem mediaItemAt = mediaController.getMediaItemAt(i);
|
if (mediaItemAt.mediaId.equals(playUrl.getVideoId())) {
|
||||||
// if (mediaItemAt.mediaId.equals(playUrl.getVideoId())) {
|
|
||||||
//
|
MediaItem.Builder builder = mediaItemAt.buildUpon();
|
||||||
// MediaItem.Builder builder = mediaItemAt.buildUpon();
|
builder.setMediaId(playUrl.getVideoId());
|
||||||
//// mediaController.removeMediaItem(i);
|
if (playUrl.getAudioUrlMedium() != null) {
|
||||||
//// MediaItem.Builder builder = new MediaItem.Builder();
|
builder.setUri(playUrl.getAudioUrlMedium());
|
||||||
// builder.setMediaId(playUrl.getVideoId());
|
} else {
|
||||||
// if (playUrl.getAudioUrlMedium() != null) {
|
builder.setUri(playUrl.getAudioUrlLow());
|
||||||
// builder.setUri(playUrl.getAudioUrlMedium());
|
}
|
||||||
// } else {
|
CharSequence title = mediaController.getMediaItemAt(i).mediaMetadata.title;
|
||||||
// builder.setUri(playUrl.getAudioUrlLow());
|
CommonUtils.LogMsg("-------------更新播放列表中的音频url= i=" + i + "---id=" + playUrl.getVideoId() + "----mediaController.size=" + mediaController.getMediaItemCount());
|
||||||
// }
|
mediaController.replaceMediaItem(i, builder.build());
|
||||||
// mediaController.replaceMediaItem(i, builder.build());
|
break;
|
||||||
// CharSequence title = mediaController.getMediaItemAt(i).mediaMetadata.title;
|
}
|
||||||
// CommonUtils.LogMsg("-------------更新播放列表中的音频url= i=" + i + "---title=" + title + "----mediaController.size=" + mediaController.getMediaItemCount() + "---" + mediaController);
|
}
|
||||||
// break;
|
}
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void setPlayList(List<ResponsePlayListInfo> playList) {
|
public void setPlayList(List<ResponsePlayListInfo> playList) {
|
||||||
this.playList = playList;
|
this.playList = playList;
|
||||||
|
addMusicPlayList(playList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ResponsePlayListInfo> getPlayList() {
|
public List<ResponsePlayListInfo> getPlayList() {
|
||||||
@ -192,7 +186,7 @@ public class MyMediaControllerManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加播放列表(不带音频url)
|
* 添加播放列表(不带音频url)
|
||||||
* 注意没有更新有效uri的不会被实际添加到mediaController
|
* 注意没有setUri的不会被实际添加到mediaController,
|
||||||
*
|
*
|
||||||
* @param playUrl
|
* @param playUrl
|
||||||
*/
|
*/
|
||||||
@ -214,7 +208,6 @@ public class MyMediaControllerManager {
|
|||||||
MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
||||||
|
|
||||||
MediaMetadata_builder.setArtist(listInfo.getSingerName());
|
MediaMetadata_builder.setArtist(listInfo.getSingerName());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 这里使用setDescription保存歌曲时长的分秒字符串
|
* 这里使用setDescription保存歌曲时长的分秒字符串
|
||||||
*/
|
*/
|
||||||
@ -228,49 +221,53 @@ public class MyMediaControllerManager {
|
|||||||
// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
||||||
builder.setMediaMetadata(MediaMetadata_builder.build());
|
builder.setMediaMetadata(MediaMetadata_builder.build());
|
||||||
mediaController.addMediaItem(builder.build());
|
mediaController.addMediaItem(builder.build());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * 添加播放列表(不带音频url)
|
* 添加播放列表(不带音频url)
|
||||||
// * 注意没有更新有效uri的不会被实际添加到mediaController
|
* 注意没有setUri的不会被实际添加到mediaController(mediaController.getMediaItemCount())
|
||||||
// *
|
* 这里setUri 一个占位
|
||||||
// * @param listInfo
|
*
|
||||||
// */
|
* @param listInfo
|
||||||
// @OptIn(markerClass = UnstableApi.class)
|
*/
|
||||||
// public void addMusicPlayList(List<ResponsePlayListInfo> listInfo) {
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
// playList = listInfo;
|
public void addMusicPlayList(List<ResponsePlayListInfo> listInfo) {
|
||||||
// List<MediaItem> mediaItems = new ArrayList<>();
|
playList = listInfo;
|
||||||
// for (int i = 0; i < listInfo.size(); i++) {
|
List<MediaItem> mediaItems = new ArrayList<>();
|
||||||
// ResponsePlayListInfo playInfo = listInfo.get(i);
|
for (int i = 0; i < listInfo.size(); i++) {
|
||||||
//
|
ResponsePlayListInfo playInfo = listInfo.get(i);
|
||||||
// MediaItem.Builder builder = new MediaItem.Builder();
|
|
||||||
//
|
MediaItem.Builder builder = new MediaItem.Builder();
|
||||||
// //唯一标识符
|
|
||||||
// builder.setMediaId(playInfo.getVideoId());
|
//唯一标识符
|
||||||
//
|
builder.setMediaId(playInfo.getVideoId());
|
||||||
// MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
builder.setUri("-------test-----");
|
||||||
//
|
MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
||||||
// MediaMetadata_builder.setArtist(playInfo.getSingerName());
|
|
||||||
// MediaMetadata_builder.setDurationMs(playInfo.getDurationMs());
|
MediaMetadata_builder.setArtist(playInfo.getSingerName());
|
||||||
//// MediaMetadata_builder.setArtworkUri(Uri.parse(playInfo.getCovert()));
|
MediaMetadata_builder.setDescription(playInfo.getDuration());
|
||||||
// MediaMetadata_builder.setArtworkUri(Uri.parse("https://t7.baidu.com/it/u=2604797219,1573897854&fm=193&f=GIF"));
|
MediaMetadata_builder.setDurationMs(playInfo.getDurationMs());
|
||||||
// MediaMetadata_builder.setTitle(playInfo.getSongTitle());
|
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()));
|
CommonUtils.LogMsg("----------添加播放列表 i=" + i + "---" + playInfo.getSongTitle() + "-------VideoId=" + playInfo.getVideoId());
|
||||||
// builder.setMediaMetadata(MediaMetadata_builder.build());
|
// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
||||||
// mediaController.addMediaItem(builder.build());
|
builder.setMediaMetadata(MediaMetadata_builder.build());
|
||||||
//// mediaItems.add(builder.build());
|
mediaController.addMediaItem(builder.build());
|
||||||
// }
|
|
||||||
//// mediaController.setMediaItems(mediaItems);
|
}
|
||||||
// }
|
|
||||||
|
}
|
||||||
|
|
||||||
public void play() {
|
public void play() {
|
||||||
if (!mediaController.isPlaying()) {
|
if (!mediaController.isPlaying()) {
|
||||||
|
CommonUtils.LogMsg("-----------prepare");
|
||||||
mediaController.prepare();
|
mediaController.prepare();
|
||||||
mediaController.play();
|
mediaController.play();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -279,21 +276,32 @@ public class MyMediaControllerManager {
|
|||||||
if (mediaController.isPlaying())
|
if (mediaController.isPlaying())
|
||||||
mediaController.pause();
|
mediaController.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if (mediaController.isPlaying())
|
if (mediaController.isPlaying())
|
||||||
mediaController.stop();
|
mediaController.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playNext() {
|
public void playNext() {
|
||||||
if (mediaController.hasNextMediaItem()) {
|
if (mediaController.hasNextMediaItem()) {
|
||||||
|
int nextMediaItemIndex = mediaController.getNextMediaItemIndex();
|
||||||
|
MediaItem mediaItemAt = mediaController.getMediaItemAt(nextMediaItemIndex);
|
||||||
|
boolean b = CommonUtils.hasValidUri(mediaItemAt);
|
||||||
|
if (b) {
|
||||||
mediaController.seekToNextMediaItem();
|
mediaController.seekToNextMediaItem();
|
||||||
} else {
|
return;
|
||||||
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请求失败,需要重新请求");
|
|
||||||
}
|
}
|
||||||
|
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();
|
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.Nullable;
|
||||||
import androidx.annotation.OptIn;
|
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.Player;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
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.ExoPlayer;
|
||||||
|
|
||||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
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.MediaSession;
|
||||||
import androidx.media3.session.MediaSessionService;
|
import androidx.media3.session.MediaSessionService;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.hi.music.player.MusicApplication;
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
import com.hi.music.player.helper.CommonUtils;
|
||||||
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class PlaybackService extends MediaSessionService {
|
public class PlaybackService extends MediaSessionService {
|
||||||
private MediaSession mediaSession = null;
|
private MediaSession mediaSession = null;
|
||||||
private ExoPlayer player;
|
private ExoPlayer player;
|
||||||
|
|
||||||
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.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)
|
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();
|
.build();
|
||||||
|
|
||||||
// player = new ExoPlayer.Builder(this)
|
// player = new ExoPlayer.Builder(this)
|
||||||
@ -69,12 +80,39 @@ public class PlaybackService extends MediaSessionService {
|
|||||||
// .build();
|
// .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
|
@Nullable
|
||||||
@Override
|
@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")) {
|
if (mimeType.contains("audio/mp4")) {
|
||||||
String url = jsonIndex.getString("url");
|
String url = jsonIndex.getString("url");
|
||||||
boolean audioQuality1 = jsonIndex.has("audioQuality");
|
boolean audioQuality1 = jsonIndex.has("audioQuality");
|
||||||
CommonUtils.LogMsg("------------itag="+itag+"---------audioQuality1="+audioQuality1);
|
|
||||||
if (jsonIndex.has("audioQuality")) {
|
if (jsonIndex.has("audioQuality")) {
|
||||||
String audioQuality = jsonIndex.getString("audioQuality");
|
String audioQuality = jsonIndex.getString("audioQuality");
|
||||||
if (audioQuality.equals("AUDIO_QUALITY_MEDIUM")) {
|
if (audioQuality.equals("AUDIO_QUALITY_MEDIUM")) {
|
||||||
|
|||||||
@ -15,12 +15,12 @@ public class ObserverWrapper<T> implements Observer<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribe(Disposable d) {
|
public void onSubscribe(Disposable d) {
|
||||||
CommonUtils.LogMsg("----------onSubscribe");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNext(T t) {
|
public void onNext(T t) {
|
||||||
CommonUtils.LogMsg("----------onNext");
|
|
||||||
requestListener.onSuccess(t);
|
requestListener.onSuccess(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ public class ObserverWrapper<T> implements Observer<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onComplete() {
|
public void onComplete() {
|
||||||
CommonUtils.LogMsg("----------onComplete");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -57,8 +57,6 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
//接口返回的播放列表(没有音频数据)
|
//接口返回的播放列表(没有音频数据)
|
||||||
private List<ResponsePlayListInfo> mPlayList;
|
private List<ResponsePlayListInfo> mPlayList;
|
||||||
|
|
||||||
//播放列对应的音频数据
|
|
||||||
private List<ResponsePlayUrl> mPlayUrls;
|
|
||||||
|
|
||||||
private ResponsePlayUrl mCurPlayInfo;
|
private ResponsePlayUrl mCurPlayInfo;
|
||||||
private ResponsePlayListInfo musicInfo;
|
private ResponsePlayListInfo musicInfo;
|
||||||
@ -66,6 +64,8 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
private Runnable mRunnable;
|
private Runnable mRunnable;
|
||||||
private MyMediaControllerManager mediaControllerManager;
|
private MyMediaControllerManager mediaControllerManager;
|
||||||
|
|
||||||
|
private AdapterPlayList adapterPlayList;
|
||||||
|
|
||||||
|
|
||||||
//播放列表ui初始化
|
//播放列表ui初始化
|
||||||
private boolean initPlayList = false;
|
private boolean initPlayList = false;
|
||||||
@ -170,6 +170,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Player.STATE_ENDED:
|
case Player.STATE_ENDED:
|
||||||
|
//播放完成
|
||||||
vb.btnPlay.setSelected(false);
|
vb.btnPlay.setSelected(false);
|
||||||
CommonUtils.LogMsg("-------------playStatus=STATE_ENDED 播放完成");
|
CommonUtils.LogMsg("-------------playStatus=STATE_ENDED 播放完成");
|
||||||
mHandler.removeCallbacks(mRunnable); // 停止更新
|
mHandler.removeCallbacks(mRunnable); // 停止更新
|
||||||
@ -199,7 +200,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChangeMusic(MediaItem mediaItem) {
|
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);
|
loadInfo(mediaItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +251,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
private void loadInfo(MediaItem mediaItem) {
|
private void loadInfo(MediaItem mediaItem) {
|
||||||
|
|
||||||
MediaMetadata mediaMetadata = mediaItem.mediaMetadata;
|
MediaMetadata mediaMetadata = mediaItem.mediaMetadata;
|
||||||
CommonUtils.LogMsg("--------------加载当前播放歌曲信息 " + mediaMetadata.description);
|
CommonUtils.LogMsg("--------------加载当前播放歌曲信息 ");
|
||||||
if (mediaMetadata.artworkUri != null) {
|
if (mediaMetadata.artworkUri != null) {
|
||||||
loadCovert(mediaMetadata.artworkUri.toString());
|
loadCovert(mediaMetadata.artworkUri.toString());
|
||||||
}
|
}
|
||||||
@ -263,7 +264,9 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
vb.playProgress.setMax((int) durationMs);
|
vb.playProgress.setMax((int) durationMs);
|
||||||
vb.progressBarBuffer.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);
|
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 {
|
} else {
|
||||||
mediaControllerManager.pause();
|
mediaControllerManager.pause();
|
||||||
}
|
}
|
||||||
|
if(adapterPlayList!= null){
|
||||||
|
adapterPlayList.updateCurMusicAnimation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -374,52 +385,14 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
|||||||
|
|
||||||
if (!initPlayList) {
|
if (!initPlayList) {
|
||||||
List<ResponsePlayListInfo> playList = mediaControllerManager.getPlayList();
|
List<ResponsePlayListInfo> playList = mediaControllerManager.getPlayList();
|
||||||
AdapterPlayList adapterPlayList = new AdapterPlayList();
|
adapterPlayList = new AdapterPlayList();
|
||||||
vb.layoutPlayList.recyclerList.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication));
|
vb.layoutPlayList.recyclerList.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication));
|
||||||
adapterPlayList.addData(playList);
|
adapterPlayList.addData(playList);
|
||||||
vb.layoutPlayList.recyclerList.setAdapter(adapterPlayList);
|
vb.layoutPlayList.recyclerList.setAdapter(adapterPlayList);
|
||||||
vb.layoutPlayList.imPlay.setOnClickListener(this);
|
vb.layoutPlayList.imPlay.setOnClickListener(this);
|
||||||
initPlayList = true;
|
initPlayList = true;
|
||||||
}
|
}
|
||||||
|
updatePlayListUi();
|
||||||
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());
|
|
||||||
|
|
||||||
} else {
|
} 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
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
|||||||
@ -37,9 +37,6 @@ public class VMPlay extends ViewModel {
|
|||||||
String videoId = responseSingle.getVideoId();
|
String videoId = responseSingle.getVideoId();
|
||||||
String params = responseSingle.getParams();
|
String params = responseSingle.getParams();
|
||||||
String musicVideoType = responseSingle.getMusicVideoType();
|
String musicVideoType = responseSingle.getMusicVideoType();
|
||||||
|
|
||||||
CommonUtils.LogMsg("111111111-------0000---"+responseSingle.getSongTitle() +"---id="+videoId);
|
|
||||||
|
|
||||||
RetrofitManager.getInstance().getPlayList(params, playlistId, videoId, musicVideoType, new RequestListener<ResponseBody>() {
|
RetrofitManager.getInstance().getPlayList(params, playlistId, videoId, musicVideoType, new RequestListener<ResponseBody>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -54,7 +51,6 @@ public class VMPlay extends ViewModel {
|
|||||||
List<ResponsePlayListInfo> responsePlayListInfos = JsonHelper.ResolvePlayListJson(jsonObject);
|
List<ResponsePlayListInfo> responsePlayListInfos = JsonHelper.ResolvePlayListJson(jsonObject);
|
||||||
MyMediaControllerManager.getInstance().setPlayList(responsePlayListInfos);
|
MyMediaControllerManager.getInstance().setPlayList(responsePlayListInfos);
|
||||||
_playList.setValue(responsePlayListInfos);
|
_playList.setValue(responsePlayListInfos);
|
||||||
CommonUtils.LogMsg("111111111-------1111----"+responsePlayListInfos.get(0).getSongTitle() +"---id="+responsePlayListInfos.get(0).getVideoId());
|
|
||||||
getPlayUrl(responseSingle.getVideoId(),0,true);
|
getPlayUrl(responseSingle.getVideoId(),0,true);
|
||||||
} else {
|
} else {
|
||||||
_playList.setValue(null);
|
_playList.setValue(null);
|
||||||
@ -83,7 +79,8 @@ public class VMPlay extends ViewModel {
|
|||||||
// TODO: 2024/9/27
|
// TODO: 2024/9/27
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MyMediaControllerManager.getInstance().addMusicToPlayList(responsePlayUrl,playListIndex);
|
MyMediaControllerManager.getInstance().UpdateAudioUrl(responsePlayUrl,playListIndex);
|
||||||
|
// MyMediaControllerManager.getInstance().addMusicToPlayList(responsePlayUrl,playListIndex);
|
||||||
customerUrlInfo.setPlayUrl(responsePlayUrl);
|
customerUrlInfo.setPlayUrl(responsePlayUrl);
|
||||||
customerUrlInfo.setPlayMusicIndex(playListIndex);
|
customerUrlInfo.setPlayMusicIndex(playListIndex);
|
||||||
|
|
||||||
|
|||||||
@ -2,15 +2,15 @@
|
|||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/root_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/root_layout"
|
|
||||||
android:background="@color/black"
|
android:background="@color/black"
|
||||||
tools:context=".ui.activity.PlayActivity">
|
tools:context=".ui.activity.PlayActivity">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:id="@+id/content_layout"
|
android:id="@+id/content_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
@ -51,16 +51,6 @@
|
|||||||
app:show_shuffle_button="true" />
|
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
|
<TextView
|
||||||
android:id="@+id/tv_song_name"
|
android:id="@+id/tv_song_name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -186,4 +176,13 @@
|
|||||||
<include
|
<include
|
||||||
android:id="@+id/layout_playList"
|
android:id="@+id/layout_playList"
|
||||||
layout="@layout/dialog_play_list" />
|
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>
|
</FrameLayout>
|
||||||
@ -25,6 +25,7 @@
|
|||||||
android:id="@+id/top_im"
|
android:id="@+id/top_im"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
|
android:scaleType="fitXY"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:src="@mipmap/ic_launcher" />
|
android:src="@mipmap/ic_launcher" />
|
||||||
|
|
||||||
@ -64,11 +65,11 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/im_play"
|
android:id="@+id/im_play"
|
||||||
android:layout_width="16dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="16dp"
|
android:layout_height="60dp"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_marginEnd="22dp"
|
||||||
android:layout_marginEnd="42dp"
|
android:padding="20dp"
|
||||||
android:src="@drawable/selector_small_play" />
|
android:src="@drawable/selector_small_play" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|||||||
@ -1,39 +1,38 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<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"
|
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">
|
android:paddingStart="20dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="60dp"
|
|
||||||
android:id="@+id/im_covert"
|
android:id="@+id/im_covert"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_height="60dp" />
|
android:src="@mipmap/ic_launcher" />
|
||||||
|
|
||||||
<com.airbnb.lottie.LottieAnimationView
|
|
||||||
android:id="@+id/lottieAnimationView"
|
<com.hi.music.player.customerview.AnimaPlayingView
|
||||||
android:layout_width="0dp"
|
android:id="@+id/view_playing"
|
||||||
android:layout_height="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_height="wrap_content"
|
||||||
android:padding="5dp"
|
|
||||||
android:layout_alignTop="@id/im_covert"
|
|
||||||
android:layout_alignBottom="@id/im_covert"
|
|
||||||
android:layout_alignStart="@id/im_covert"
|
android:layout_alignStart="@id/im_covert"
|
||||||
|
android:layout_alignTop="@id/im_covert"
|
||||||
android:layout_alignEnd="@id/im_covert"
|
android:layout_alignEnd="@id/im_covert"
|
||||||
app:lottie_fileName="music_bounce.json"
|
android:layout_alignBottom="@id/im_covert"
|
||||||
app:lottie_autoPlay="false"
|
android:layout_marginBottom="10dp" />
|
||||||
app:lottie_loop="true"/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_toEndOf="@id/im_covert"
|
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_toEndOf="@id/im_covert"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/song_name"
|
android:id="@+id/song_name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
<color name="white_60_color">#99FFFFFF</color>
|
<color name="white_60_color">#99FFFFFF</color>
|
||||||
<color name="progress_buffer_color">#59FFFFFF</color>
|
<color name="progress_buffer_color">#59FFFFFF</color>
|
||||||
<color name="default_play_list_color">#1A1A1A</color>
|
<color name="default_play_list_color">#1A1A1A</color>
|
||||||
|
<color name="cur_play_music">#4DFFFFFF</color>
|
||||||
|
|
||||||
<color name="test">#2D9C31</color>
|
<color name="test">#2D9C31</color>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in New Issue
Block a user