增加缓存功能,优化用户体验;增加重试view

This commit is contained in:
litingting 2024-10-08 18:12:09 +08:00
parent 72bf148ad5
commit 5b390f4bff
17 changed files with 277 additions and 74 deletions

View File

@ -15,6 +15,7 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.hi.music.player.MusicApplication;
import com.hi.music.player.R;
import com.hi.music.player.api.MediaControllerListener;
import com.hi.music.player.databinding.ItemPlayListBinding;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
@ -26,7 +27,7 @@ public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayL
private String lastVideId;
private int curMusicPos = 0;
// private int curMusicPos = 0;
private MyMediaControllerManager instance = MyMediaControllerManager.getInstance();
@Override
@ -48,8 +49,25 @@ public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayL
}
}
public void updateCurPlayStatus(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);
int curIndex = instance.getCurIndex();
CommonUtils.LogMsg("--curIndex="+curIndex);
notifyItemChanged(curIndex);
}
@Override
@ -69,18 +87,19 @@ public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayL
MediaItem currentMediaItem = instance.getMediaController().getCurrentMediaItem();
if (currentMediaItem != null && currentMediaItem.mediaId.equals(listInfo.getVideoId())) {
vb.viewPlaying.setVisibility(View.VISIBLE);
vb.getRoot().setBackgroundColor(CommonUtils.getMyColor(R.color.cur_play_music));
vb.itemLayout.setBackgroundColor(CommonUtils.getMyColor(R.color.cur_play_music));
if (instance.getMediaController().isPlaying()) {
vb.viewPlaying.startAnimating();
lastVideId = listInfo.getVideoId();
CommonUtils.LogMsg("-------playAnimation");
CommonUtils.LogMsg("-------playAnimation "+itemHolder.getAbsoluteAdapterPosition());
} else {
vb.viewPlaying.pauseAnimating();
CommonUtils.LogMsg("-------pauseAnimation");
CommonUtils.LogMsg("-------pauseAnimation "+itemHolder.getAbsoluteAdapterPosition());
}
} else {
vb.viewPlaying.setVisibility(View.GONE);
// CommonUtils.LogMsg("-------GONE");
vb.itemLayout.setBackgroundColor(CommonUtils.getMyColor(R.color.color_transparent));
}
vb.itemLayout.setOnClickListener(new View.OnClickListener() {

View File

@ -35,6 +35,13 @@ abstract public class BaseAdapter<K, T extends ViewBinding> extends RecyclerView
notifyDataSetChanged();
}
public void setData(List<K> data) {
this.data.clear();
this.data.addAll(data);
notifyDataSetChanged();
}
public void addLoadingFooter() {
isLoadingAdded = true;
// notifyItemInserted(data.size());

View File

@ -18,5 +18,5 @@ public interface MediaControllerListener {
void onRequestNextUri(String videoId,int playListIndex,boolean playNow);
void onChangeMusic(MediaItem mediaItem);
void onChangeMusic(MediaItem mediaItem);
}

View File

@ -0,0 +1,5 @@
package com.hi.music.player.api;
public interface OnHasUrlAction {
void onHasUrl();
}

View File

@ -11,6 +11,8 @@ import android.view.animation.LinearInterpolator;
import com.hi.music.player.helper.CommonUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class AnimaPlayingView extends View {
@ -23,7 +25,7 @@ public class AnimaPlayingView extends View {
private int minHeight = CommonUtils.dpToPx(4); // 音量条的最小高度
// 每个柱子的宽度
private int barWidth =CommonUtils. dpToPx(4);
private int barWidth = CommonUtils.dpToPx(4);
// 柱子之间的间距
private int barSpacing = CommonUtils.dpToPx(2);
@ -31,6 +33,7 @@ public class AnimaPlayingView extends View {
private Random random;
private ValueAnimator animator;
private List<ValueAnimator> valueAnimatorList;
public AnimaPlayingView(Context context) {
super(context);
@ -48,6 +51,7 @@ public class AnimaPlayingView extends View {
}
private void init() {
valueAnimatorList = new ArrayList<>();
paint = new Paint();
paint.setColor(barColor);
paint.setStyle(Paint.Style.FILL);
@ -58,6 +62,7 @@ public class AnimaPlayingView extends View {
for (int i = 0; i < numBars; i++) {
barHeights[i] = 0;
}
initAnimating();
}
@ -84,9 +89,14 @@ public class AnimaPlayingView extends View {
}
}
// 启动固定动画使音量条的高度变化
public void startAnimating() {
for (ValueAnimator valueAnimator : valueAnimatorList) {
valueAnimator.start();
}
}
// 启动固定动画使音量条的高度变化
public void initAnimating() {
for (int i = 0; i < numBars; i++) {
animator = ValueAnimator.ofFloat(0, 1);
animator.setDuration(1000); // 每0.5秒更新一次
@ -104,16 +114,16 @@ public class AnimaPlayingView extends View {
invalidate(); // 重绘视图
}
});
animator.setStartDelay(i* 200L);
animator.start();
valueAnimatorList.add(animator);
animator.setStartDelay(i * 200L);
}
}
public void pauseAnimating(){
if(animator!= null){
animator.pause();
public void pauseAnimating() {
for (ValueAnimator valueAnimator : valueAnimatorList) {
valueAnimator.pause();
}
for (int i = 0; i < numBars; i++) {
barHeights[i] = minHeight;
@ -122,7 +132,6 @@ public class AnimaPlayingView extends View {
}
// 随机生成音量条的高度
private float randomHeight() {
return minHeight + random.nextFloat() * (maxHeight - minHeight);

View File

@ -31,7 +31,7 @@ public class CommonUtils {
private static String TAG = "----MUSIC---------";
private static String TAG_ERROR = "----ERROR MUSIC---------";
private static String TAG_ERROR = "----MUSIC---------ERROR--";
public static void LogMsg(String msg) {
Log.d(TAG, msg);
@ -191,7 +191,6 @@ public class CommonUtils {
// 3. 检查 URI 是否具有正确的格式
try {
if (parsedUri.getScheme() == null) {
LogMsg( "URI has no valid scheme.");
return false;
}
} catch (Exception e) {

View File

@ -7,8 +7,17 @@ public class CustomerUrlInfo {
private ResponsePlayUrl playUrl;
private int playMusicIndex;
private boolean needPlayNow;
private String videoId;
public String getVideoId() {
return videoId;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public ResponsePlayUrl getPlayUrl() {
return playUrl;
}

View File

@ -6,8 +6,12 @@ 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.DefaultDataSource;
import androidx.media3.datasource.DefaultDataSourceFactory;
import androidx.media3.datasource.DefaultHttpDataSource;
import androidx.media3.datasource.ResolvingDataSource;
import androidx.media3.datasource.cache.CacheDataSource;
import androidx.media3.datasource.cache.SimpleCache;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.drm.DrmSessionManagerProvider;
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
@ -16,6 +20,7 @@ import androidx.media3.exoplayer.source.MediaSourceFactory;
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
import com.hi.music.player.MusicApplication;
import com.hi.music.player.api.RequestListener;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.response.ResponsePlayUrl;
@ -32,16 +37,18 @@ import okhttp3.ResponseBody;
public class DynamicMediaSourceFactory implements MediaSource.Factory {
// private final CacheDataSource.Factory cacheDataSourceFactory;
// private final ExoPlayer player;
private DefaultMediaSourceFactory mediaSourceFactory;
private DataSource.Factory mediaSourceFactory;
private SimpleCache simpleCache;
// public DynamicMediaSourceFactory(DefaultMediaSourceFactory factory,CacheDataSource.Factory cacheDataSourceFactory, ExoPlayer exoPlayer) {
// this.cacheDataSourceFactory = cacheDataSourceFactory;
// this.player = exoPlayer;
// this.mediaSourceFactory = factory;
// }
public DynamicMediaSourceFactory(DefaultMediaSourceFactory factory) {
public DynamicMediaSourceFactory(DataSource.Factory factory, SimpleCache cache) {
this.mediaSourceFactory = factory;
this.simpleCache = cache;
}
@ -105,22 +112,40 @@ public class DynamicMediaSourceFactory implements MediaSource.Factory {
// }
// });
// DefaultHttpDataSource.Factory httpDataSourceFactory = new DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true);
// 这里的DefaultDataSource同时支持本地和HTTP请求的资源自动实现检测 The DefaultDataSource supports both local and Http sources. It automatically detects which one to use.
//实现缓存
CacheDataSource.Factory cacheDataSourceFactory = new CacheDataSource.Factory()
.setCache(simpleCache)
.setUpstreamDataSourceFactory(mediaSourceFactory)
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
MediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
.createMediaSource(mediaItem);
return mediaSource;
// 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;
// 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);
// }
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());
// return mediaSourceFactory.createMediaSource(builder.build());
}

View File

@ -18,6 +18,7 @@ import com.google.common.util.concurrent.MoreExecutors;
import com.hi.music.player.MusicApplication;
import com.hi.music.player.api.MediaControllerListener;
import com.hi.music.player.api.MediaControllerStatusListener;
import com.hi.music.player.api.OnHasUrlAction;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.helper.MyValue;
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
@ -78,7 +79,6 @@ public class MyMediaControllerManager {
mediaController.addListener(new Player.Listener() {
@Override
public void onPlayerError(PlaybackException error) {
CommonUtils.LogMsg("=-----PlaybackException+" + error.getMessage());
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_ERROR);
}
@ -99,13 +99,22 @@ public class MyMediaControllerManager {
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PLAYING);
// TODO: 2024/9/26 自动播放完成切歌到下一首播放没有触发这里请求下一首
if (mediaController.hasNextMediaItem()) {
MediaItem mediaItemAt = mediaController.getMediaItemAt(mediaController.getNextMediaItemIndex());
if (!CommonUtils.hasValidUri(mediaItemAt)) {
CommonUtils.LogMsg("----0000000000-请求下一首的uri" + mediaController.getMediaItemCount());
int nextIndex = mediaController.getNextMediaItemIndex();
mListener.onRequestNextUri(mediaController.getMediaItemAt(nextIndex).mediaId, nextIndex, false);
}
int nextMediaItemIndex = mediaController.getNextMediaItemIndex();
onCallRequestUrl(nextMediaItemIndex, false, new OnHasUrlAction() {
@Override
public void onHasUrl() {
CommonUtils.LogMsg("-------------有有效URl--播放检查下一首 位置="+nextMediaItemIndex );
}
});
}
if (mediaController.hasPreviousMediaItem()) {
int previousMediaItemIndex = mediaController.getPreviousMediaItemIndex();
onCallRequestUrl(previousMediaItemIndex, false, new OnHasUrlAction() {
@Override
public void onHasUrl() {
CommonUtils.LogMsg("-------------有有效URl--播放检查上一首 位置="+previousMediaItemIndex );
}
});
}
} else {
@ -145,11 +154,15 @@ public class MyMediaControllerManager {
}
// /**
// * 更新播放列表中的音频url
// *
// * @param playUrl
// */
public int getCurIndex(){
return mediaController.getCurrentMediaItemIndex();
}
/**
* 更新播放列表中的音频url
*
* @param playUrl
*/
public void UpdateAudioUrl(ResponsePlayUrl playUrl, int index) {
CommonUtils.LogMsg("-------------更新播放列表中的音频url= index=" + index);
for (int i = 0; i < mediaController.getMediaItemCount(); i++) {
@ -285,15 +298,14 @@ public class MyMediaControllerManager {
public void playNext() {
if (mediaController.hasNextMediaItem()) {
int nextMediaItemIndex = mediaController.getNextMediaItemIndex();
MediaItem mediaItemAt = mediaController.getMediaItemAt(nextMediaItemIndex);
boolean b = CommonUtils.hasValidUri(mediaItemAt);
if (b) {
mediaController.seekToNextMediaItem();
return;
}
CommonUtils.LogMsg("-------------有下一首但是歌曲url请求失败需要重新请求");
mListener.onRequestNextUri(mediaController.getMediaItemAt(nextMediaItemIndex).mediaId, nextMediaItemIndex, true);
onCallRequestUrl(nextMediaItemIndex, true, new OnHasUrlAction() {
@Override
public void onHasUrl() {
mediaController.seekToNextMediaItem();
mediaController.play();
}
});
} else {
// int currentMediaItemIndex = mediaController.getCurrentMediaItemIndex();
// if (currentMediaItemIndex < playList.size() - 1) {
@ -307,7 +319,16 @@ public class MyMediaControllerManager {
public void playPrevious() {
if (mediaController.hasPreviousMediaItem()) {
mediaController.seekToPreviousMediaItem();
int nextMediaItemIndex = mediaController.getNextMediaItemIndex();
onCallRequestUrl(nextMediaItemIndex, true, new OnHasUrlAction() {
@Override
public void onHasUrl() {
mediaController.seekToPreviousMediaItem();
mediaController.play();
}
});
} else {
mediaController.seekTo(0);
mediaController.play();
@ -327,15 +348,25 @@ public class MyMediaControllerManager {
}
stop();
mediaController.prepare();
mediaController.seekTo(index);
mediaController.seekTo(index,0);
onCallRequestUrl(index, true, new OnHasUrlAction() {
@Override
public void onHasUrl() {
mediaController.play();
CommonUtils.LogMsg("-------------有有效URl--播放指定播放列表位置的歌曲" );
}
});
}
private void onCallRequestUrl(int index, boolean playNow, OnHasUrlAction action){
MediaItem mediaItemAt = mediaController.getMediaItemAt(index);
boolean b = CommonUtils.hasValidUri(mediaItemAt);
if (!b) {
CommonUtils.LogMsg("-------------播放指定播放列表位置的歌曲,需要重新请求");
mListener.onRequestNextUri(mediaItemAt.mediaId, index, true);
CommonUtils.LogMsg("-------------请求URl index"+index+"---playNow="+playNow);
mListener.onRequestNextUri(mediaItemAt.mediaId, index, playNow);
}else {
action.onHasUrl();
}
}
}

View File

@ -7,10 +7,13 @@ import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.media3.common.Player;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.database.DatabaseProvider;
import androidx.media3.database.ExoDatabaseProvider;
import androidx.media3.database.StandaloneDatabaseProvider;
import androidx.media3.datasource.DataSource;
import androidx.media3.datasource.DataSpec;
import androidx.media3.datasource.DefaultDataSource;
import androidx.media3.datasource.DefaultDataSourceFactory;
import androidx.media3.datasource.DefaultHttpDataSource;
import androidx.media3.datasource.ResolvingDataSource;
import androidx.media3.datasource.cache.CacheDataSource;
@ -40,8 +43,21 @@ public class PlaybackService extends MediaSessionService {
public void onCreate() {
super.onCreate();
// 1. 初始化缓存
File cacheDir = new File(getCacheDir(), "media_cache");
long maxCacheSize = 100 * 1024 * 1024; // 缓存大小 100MB
StandaloneDatabaseProvider databaseProvider = new StandaloneDatabaseProvider(this);
SimpleCache cache = new SimpleCache(cacheDir, new LeastRecentlyUsedCacheEvictor(maxCacheSize), databaseProvider);
DynamicMediaSourceFactory customMediaSourceFactory = new DynamicMediaSourceFactory(new DefaultMediaSourceFactory(new DefaultHttpDataSource.Factory()));
DefaultHttpDataSource.Factory httpDataSourceFactory = new DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true);
// 这里的DefaultDataSource同时支持本地和HTTP请求的资源自动实现检测 The DefaultDataSource supports both local and Http sources. It automatically detects which one to use.
// DefaultDataSource.Factory defaultDataSourceFactory = new DefaultDataSourceFactory(MusicApplication.myApplication, httpDataSourceFactory);
DefaultDataSource.Factory upstreamFactory = new DefaultDataSource.Factory(this);
DynamicMediaSourceFactory customMediaSourceFactory = new DynamicMediaSourceFactory(upstreamFactory,cache);
// DynamicMediaSourceFactory customMediaSourceFactory = new DynamicMediaSourceFactory(new DefaultMediaSourceFactory(new DefaultHttpDataSource.Factory()),cache);
DefaultMediaSourceFactory defaultMediaSourceFactory1 = new DefaultMediaSourceFactory(getUrlFactory());
@ -53,8 +69,13 @@ public class PlaybackService extends MediaSessionService {
10000, // bufferForPlaybackMs: 播放时的目标缓冲时间毫秒
5000) // bufferForPlaybackAfterRebufferMs: 重新缓冲后的缓冲时间毫秒)
.build();
player = new ExoPlayer.Builder(this)
// .setMediaSourceFactory(customMediaSourceFactory)
.setMediaSourceFactory(customMediaSourceFactory)
// .setLoadControl(loadControl)
.build();
mediaSession = new MediaSession.Builder(this, player)

View File

@ -26,7 +26,7 @@ public class ObserverWrapper<T> implements Observer<T> {
@Override
public void onError(Throwable e) {
CommonUtils.LogMsg("----------onError"+e.getMessage());
CommonUtils.LogMsg("----------onError---"+e.getMessage());
requestListener.onFail(e.getMessage());
}

View File

@ -53,7 +53,7 @@ public class RetrofitManager {
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(httpLoggingInterceptor)
// .addInterceptor(httpLoggingInterceptor)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(base_Host)

View File

@ -73,6 +73,12 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
private GradientDrawable gradientDrawable;
private int lighterColor, darkerColor;
// 0 播放列表请求失败 1 立即播放的歌曲请求失败
private int netError = 0;
// 请求失败的立即播放的歌曲信息
private CustomerUrlInfo mCustomerUrlInfo;
@Override
protected ActivityPlayBinding getViewBinding() {
@ -94,7 +100,9 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
@Override
public void onChanged(List<ResponsePlayListInfo> playList) {
if (playList == null) {
CommonUtils.LogMsg("---------playList = null");
CommonUtils.LogErrorMsg("---------playList = null");
netError = 0;
vb.linearRetry.setVisibility(View.VISIBLE);
return;
}
if (playList.size() > 0) {
@ -111,7 +119,12 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
public void onChanged(CustomerUrlInfo customerUrlInfo) {
if (customerUrlInfo.isNeedPlayNow() && customerUrlInfo.getPlayUrl() == null) {
// TODO: 2024/9/26 需要马上播放这首歌曲但是此次网络请求失败
CommonUtils.LogMsg("-------------需要马上播放这首歌曲,但是此次网络请求失败");
CommonUtils.LogErrorMsg("-------------需要马上播放这首歌曲,但是此次网络请求失败");
netError = 1;
mCustomerUrlInfo = customerUrlInfo;
initShowPlayList(false);
vb.linearRetry.setVisibility(View.VISIBLE);
mediaControllerManager.pause();
return;
}
@ -119,13 +132,13 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
int second = customerUrlInfo.getPlayMusicIndex();
boolean needPlayNow = customerUrlInfo.isNeedPlayNow();
if (needPlayNow) {
mediaControllerManager.playPositionMusic(second);
mediaControllerManager.play();
}
}
});
}
@OptIn(markerClass = UnstableApi.class)
private void initPlayerView() {
vb.playerView.setShowRewindButton(false);
@ -154,35 +167,45 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
switch (playStatus) {
case Player.STATE_IDLE:
CommonUtils.LogMsg("-------------playStatus=STATE_IDLE");
CommonUtils.LogMsg("-------------IDLE");
break;
case Player.STATE_BUFFERING:
//快进没有缓冲的时候触发
vb.btnPlay.setSelected(false);
vb.progressBarLoading.setVisibility(View.VISIBLE);
CommonUtils.LogMsg("-------------playStatus=STATE_BUFFERING");
CommonUtils.LogMsg("-------------缓冲");
break;
case Player.STATE_READY:
vb.btnPlay.setSelected(true);
mHandler.post(mRunnable);
vb.progressBarLoading.setVisibility(View.GONE);
CommonUtils.LogMsg("-------------playStatus=STATE_READY");
CommonUtils.LogMsg("-------------准备");
break;
case Player.STATE_ENDED:
//播放完成
vb.btnPlay.setSelected(false);
CommonUtils.LogMsg("-------------playStatus=STATE_ENDED 播放完成");
CommonUtils.LogMsg("------------- 播放完成");
mHandler.removeCallbacks(mRunnable); // 停止更新
updatePlayComplete();
mediaControllerManager.playNext();
break;
case MyValue.PLAY_STATUS_CODE_PAUSE:
CommonUtils.LogMsg("------------- 暂停");
vb.btnPlay.setSelected(false);
vb.layoutPlayList.imPlay.setSelected(false);
break;
case MyValue.PLAY_STATUS_CODE_PLAYING:
CommonUtils.LogMsg("------------- 播放ing getCurIndex=" + mediaControllerManager.getCurIndex());
vb.progressBarLoading.setVisibility(View.GONE);
vb.btnPlay.setSelected(true);
vb.layoutPlayList.imPlay.setSelected(true);
break;
case MyValue.PLAY_STATUS_CODE_ERROR:
vb.progressBarLoading.setVisibility(View.GONE);
int currentMediaItemIndex = mediaControllerManager.getMediaController().getCurrentMediaItemIndex();
CommonUtils.LogMsg("------------- 播放错误 currentMediaItemIndex=" + currentMediaItemIndex);
break;
}
@ -190,7 +213,6 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
@Override
public void onRequestNextUri(String videoId, int playListIndex, boolean playNow) {
CommonUtils.LogMsg("------------onRequestNextUri= videoId=" + videoId);
if (playNow) {
vb.progressBarLoading.setVisibility(View.VISIBLE);
}
@ -215,6 +237,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
vb.btnPrevious.setOnClickListener(this);
vb.imBack.setOnClickListener(this);
vb.btnMusicList.setOnClickListener(this);
vb.tvRetry.setOnClickListener(this);
}
@ -363,9 +386,19 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
} else {
mediaControllerManager.pause();
}
if(adapterPlayList!= null){
if (adapterPlayList != null) {
adapterPlayList.updateCurMusicAnimation();
}
} else if (v.equals(vb.tvRetry)) {
vb.linearRetry.setVisibility(View.GONE);
if (netError == 0) {
vmPlay.getPlayMusicList(responseSingle);
} else {
if (mCustomerUrlInfo != null) {
vmPlay.getPlayUrl(mCustomerUrlInfo.getVideoId(), mCustomerUrlInfo.getPlayMusicIndex(), true);
}
}
}
}
@ -387,7 +420,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
List<ResponsePlayListInfo> playList = mediaControllerManager.getPlayList();
adapterPlayList = new AdapterPlayList();
vb.layoutPlayList.recyclerList.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication));
adapterPlayList.addData(playList);
adapterPlayList.setData(playList);
vb.layoutPlayList.recyclerList.setAdapter(adapterPlayList);
vb.layoutPlayList.imPlay.setOnClickListener(this);
initPlayList = true;

View File

@ -41,6 +41,7 @@ public class VMPlay extends ViewModel {
@Override
public void onFail(String errorMsg) {
// TODO: 2024/10/8 播放列表拉取失败
_playList.setValue(null);
}
@ -63,10 +64,12 @@ public class VMPlay extends ViewModel {
public void getPlayUrl(String videoId, int playListIndex,boolean playNow) {
CustomerUrlInfo customerUrlInfo = new CustomerUrlInfo();
customerUrlInfo.setNeedPlayNow(playNow);
customerUrlInfo.setVideoId(videoId);
RetrofitManager.getInstance().getPlayUrl(videoId, new RequestListener<ResponseBody>() {
@Override
public void onFail(String errorMsg) {
CommonUtils.LogMsg("-------------此次网络请求失败 playNow="+playNow);
_playUrlMutableLiveData.setValue(customerUrlInfo);
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="10dp"/>
<solid android:color="@color/cur_play_music"/>
</shape>

View File

@ -37,6 +37,39 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/im_back" />
<LinearLayout
android:layout_width="140dp"
android:layout_height="100dp"
android:background="@drawable/bg_retry"
android:gravity="center"
android:orientation="vertical"
android:id="@+id/linear_retry"
android:visibility="gone"
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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/An_error_occurred"
android:textColor="@color/black"
android:textSize="15sp" />
<TextView
android:id="@+id/tv_retry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="@string/retry"
android:textColor="@color/black"
android:textSize="17sp" />
</LinearLayout>
<androidx.media3.ui.PlayerView
android:id="@+id/player_view"
@ -183,6 +216,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
android:indeterminateTint="@color/white" />
android:indeterminateTint="@color/white"
android:visibility="gone" />
</FrameLayout>

View File

@ -22,4 +22,6 @@
<string name="privacy_policy">Privacy Policy</string>
<string name="terms_of_service">Terms of Service</string>
<string name="play_next">Play next</string>
<string name="retry">Retry</string>
<string name="An_error_occurred">An error occurred</string>
</resources>