ui优化,喜爱列表增加下载功能,播放页面优先去下载缓存里面找数据
This commit is contained in:
parent
64728f5096
commit
bdbf4b0eae
@ -49,7 +49,7 @@
|
||||
},
|
||||
{
|
||||
"id": "2:2417298624721077393",
|
||||
"lastPropertyId": "8:376288481537034221",
|
||||
"lastPropertyId": "9:2139176999400933939",
|
||||
"name": "BoxDownloadSong",
|
||||
"properties": [
|
||||
{
|
||||
@ -89,8 +89,8 @@
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "8:376288481537034221",
|
||||
"name": "cachePath",
|
||||
"id": "9:2139176999400933939",
|
||||
"name": "videoUrl",
|
||||
"type": 9
|
||||
}
|
||||
],
|
||||
@ -105,7 +105,9 @@
|
||||
"modelVersionParserMinimum": 5,
|
||||
"retiredEntityUids": [],
|
||||
"retiredIndexUids": [],
|
||||
"retiredPropertyUids": [],
|
||||
"retiredPropertyUids": [
|
||||
376288481537034221
|
||||
],
|
||||
"retiredRelationUids": [],
|
||||
"version": 1
|
||||
}
|
||||
@ -40,7 +40,7 @@ public class MusicApplication extends Application {
|
||||
super.onCreate();
|
||||
myApplication = this;
|
||||
ObjectBoxManager.init(this);
|
||||
MyDownloadService.init(this);
|
||||
// MyDownloadService.init(this);
|
||||
MyMediaControllerManager.getInstance().init(new MediaControllerStatusListener() {
|
||||
@Override
|
||||
public void onMediaControllerComplete(boolean isOk) {
|
||||
|
||||
@ -38,7 +38,7 @@ public class AdapterDownloadSong extends BaseAdapter<Download, ItemLikeSongBindi
|
||||
Download download = data.get(position);
|
||||
BoxDownloadSong boxDownloadSong = CommonUtils.downloadToBean(download);
|
||||
|
||||
|
||||
vb.layoutDownload.setVisibility(View.GONE);
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.load(boxDownloadSong.getCovert())
|
||||
|
||||
@ -1,12 +1,22 @@
|
||||
package com.hi.music.player.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.exoplayer.offline.Download;
|
||||
import androidx.media3.exoplayer.offline.DownloadRequest;
|
||||
import androidx.media3.exoplayer.offline.DownloadService;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
@ -16,28 +26,152 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.google.gson.Gson;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.api.onCheckDownload;
|
||||
import com.hi.music.player.databinding.ItemLikeSongBinding;
|
||||
import com.hi.music.player.databinding.ItemSingerBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.BoxDownloadSong;
|
||||
import com.hi.music.player.javabean.BoxLikeSong;
|
||||
import com.hi.music.player.javabean.CustomerDownload;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
||||
import com.hi.music.player.media3.MyDownloadService;
|
||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
||||
import com.hi.music.player.network.JsonHelper;
|
||||
import com.hi.music.player.network.RetrofitManager;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
public class AdapterLikeSong extends BaseAdapter<BoxLikeSong, ItemLikeSongBinding> {
|
||||
|
||||
private VMApplication vmApplication;
|
||||
|
||||
private List<Pair<Boolean, String>> status = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected ItemLikeSongBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemLikeSongBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
|
||||
public AdapterLikeSong(Context mContext, VMApplication vm) {
|
||||
super(mContext);
|
||||
vmApplication = vm;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void updateDownloadStatus(boolean isSuccess, int position, String videoId) {
|
||||
status.add(new Pair<>(isSuccess, videoId));
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
VHolder<ItemLikeSongBinding> itemHolder = (VHolder<ItemLikeSongBinding>) holder;
|
||||
ItemLikeSongBinding vb = itemHolder.getVb();
|
||||
BoxLikeSong boxLikeSong = data.get(position);
|
||||
String videoId = boxLikeSong.getVideoId();
|
||||
|
||||
|
||||
for(Pair<Boolean,String> pair:status){
|
||||
if(pair.second.equals(videoId)){
|
||||
vb.imDownload.setSelected(pair.first);
|
||||
vb.imDownload.setVisibility(View.VISIBLE);
|
||||
vb.downloadPb.setVisibility(View.GONE);
|
||||
CommonUtils.LogMsg("--------------------状态更新");
|
||||
}
|
||||
}
|
||||
|
||||
MyDownloadService.queryIsDownload(videoId, new onCheckDownload() {
|
||||
@Override
|
||||
public void onHasDownload(CustomerDownload customerDownload) {
|
||||
boolean download = customerDownload.isDownload();
|
||||
if (download) {
|
||||
vb.imDownload.setSelected(true);
|
||||
} else {
|
||||
vb.imDownload.setSelected(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
vb.layoutDownload.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (vb.imDownload.isSelected()) {
|
||||
//已经下载
|
||||
Toast.makeText(mContext,mContext.getText(R.string.text_has_downloaded),Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
vb.imDownload.setVisibility(View.GONE);
|
||||
vb.downloadPb.setVisibility(View.VISIBLE);
|
||||
RetrofitManager.getInstance().getPlayUrl(videoId, new com.hi.music.player.api.RequestListener<ResponseBody>() {
|
||||
|
||||
@Override
|
||||
public void onFail(String errorMsg) {
|
||||
CommonUtils.LogMsg("-------------onFail");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(JSONObject data) {
|
||||
// JSONObject jsonObject = CommonUtils.toJsonObject(data);
|
||||
if (data != null) {
|
||||
ResponsePlayUrl responsePlayUrl = JsonHelper.ResolvePlayUrlJson(data);
|
||||
if (responsePlayUrl == null) {
|
||||
// TODO: 2024/9/27
|
||||
return;
|
||||
}
|
||||
String videoUrlMedium = responsePlayUrl.getVideoUrlMedium();
|
||||
|
||||
BoxDownloadSong downloadSong = new BoxDownloadSong();
|
||||
downloadSong.setVideoId(videoId);
|
||||
downloadSong.setCovert(String.valueOf(boxLikeSong.getCovert()));
|
||||
downloadSong.setSongName((String) boxLikeSong.getSongName());
|
||||
downloadSong.setSingerName((String) boxLikeSong.getSingerName());
|
||||
downloadSong.setDuration((String) boxLikeSong.getDuration());
|
||||
downloadSong.setDurationMs(boxLikeSong.getDurationMs());
|
||||
downloadSong.setVideoUrl(videoUrlMedium);
|
||||
Gson gson = new Gson();
|
||||
String info = gson.toJson(downloadSong);
|
||||
byte[] bytes = info.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
DownloadRequest downloadRequest = new DownloadRequest.Builder(videoId, Uri.parse(videoUrlMedium))
|
||||
.setMimeType("video/mp4")
|
||||
.setData(bytes)
|
||||
.build();
|
||||
|
||||
|
||||
DownloadService.sendAddDownload(
|
||||
mContext,
|
||||
MyDownloadService.class, // 上面定义的下载服务类
|
||||
downloadRequest,
|
||||
true // 是否在前台运行
|
||||
);
|
||||
if (homeItemClickListener != null) {
|
||||
homeItemClickListener.onDownloadSong(videoId, itemHolder.getAbsoluteAdapterPosition());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.load(boxLikeSong.getCovert())
|
||||
@ -62,9 +196,9 @@ public class AdapterLikeSong extends BaseAdapter<BoxLikeSong, ItemLikeSongBindin
|
||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(homeItemClickListener!= null){
|
||||
if (homeItemClickListener != null) {
|
||||
int absoluteAdapterPosition = itemHolder.getAbsoluteAdapterPosition();
|
||||
homeItemClickListener.onClickLikeSong(boxLikeSong,absoluteAdapterPosition);
|
||||
homeItemClickListener.onClickLikeSong(boxLikeSong, absoluteAdapterPosition);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -28,8 +28,8 @@ public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayL
|
||||
|
||||
private String lastVideId;
|
||||
|
||||
// private int curMusicPos = 0;
|
||||
private MyMediaControllerManager instance = MyMediaControllerManager.getInstance();
|
||||
// private int curMusicPos = 0;
|
||||
private MyMediaControllerManager instance = MyMediaControllerManager.getInstance();
|
||||
|
||||
@Override
|
||||
protected ItemPlayListBinding getViewBinding(ViewGroup parent) {
|
||||
@ -51,23 +51,9 @@ 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(){
|
||||
public void updateCurMusicAnimation() {
|
||||
int curIndex = instance.getCurIndex();
|
||||
CommonUtils.LogMsg("--curIndex="+curIndex);
|
||||
CommonUtils.LogMsg("--curIndex=" + curIndex);
|
||||
notifyItemChanged(curIndex);
|
||||
}
|
||||
|
||||
@ -80,12 +66,20 @@ public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayL
|
||||
vb.songName.setText(listInfo.getSongTitle());
|
||||
String singerName = listInfo.getSingerName();
|
||||
String describe = listInfo.getDescribe();
|
||||
if(singerName!= null&&!singerName.isEmpty()){
|
||||
if (singerName != null && !singerName.isEmpty()) {
|
||||
vb.artistName.setText(singerName);
|
||||
}else if(describe!= null&&!describe.isEmpty()){
|
||||
} else if (describe != null && !describe.isEmpty()) {
|
||||
vb.artistName.setText(describe);
|
||||
}
|
||||
String covert = listInfo.getSmallCovert();
|
||||
|
||||
String covert;
|
||||
String small = listInfo.getSmallCovert();
|
||||
String covert1 = listInfo.getCovert();
|
||||
if (small == null || small.isEmpty()) {
|
||||
covert = covert1;
|
||||
} else {
|
||||
covert = small;
|
||||
}
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
// .apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10))))
|
||||
@ -93,17 +87,17 @@ public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayL
|
||||
.placeholder(R.drawable.placeholder)
|
||||
.into(vb.imCovert);
|
||||
|
||||
MediaItem currentMediaItem = instance.getMediaController().getCurrentMediaItem();
|
||||
MediaItem currentMediaItem = instance.getCurMediaItem();
|
||||
if (currentMediaItem != null && currentMediaItem.mediaId.equals(listInfo.getVideoId())) {
|
||||
vb.viewPlaying.setVisibility(View.VISIBLE);
|
||||
vb.itemLayout.setBackgroundColor(CommonUtils.getMyColor(R.color.cur_play_music));
|
||||
if (instance.getMediaController().isPlaying()) {
|
||||
if (instance.getIsPlaying()) {
|
||||
vb.viewPlaying.startAnimating();
|
||||
lastVideId = listInfo.getVideoId();
|
||||
CommonUtils.LogMsg("-------playAnimation "+itemHolder.getAbsoluteAdapterPosition());
|
||||
CommonUtils.LogMsg("-------playAnimation " + itemHolder.getAbsoluteAdapterPosition());
|
||||
} else {
|
||||
vb.viewPlaying.pauseAnimating();
|
||||
CommonUtils.LogMsg("-------pauseAnimation "+itemHolder.getAbsoluteAdapterPosition());
|
||||
CommonUtils.LogMsg("-------pauseAnimation " + itemHolder.getAbsoluteAdapterPosition());
|
||||
}
|
||||
} else {
|
||||
vb.viewPlaying.setVisibility(View.GONE);
|
||||
@ -114,7 +108,7 @@ public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayL
|
||||
vb.itemLayout.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
CommonUtils.LogMsg("-------onClick curMusicPos="+itemHolder.getAbsoluteAdapterPosition());
|
||||
CommonUtils.LogMsg("-------onClick curMusicPos=" + itemHolder.getAbsoluteAdapterPosition());
|
||||
setCurVideId(listInfo.getVideoId());
|
||||
instance.playPositionMusic(itemHolder.getAbsoluteAdapterPosition());
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ import com.hi.music.player.databinding.ItemResultListSongBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.response.child.ResponseResultListChild;
|
||||
|
||||
public class AdapterResultListSong extends BaseAdapter<ResponseResultListChild, ItemResultListSongBinding>{
|
||||
public class AdapterResultListSong extends BaseAdapter<ResponseResultListChild, ItemResultListSongBinding> {
|
||||
@Override
|
||||
protected ItemResultListSongBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemResultListSongBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
@ -54,23 +54,30 @@ public class AdapterResultListSong extends BaseAdapter<ResponseResultListChild,
|
||||
})
|
||||
.into(vb.imCovert);
|
||||
vb.tvSongName.setText(listChild.getSongName());
|
||||
String s = listChild.getSubTitle() +" • "+listChild.getPlayCount();
|
||||
vb.tvSubtitle.setText(s);
|
||||
String playCount = listChild.getPlayCount();
|
||||
String subTitle = listChild.getSubTitle();
|
||||
if (playCount == null){
|
||||
vb.tvSubtitle.setText(subTitle);
|
||||
}else {
|
||||
String s = subTitle + " • " + playCount;
|
||||
vb.tvSubtitle.setText(s);
|
||||
}
|
||||
|
||||
|
||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(homeItemClickListener != null){
|
||||
if (homeItemClickListener != null) {
|
||||
int absoluteAdapterPosition = itemHolder.getAbsoluteAdapterPosition();
|
||||
String videoId = listChild.getVideoId();
|
||||
String browserId = listChild.getBrowserId();
|
||||
homeItemClickListener.onClickResultSong(listChild,absoluteAdapterPosition);
|
||||
homeItemClickListener.onClickResultSong(listChild, absoluteAdapterPosition);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CommonUtils.LogMsg("-------Song getBrowserId="+listChild.getBrowserId()+"---getPlayListId= "+listChild.getPlayListId()+"---getVideoId="+listChild.getVideoId());
|
||||
CommonUtils.LogMsg("-------Song getBrowserId=" + listChild.getBrowserId() + "---getPlayListId= " + listChild.getPlayListId() + "---getVideoId=" + listChild.getVideoId());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,6 +80,15 @@ public interface HomeItemClickListener {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开始下载歌曲
|
||||
* @param boxLikeSong
|
||||
* @param index
|
||||
*/
|
||||
default void onDownloadSong(String videoId, int index){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击下载歌曲列表的某一首歌曲
|
||||
* @param index
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
package com.hi.music.player.api;
|
||||
|
||||
import com.hi.music.player.javabean.CustomerDownload;
|
||||
|
||||
public interface onCheckDownload {
|
||||
void onHasDownload(CustomerDownload customerDownload);
|
||||
}
|
||||
@ -47,7 +47,7 @@ public class DialogPlayList extends BaseDialog<DialogPlayListBinding> {
|
||||
instance = MyMediaControllerManager.getInstance();
|
||||
initPlayListUi();
|
||||
|
||||
MediaItem currentMediaItem = instance.getMediaController().getCurrentMediaItem();
|
||||
MediaItem currentMediaItem = instance.getCurMediaItem();
|
||||
if (currentMediaItem != null) {
|
||||
Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri;
|
||||
vb.topSongName.setText(currentMediaItem.mediaMetadata.title);
|
||||
@ -93,7 +93,7 @@ public class DialogPlayList extends BaseDialog<DialogPlayListBinding> {
|
||||
})
|
||||
.into(vb.topIm);
|
||||
}
|
||||
vb.imPlay.setSelected(instance.getMediaController().isPlaying());
|
||||
vb.imPlay.setSelected(instance.getIsPlaying());
|
||||
|
||||
vb.imPlay.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
||||
@ -15,7 +15,12 @@ import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.MediaMetadata;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.datasource.cache.Cache;
|
||||
import androidx.media3.datasource.cache.CacheEvictor;
|
||||
import androidx.media3.datasource.cache.CacheSpan;
|
||||
import androidx.media3.datasource.cache.SimpleCache;
|
||||
import androidx.media3.exoplayer.offline.Download;
|
||||
import androidx.palette.graphics.Palette;
|
||||
|
||||
@ -28,10 +33,12 @@ import com.hi.music.player.javabean.BoxDownloadSong;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import java.util.NavigableSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
@ -239,7 +246,7 @@ public class CommonUtils {
|
||||
});
|
||||
}
|
||||
|
||||
private static void createGradientBackground(int leftColor, int rightColor, View view) {
|
||||
public static void createGradientBackground(int leftColor, int rightColor, View view) {
|
||||
GradientDrawable gradientDrawable = new android.graphics.drawable.GradientDrawable(
|
||||
android.graphics.drawable.GradientDrawable.Orientation.LEFT_RIGHT,
|
||||
new int[]{leftColor, rightColor}
|
||||
@ -288,4 +295,30 @@ public class CommonUtils {
|
||||
|
||||
return gson.fromJson(additionalData, BoxDownloadSong.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
public static MediaItem downloadToMediaItem(Download data){
|
||||
MediaItem mediaItem = data.request.toMediaItem();
|
||||
BoxDownloadSong boxDownloadSong = CommonUtils.downloadToBean(data);
|
||||
MediaItem.Builder builder = mediaItem.buildUpon();
|
||||
|
||||
MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder();
|
||||
metadataBuilder.setArtist(boxDownloadSong.getSingerName());
|
||||
metadataBuilder.setDescription(boxDownloadSong.getDuration());
|
||||
metadataBuilder.setDurationMs(boxDownloadSong.getDurationMs());
|
||||
metadataBuilder.setArtworkUri(Uri.parse(boxDownloadSong.getCovert()));
|
||||
metadataBuilder.setTitle(boxDownloadSong.getSongName());
|
||||
builder.setMediaMetadata(metadataBuilder.build());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
// @OptIn(markerClass = UnstableApi.class)
|
||||
// public static boolean isSongCached(SimpleCache cache, String id) {
|
||||
//
|
||||
// return cachedFile.exists();
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
@ -91,6 +91,9 @@ public class MyValue {
|
||||
//从喜爱歌曲进入
|
||||
public final static int TYPE_ENTER_LIKE= 4;
|
||||
|
||||
//从下载歌曲进入
|
||||
public final static int TYPE_ENTER_DOWNLOAD= 5;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -16,8 +16,8 @@ public class BoxDownloadSong {
|
||||
private long durationMs;
|
||||
private String duration ;
|
||||
|
||||
//下载的音视频文件存储路径
|
||||
private String cachePath ;
|
||||
// 音视频文件uri
|
||||
private String videoUrl ;
|
||||
|
||||
public BoxDownloadSong( ) {
|
||||
|
||||
@ -32,12 +32,12 @@ public class BoxDownloadSong {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public String getCachePath() {
|
||||
return cachePath;
|
||||
public String getVideoUrl() {
|
||||
return videoUrl;
|
||||
}
|
||||
|
||||
public void setCachePath(String cachePath) {
|
||||
this.cachePath = cachePath;
|
||||
public void setVideoUrl(String videoUrl) {
|
||||
this.videoUrl = videoUrl;
|
||||
}
|
||||
|
||||
public long getDurationMs() {
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
package com.hi.music.player.javabean;
|
||||
|
||||
import androidx.media3.exoplayer.offline.Download;
|
||||
|
||||
public class CustomerDownload {
|
||||
|
||||
private Download download;
|
||||
|
||||
private boolean isDownload;
|
||||
|
||||
|
||||
public CustomerDownload(Download download, boolean isDownload) {
|
||||
this.download = download;
|
||||
this.isDownload = isDownload;
|
||||
}
|
||||
|
||||
public Download getDownloadData() {
|
||||
return download;
|
||||
}
|
||||
|
||||
public boolean isDownload() {
|
||||
return isDownload;
|
||||
}
|
||||
}
|
||||
@ -35,20 +35,14 @@ import okhttp3.ResponseBody;
|
||||
|
||||
|
||||
public class DynamicMediaSourceFactory implements MediaSource.Factory {
|
||||
// private final CacheDataSource.Factory cacheDataSourceFactory;
|
||||
// private final ExoPlayer player;
|
||||
|
||||
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(DataSource.Factory factory, SimpleCache cache) {
|
||||
public DynamicMediaSourceFactory(DataSource.Factory factory) {
|
||||
|
||||
this.mediaSourceFactory = factory;
|
||||
this.simpleCache = cache;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -76,41 +70,7 @@ public class DynamicMediaSourceFactory implements MediaSource.Factory {
|
||||
|
||||
|
||||
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();
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
// });
|
||||
|
||||
|
||||
|
||||
|
||||
@ -118,12 +78,12 @@ public class DynamicMediaSourceFactory implements MediaSource.Factory {
|
||||
// 这里的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);
|
||||
// CacheDataSource.Factory cacheDataSourceFactory = new CacheDataSource.Factory()
|
||||
// .setCache(simpleCache)
|
||||
// .setUpstreamDataSourceFactory(mediaSourceFactory)
|
||||
// .setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
|
||||
|
||||
MediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
|
||||
MediaSource mediaSource = new ProgressiveMediaSource.Factory(mediaSourceFactory)
|
||||
.createMediaSource(mediaItem);
|
||||
|
||||
return mediaSource;
|
||||
|
||||
@ -12,7 +12,10 @@ import com.hi.music.player.MusicApplication;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class MyCacheManager {
|
||||
/**
|
||||
* 下载缓存
|
||||
*/
|
||||
public class MyDownloadCacheManager {
|
||||
|
||||
private static SimpleCache downloadCache;
|
||||
|
||||
@ -2,6 +2,7 @@ package com.hi.music.player.media3;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -17,15 +18,12 @@ import androidx.media3.exoplayer.offline.DownloadNotificationHelper;
|
||||
import androidx.media3.exoplayer.offline.DownloadService;
|
||||
import androidx.media3.exoplayer.scheduler.Scheduler;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.api.onCheckDownload;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.BoxDownloadSong;
|
||||
import com.hi.music.player.javabean.CustomerDownload;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
@ -52,10 +50,9 @@ public class MyDownloadService extends DownloadService {
|
||||
);
|
||||
}
|
||||
|
||||
public static void init(Context context) {
|
||||
public static void init(Context context, StandaloneDatabaseProvider databaseProvider) {
|
||||
if (mDownloadManager == null) {
|
||||
StandaloneDatabaseProvider databaseProvider = new StandaloneDatabaseProvider(context);
|
||||
SimpleCache downloadCache = MyCacheManager.getMyCache(databaseProvider);
|
||||
SimpleCache downloadCache = MyDownloadCacheManager.getMyCache(databaseProvider);
|
||||
DefaultHttpDataSource.Factory factory = new DefaultHttpDataSource.Factory();
|
||||
Executor downloadExecutor = Runnable::run;
|
||||
|
||||
@ -82,15 +79,22 @@ public class MyDownloadService extends DownloadService {
|
||||
@Override
|
||||
public void onDownloadChanged(@NonNull DownloadManager downloadManager, Download download, @Nullable Exception finalException) {
|
||||
String id = download.request.id;
|
||||
|
||||
|
||||
if (download.state == Download.STATE_COMPLETED) {
|
||||
// 下载完成
|
||||
vmApplication.setDownloadChange(new Pair<>(true,download));
|
||||
CommonUtils.LogMsg("----------------下载完成 id=" + id + "--thread=" + Thread.currentThread().getName());
|
||||
updateDownloadUi(vmApplication);
|
||||
|
||||
} else if (download.state == Download.STATE_FAILED) {
|
||||
// 下载失败
|
||||
CommonUtils.LogMsg("----------------下载失败 id=" + id + "---finalException=" + finalException.getMessage());
|
||||
|
||||
vmApplication.setDownloadChange(new Pair<>(false,download));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -102,6 +106,26 @@ public class MyDownloadService extends DownloadService {
|
||||
}
|
||||
|
||||
|
||||
public static void queryIsDownload(String videoId, onCheckDownload listener) {
|
||||
Disposable subscribe = Observable.fromCallable(() -> {
|
||||
// 不允许返回null,所以采用CustomerDownload类包装
|
||||
DownloadIndex downloadIndex = mDownloadManager.getDownloadIndex();
|
||||
Download download = downloadIndex.getDownload(videoId);
|
||||
|
||||
return new CustomerDownload(download, download != null);
|
||||
|
||||
}).subscribeOn(Schedulers.io())
|
||||
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(listener::onHasDownload);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 下载完成的数量增加
|
||||
*
|
||||
* @param vmApplication
|
||||
*/
|
||||
@UnstableApi
|
||||
public static void updateDownloadUi(VMApplication vmApplication) {
|
||||
Disposable subscribe = Observable.fromCallable(() -> {
|
||||
@ -141,47 +165,6 @@ public class MyDownloadService extends DownloadService {
|
||||
@NonNull
|
||||
@Override
|
||||
protected DownloadManager getDownloadManager() {
|
||||
// 初始化下载管理器
|
||||
// StandaloneDatabaseProvider databaseProvider = new StandaloneDatabaseProvider(this);
|
||||
// SimpleCache downloadCache = MyCacheManager.getMyCache(databaseProvider);
|
||||
// DefaultHttpDataSource.Factory factory = new DefaultHttpDataSource.Factory();
|
||||
// Executor downloadExecutor = Runnable::run;
|
||||
//
|
||||
// downloadManager = new DownloadManager(
|
||||
// this,
|
||||
// databaseProvider, // 数据库提供者
|
||||
// downloadCache,
|
||||
// factory, // 数据源工厂
|
||||
// downloadExecutor // 线程池
|
||||
// );
|
||||
//
|
||||
// downloadManager.setMaxParallelDownloads(3); // 设置最大并行下载数
|
||||
// downloadManager.addListener(new DownloadManager.Listener() {
|
||||
// @Override
|
||||
// public void onDownloadChanged(DownloadManager downloadManager, Download download, @Nullable Exception finalException) {
|
||||
// String id = download.request.id;
|
||||
// if (download.state == Download.STATE_COMPLETED) {
|
||||
// // 下载完成
|
||||
// CommonUtils.LogMsg("----------------下载完成 id="+id);
|
||||
// byte[] data = download.request.data;
|
||||
// String additionalData = new String(data, StandardCharsets.UTF_8);
|
||||
// Gson gson = new Gson();
|
||||
// BoxDownloadSong boxDownloadSong = gson.fromJson(additionalData, BoxDownloadSong.class);
|
||||
//
|
||||
//
|
||||
//
|
||||
// } else if (download.state == Download.STATE_FAILED) {
|
||||
// // 下载失败
|
||||
// CommonUtils.LogMsg("----------------下载失败 id="+id+"---finalException="+finalException.getMessage());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onDownloadRemoved(DownloadManager downloadManager, Download download) {
|
||||
// String id = download.request.id;
|
||||
// CommonUtils.LogMsg("----------------onDownloadRemoved id="+id);
|
||||
// }
|
||||
// });
|
||||
return getMyDownloadManager();
|
||||
}
|
||||
|
||||
|
||||
@ -19,9 +19,11 @@ 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.api.onCheckDownload;
|
||||
import com.hi.music.player.api.onPlayNextListener;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.CustomerDownload;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
||||
import com.hi.music.player.network.RetrofitManager;
|
||||
@ -42,7 +44,6 @@ public class MyMediaControllerManager {
|
||||
private VMApplication mVmApplication;
|
||||
|
||||
|
||||
|
||||
//播放列表总数量
|
||||
private List<ResponsePlayListInfo> playList;
|
||||
|
||||
@ -90,6 +91,11 @@ public class MyMediaControllerManager {
|
||||
mVmApplication.setPlayStatus(MyValue.PLAY_STATUS_CODE_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaItemTransition(@Nullable MediaItem mediaItem, int reason) {
|
||||
//当前媒体项发生变化,切歌
|
||||
@ -132,7 +138,7 @@ public class MyMediaControllerManager {
|
||||
});
|
||||
}
|
||||
|
||||
public void checkUrl(boolean playNextNow){
|
||||
public void checkUrl(boolean playNextNow) {
|
||||
if (mediaController.hasNextMediaItem()) {
|
||||
int nextMediaItemIndex = mediaController.getNextMediaItemIndex();
|
||||
onCallRequestUrl(nextMediaItemIndex, playNextNow, new OnHasUrlAction() {
|
||||
@ -157,6 +163,14 @@ public class MyMediaControllerManager {
|
||||
return mediaController;
|
||||
}
|
||||
|
||||
/**
|
||||
* 针对已经下载过的数据,从download构造出MediaItem 直接替换
|
||||
* @param index
|
||||
* @param mediaItem
|
||||
*/
|
||||
public void replaceMediaItem(int index, MediaItem mediaItem) {
|
||||
mediaController.replaceMediaItem(index, mediaItem);
|
||||
}
|
||||
|
||||
public long getContentPos() {
|
||||
if (mediaController == null) return 0;
|
||||
@ -167,22 +181,26 @@ public class MyMediaControllerManager {
|
||||
if (mediaController == null) return 0;
|
||||
return mediaController.getBufferedPosition();
|
||||
}
|
||||
|
||||
public MediaItem getCurMediaItem() {
|
||||
return mediaController.getCurrentMediaItem();
|
||||
}
|
||||
|
||||
public Boolean getIsPlaying() {
|
||||
return mediaController.isPlaying();
|
||||
}
|
||||
|
||||
public int getCurIndex() {
|
||||
return mediaController.getCurrentMediaItemIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* //0 不循环、1 单曲循环、2 列表循环、
|
||||
* //0 不循环、1 单曲循环、2 列表循环、
|
||||
*
|
||||
* @param mode
|
||||
*/
|
||||
public void setMode(int mode){
|
||||
switch (mode){
|
||||
public void setMode(int mode) {
|
||||
switch (mode) {
|
||||
case 0:
|
||||
mediaController.setRepeatMode(Player.REPEAT_MODE_OFF);
|
||||
break;
|
||||
@ -196,16 +214,16 @@ public class MyMediaControllerManager {
|
||||
|
||||
}
|
||||
|
||||
public int getRepeatMode(){
|
||||
public int getRepeatMode() {
|
||||
return mediaController.getRepeatMode();
|
||||
|
||||
}
|
||||
|
||||
public String getCurVideoId() {
|
||||
MediaItem currentMediaItem = mediaController.getCurrentMediaItem();
|
||||
if(currentMediaItem!= null){
|
||||
if (currentMediaItem != null) {
|
||||
return currentMediaItem.mediaId;
|
||||
}else {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -217,8 +235,8 @@ public class MyMediaControllerManager {
|
||||
*
|
||||
* @param playUrl
|
||||
*/
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
public void UpdateAudioUrl(ResponsePlayUrl playUrl, int index) {
|
||||
CommonUtils.LogMsg("-------------更新播放列表中的音频url= index=" + index);
|
||||
for (int i = 0; i < mediaController.getMediaItemCount(); i++) {
|
||||
MediaItem mediaItemAt = mediaController.getMediaItemAt(i);
|
||||
if (mediaItemAt.mediaId.equals(playUrl.getVideoId())) {
|
||||
@ -226,12 +244,7 @@ public class MyMediaControllerManager {
|
||||
MediaItem.Builder builder = mediaItemAt.buildUpon();
|
||||
builder.setMediaId(playUrl.getVideoId());
|
||||
builder.setUri(playUrl.getVideoUrlMedium());
|
||||
// if (playUrl.getAudioUrlMedium() != null) {
|
||||
// builder.setUri(playUrl.getAudioUrlMedium());
|
||||
// } else {
|
||||
// builder.setUri(playUrl.getAudioUrlLow());
|
||||
// }
|
||||
|
||||
builder.setCustomCacheKey(playUrl.getVideoUrlMedium());
|
||||
//针对于,已经从分类合集列表页面进入播放页面的数据(只有小的封面图)
|
||||
if (mediaItemAt.mediaMetadata.artworkUri == null) {
|
||||
MediaMetadata.Builder builder1 = mediaItemAt.mediaMetadata.buildUpon();
|
||||
@ -240,7 +253,7 @@ public class MyMediaControllerManager {
|
||||
}
|
||||
|
||||
CharSequence title = mediaController.getMediaItemAt(i).mediaMetadata.title;
|
||||
CommonUtils.LogMsg("-------------更新播放列表中的音频url= i=" + i + "---id=" + playUrl.getVideoId() + "----mediaController.size=" + mediaController.getMediaItemCount());
|
||||
CommonUtils.LogMsg("-------------更新播放列表中的音频--id=" + playUrl.getVideoId());
|
||||
mediaController.replaceMediaItem(i, builder.build());
|
||||
break;
|
||||
}
|
||||
@ -260,47 +273,6 @@ public class MyMediaControllerManager {
|
||||
mediaController.clearMediaItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加播放列表(不带音频url)
|
||||
* 注意没有setUri的不会被实际添加到mediaController,
|
||||
*
|
||||
* @param playUrl
|
||||
*/
|
||||
// @OptIn(markerClass = UnstableApi.class)
|
||||
// public void addMusicToPlayList(ResponsePlayUrl playUrl, int playListIndex) {
|
||||
// if (playListIndex < playList.size() && playListIndex >= mediaController.getMediaItemCount()) {
|
||||
// ResponsePlayListInfo listInfo = playList.get(playListIndex);
|
||||
// if (listInfo.getVideoId().equals(playUrl.getVideoId())) {
|
||||
// MediaItem.Builder builder = new MediaItem.Builder();
|
||||
//
|
||||
// //唯一标识符
|
||||
// builder.setMediaId(playUrl.getVideoId());
|
||||
// if (playUrl.getAudioUrlMedium() != null) {
|
||||
// builder.setUri(playUrl.getAudioUrlMedium());
|
||||
// } else {
|
||||
// builder.setUri(playUrl.getAudioUrlLow());
|
||||
// }
|
||||
//
|
||||
// MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
||||
//
|
||||
// MediaMetadata_builder.setArtist(listInfo.getSingerName());
|
||||
// /**
|
||||
// * 这里使用setDescription保存歌曲时长的分秒字符串
|
||||
// */
|
||||
// MediaMetadata_builder.setDescription(listInfo.getDuration());
|
||||
// MediaMetadata_builder.setDurationMs(listInfo.getDurationMs());
|
||||
// MediaMetadata_builder.setArtworkUri(Uri.parse(listInfo.getCovert()));
|
||||
//// MediaMetadata_builder.setArtworkUri(Uri.parse("https://t7.baidu.com/it/u=2604797219,1573897854&fm=193&f=GIF"));
|
||||
// MediaMetadata_builder.setTitle(listInfo.getSongTitle());
|
||||
//
|
||||
// CommonUtils.LogMsg("----------添加到播放列表 i=" + playListIndex + "---" + listInfo.getSongTitle() + "-------VideoId=" + listInfo.getVideoId());
|
||||
//// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
||||
// builder.setMediaMetadata(MediaMetadata_builder.build());
|
||||
// mediaController.addMediaItem(builder.build());
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 添加播放列表(不带音频url)
|
||||
@ -312,7 +284,6 @@ public class MyMediaControllerManager {
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
public void addMusicPlayList(List<ResponsePlayListInfo> listInfo) {
|
||||
playList = listInfo;
|
||||
List<MediaItem> mediaItems = new ArrayList<>();
|
||||
for (int i = 0; i < listInfo.size(); i++) {
|
||||
ResponsePlayListInfo playInfo = listInfo.get(i);
|
||||
|
||||
@ -321,16 +292,17 @@ public class MyMediaControllerManager {
|
||||
//唯一标识符
|
||||
builder.setMediaId(videoId);
|
||||
builder.setUri("-------test-----");
|
||||
builder.setCustomCacheKey(videoId);
|
||||
MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
||||
|
||||
MediaMetadata_builder.setArtist(playInfo.getSingerName());
|
||||
MediaMetadata_builder.setDescription(playInfo.getDuration());
|
||||
MediaMetadata_builder.setDurationMs(playInfo.getDurationMs());
|
||||
if (playInfo.getCovert() != null&&!playInfo.getCovert().isEmpty())
|
||||
if (playInfo.getCovert() != null && !playInfo.getCovert().isEmpty())
|
||||
MediaMetadata_builder.setArtworkUri(Uri.parse(playInfo.getCovert()));
|
||||
MediaMetadata_builder.setTitle(playInfo.getSongTitle());
|
||||
|
||||
CommonUtils.LogMsg("----------添加播放列表 i=" + i + "---" + playInfo.getSingerName() + "-------VideoId=" + videoId+"---playInfo.getDuration()="+playInfo.getDuration());
|
||||
CommonUtils.LogMsg("----------添加播放列表 i=" + i + "---" + playInfo.getSingerName() + "-------VideoId=" + videoId + "---playInfo.getDuration()=" + playInfo.getDuration());
|
||||
// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
||||
builder.setMediaMetadata(MediaMetadata_builder.build());
|
||||
mediaController.addMediaItem(builder.build());
|
||||
@ -339,6 +311,11 @@ public class MyMediaControllerManager {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void addMusicPlayList(MediaItem mediaItem) {
|
||||
mediaController.addMediaItem(mediaItem);
|
||||
}
|
||||
|
||||
public void play() {
|
||||
if (!mediaController.isPlaying()) {
|
||||
CommonUtils.LogMsg("-----------prepare");
|
||||
@ -410,18 +387,33 @@ public class MyMediaControllerManager {
|
||||
@Override
|
||||
public void onHasUrl() {
|
||||
mediaController.play();
|
||||
CommonUtils.LogMsg("-------------有有效URl--播放指定播放列表位置的歌曲 index="+index);
|
||||
CommonUtils.LogMsg("-------------有有效URl--播放指定播放列表位置的歌曲 index=" + index);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private void onCallRequestUrl(int index, boolean playNow, OnHasUrlAction action) {
|
||||
MediaItem mediaItemAt = mediaController.getMediaItemAt(index);
|
||||
boolean b = CommonUtils.hasValidUri(mediaItemAt);
|
||||
if (!b) {
|
||||
CommonUtils.LogMsg("-------------请求URl index" + index + "---playNow=" + playNow);
|
||||
mListener.onRequestNextUri(mediaItemAt.mediaId, index, playNow);
|
||||
//查看
|
||||
MyDownloadService.queryIsDownload(mediaItemAt.mediaId, new onCheckDownload() {
|
||||
@Override
|
||||
public void onHasDownload(CustomerDownload customerDownload) {
|
||||
if (customerDownload.isDownload()) {
|
||||
MediaItem mediaItem = CommonUtils.downloadToMediaItem(customerDownload.getDownloadData());
|
||||
mediaController.replaceMediaItem(index, mediaItem);
|
||||
CommonUtils.LogMsg("-------------请求URl 已经下载过 index" + index + "---playNow=" + playNow);
|
||||
} else {
|
||||
CommonUtils.LogMsg("-------------请求URl index" + index + "---playNow=" + playNow);
|
||||
mListener.onRequestNextUri(mediaItemAt.mediaId, index, playNow);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
action.onHasUrl();
|
||||
}
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
package com.hi.music.player.media3;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.database.StandaloneDatabaseProvider;
|
||||
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor;
|
||||
import androidx.media3.datasource.cache.SimpleCache;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
/**
|
||||
* 播放缓存
|
||||
*/
|
||||
public class MyPlayCacheManager {
|
||||
|
||||
private static SimpleCache playCache;
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
public static SimpleCache getInitPlayCache(Context context) {
|
||||
if (playCache == null) {
|
||||
File cacheDir = new File(context.getCacheDir(), "media_cache");
|
||||
long maxCacheSize = 100 * 1024 * 1024; // 缓存大小 100MB
|
||||
StandaloneDatabaseProvider databaseProvider = new StandaloneDatabaseProvider(context);
|
||||
playCache = new SimpleCache(cacheDir, new LeastRecentlyUsedCacheEvictor(maxCacheSize), databaseProvider);
|
||||
MyDownloadService.init(context,databaseProvider);
|
||||
}
|
||||
return playCache;
|
||||
}
|
||||
|
||||
public static SimpleCache getPlayCache() {
|
||||
return playCache;
|
||||
}
|
||||
}
|
||||
@ -1,39 +1,31 @@
|
||||
package com.hi.music.player.media3;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
|
||||
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.TransferListener;
|
||||
import androidx.media3.datasource.cache.CacheDataSource;
|
||||
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor;
|
||||
import androidx.media3.datasource.cache.SimpleCache;
|
||||
import androidx.media3.exoplayer.DefaultLoadControl;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
|
||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
||||
import androidx.media3.extractor.ExtractorsFactory;
|
||||
import androidx.media3.extractor.mkv.MatroskaExtractor;
|
||||
import androidx.media3.exoplayer.source.MediaSource;
|
||||
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
|
||||
import androidx.media3.session.MediaSession;
|
||||
import androidx.media3.session.MediaSessionService;
|
||||
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PlaybackService extends MediaSessionService {
|
||||
private MediaSession mediaSession = null;
|
||||
private ExoPlayer player;
|
||||
@ -43,98 +35,62 @@ 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);
|
||||
SimpleCache downloadCache = MyCacheManager.getMyCache(databaseProvider);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
DynamicMediaSourceFactory customMediaSourceFactory = new DynamicMediaSourceFactory(getCacheDataSourceFactory(this));
|
||||
DefaultMediaSourceFactory defaultMediaSourceFactory1 = new DefaultMediaSourceFactory(getUrlFactory());
|
||||
|
||||
|
||||
// 创建 DefaultLoadControl,配置缓冲参数
|
||||
DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
|
||||
.setBufferDurationsMs(10000, // minBufferMs: 播放前的最小缓冲时间(毫秒)
|
||||
60000, // maxBufferMs: 最大缓冲时间(毫秒)
|
||||
10000, // bufferForPlaybackMs: 播放时的目标缓冲时间(毫秒)
|
||||
5000) // bufferForPlaybackAfterRebufferMs: 重新缓冲后的缓冲时间(毫秒)
|
||||
.setBufferDurationsMs(3000, // minBufferMs: 播放前的最小缓冲时间(毫秒)
|
||||
300000, // maxBufferMs: 最大缓冲时间(毫秒)
|
||||
3000, // bufferForPlaybackMs: 播放时的目标缓冲时间(毫秒)
|
||||
2000) // bufferForPlaybackAfterRebufferMs: 重新缓冲后的缓冲时间(毫秒)
|
||||
.build();
|
||||
|
||||
|
||||
|
||||
|
||||
CacheDataSource.Factory cacheDataSourceFactory = getCacheDataSourceFactory(this);
|
||||
MediaSource.Factory mediaSourceFactory = new ProgressiveMediaSource.Factory(cacheDataSourceFactory);
|
||||
CacheDataSource dataSource = cacheDataSourceFactory.createDataSource();
|
||||
|
||||
player = new ExoPlayer.Builder(this)
|
||||
.setMediaSourceFactory(customMediaSourceFactory)
|
||||
// .setLoadControl(loadControl)
|
||||
.setMediaSourceFactory(mediaSourceFactory)
|
||||
.setLoadControl(loadControl)
|
||||
.build();
|
||||
mediaSession = new MediaSession.Builder(this, player)
|
||||
.build();
|
||||
|
||||
// player = new ExoPlayer.Builder(this)
|
||||
// .setWakeMode(C.WAKE_MODE_LOCAL)
|
||||
//// .setMediaSourceFactory(mediaSourceFactory)
|
||||
// .setAudioAttributes(audioAttributes, true).build();
|
||||
//
|
||||
// mediaSession = new MediaSession.Builder(this, player)
|
||||
// .setId(getString(R.string.app_name) + "_MusicId")
|
||||
// .setCallback(new MediaSession.Callback() {
|
||||
// @Override
|
||||
// public ListenableFuture<List<MediaItem>> onAddMediaItems(MediaSession mediaSession, MediaSession.ControllerInfo controller, List<MediaItem> mediaItems) {
|
||||
//
|
||||
// CommonUtils.LogMsg("--------实际添加的媒体项="+player.getMediaItemCount());
|
||||
//// player.addMediaItems(mediaItems);
|
||||
//
|
||||
// return MediaSession.Callback.super.onAddMediaItems(mediaSession, controller, mediaItems);
|
||||
// }
|
||||
// })
|
||||
// .build();
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 创建带缓存的数据源工厂
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private CacheDataSource.Factory getCacheDataSourceFactory(Context context) {
|
||||
DefaultDataSource.Factory factory = new DefaultDataSource.Factory(this);
|
||||
return new CacheDataSource.Factory()
|
||||
.setCache(MyPlayCacheManager.getInitPlayCache(context))
|
||||
.setUpstreamDataSourceFactory(factory)
|
||||
.setFlags(CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
|
||||
// .setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
|
||||
}
|
||||
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private DataSource.Factory getUrlFactory() {
|
||||
CommonUtils.LogMsg("--------getUrlFactory");
|
||||
return new ResolvingDataSource.Factory(getCacheDataSource(), new ResolvingDataSource.Resolver() {
|
||||
return new ResolvingDataSource.Factory(getCacheDataSourceFactory(this), new ResolvingDataSource.Resolver() {
|
||||
|
||||
@Override
|
||||
public DataSpec resolveDataSpec(DataSpec dataSpec) {
|
||||
|
||||
CommonUtils.LogMsg("--------resolveDataSpec=" + dataSpec.key);
|
||||
return null;
|
||||
|
||||
String string = "https://rr5---sn-ab5sznzy.googlevideo.com//videoplayback?expire=1730814877&ei=PM8pZ_37PL6b2_gP1LeTsQY&ip=146.19.167.8&id=o-AOdAohYUdM95I2jXmxqV5-JBeVgnMYAS3AKn2fsaiz72&itag=18&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&met=1730793277%2C&mh=Od&mm=31%2C29&mn=sn-ab5sznzy%2Csn-tt1e7nls&ms=au%2Crdu&mv=m&mvi=5&pl=24&rms=au%2Cau&gcr=us&initcwndbps=7066250&vprv=1&svpuc=1&xtags=heaudio%3Dtrue&mime=video%2Fmp4&rqh=1&cnr=14&ratebypass=yes&dur=181.394&lmt=1711913129189608&mt=1730792707&fvip=2&fexp=51312688%2C51326932&c=ANDROID&txp=4538434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cgcr%2Cvprv%2Csvpuc%2Cxtags%2Cmime%2Crqh%2Ccnr%2Cratebypass%2Cdur%2Clmt&sig=AJfQdSswRgIhAMmdioipTMb9rGt1ZIzbhTPL0yWZGnuorRv7jOS9THllAiEAnkSJJhOkXt3SdMYmeNuRMEosaJl2H00SQxORzbbGRP4%3D&lsparams=met%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Crms%2Cinitcwndbps&lsig=ACJ0pHgwRQIhANId6hdBj5z2g7IWnbCdzQ6MyYO_wit31Zaxh3VWahe7AiAIlubSJiPZP4deLNaBQ8eyT12Zf7nPkJ_ZZYBHeFf9XA%3D%3D";
|
||||
return dataSpec.withUri(Uri.parse(dataSpec.key));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private CacheDataSource.Factory getCacheDataSource() {
|
||||
// 1. 创建缓存对象
|
||||
SimpleCache simpleCache = new SimpleCache(
|
||||
new File(MusicApplication.myApplication.getCacheDir(), "media3_cache"), // 设置缓存目录
|
||||
new LeastRecentlyUsedCacheEvictor(100 * 1024 * 1024), // 设置最大缓存大小(例如 100MB)
|
||||
new StandaloneDatabaseProvider(MusicApplication.myApplication));
|
||||
|
||||
// 2. 创建 DataSource.Factory,用于加载媒体资源
|
||||
DataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(MusicApplication.myApplication);
|
||||
|
||||
// 3. 创建 CacheDataSource.Factory,包含缓存功能
|
||||
return new CacheDataSource.Factory()
|
||||
.setCache(simpleCache)
|
||||
.setUpstreamDataSourceFactory(dataSourceFactory) // 用于从网络加载的工厂
|
||||
.setCacheWriteDataSinkFactory(null); // 默认写入缓存
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) {
|
||||
|
||||
@ -203,7 +203,7 @@ public class JsonHelper {
|
||||
JSONArray thumbnails = videoDetails.getJSONObject("thumbnail").getJSONArray("thumbnails");
|
||||
|
||||
String url = thumbnails.getJSONObject(thumbnails.length() - 1).getString("url");
|
||||
CommonUtils.LogMsg("title="+title+"-------videoUrl="+videoUrl);
|
||||
|
||||
|
||||
responsePlayUrl.setBigCovert(url);
|
||||
responsePlayUrl.setVideoId(videoId);
|
||||
@ -314,7 +314,6 @@ public class JsonHelper {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (contentsArray.has("musicShelfRenderer")) {
|
||||
// MUSIC_PAGE_TYPE_ALBUM
|
||||
JSONArray jsonArray = contentsArray.getJSONObject("musicShelfRenderer")
|
||||
|
||||
@ -153,7 +153,7 @@ public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActiv
|
||||
rootVb.frameLayout.addView(panelView, layoutParams);
|
||||
mHandler.post(mRunnable);
|
||||
}
|
||||
MediaItem currentMediaItem = mediaControllerManager.getMediaController().getCurrentMediaItem();
|
||||
MediaItem currentMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
if(currentMediaItem!= null){
|
||||
Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri;
|
||||
CharSequence title = currentMediaItem.mediaMetadata.title;
|
||||
|
||||
@ -4,6 +4,8 @@ import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
@ -80,19 +82,32 @@ public class HomeActivity extends BaseActivity<ActivityHomeBinding> {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
updateTabIcon(tab, true); // 更新选中的图标
|
||||
int position = tab.getPosition();
|
||||
switch (position){
|
||||
case 0:
|
||||
vb.view.setVisibility(View.VISIBLE);
|
||||
vb.homeLayout.setBackgroundColor(ContextCompat.getColor(HomeActivity.this,R.color.black));
|
||||
break;
|
||||
case 1:
|
||||
vb.view.setVisibility(View.GONE);
|
||||
vb.homeLayout.setBackgroundColor(ContextCompat.getColor(HomeActivity.this,R.color.default_play_list_color));
|
||||
break;
|
||||
case 2:
|
||||
vb.view.setVisibility(View.GONE);
|
||||
vb.homeLayout.setBackground(ContextCompat.getDrawable(HomeActivity.this,R.mipmap.bg_library));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
|
||||
updateTabIcon(tab, false); // 恢复未选中图标
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
// 可选:重复选择Tab时的操作
|
||||
}
|
||||
});
|
||||
|
||||
// 设置默认选中第一个
|
||||
TabLayout.Tab firstTab = vb.homeTabLayout.getTabAt(0);
|
||||
if (firstTab != null) {
|
||||
@ -101,8 +116,6 @@ public class HomeActivity extends BaseActivity<ActivityHomeBinding> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void updateTabIcon(TabLayout.Tab tab, boolean isSelected) {
|
||||
HomeTabCustomBinding tabBinding = HomeTabCustomBinding.bind(tab.getCustomView());
|
||||
int position = tab.getPosition();
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.hi.music.player.ui.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.OptIn;
|
||||
@ -30,6 +31,9 @@ public class LikeSongActivity extends BaseActivity<ActivityLikeSongBinding> impl
|
||||
|
||||
private List<BoxLikeSong> boxLikeSongs;
|
||||
private int mType;
|
||||
|
||||
private List<Pair<Integer, String>> downloadList = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected ActivityLikeSongBinding getViewBinding() {
|
||||
return ActivityLikeSongBinding.inflate(getLayoutInflater());
|
||||
@ -41,16 +45,33 @@ public class LikeSongActivity extends BaseActivity<ActivityLikeSongBinding> impl
|
||||
Intent intent = getIntent();
|
||||
mType = intent.getIntExtra(MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE, MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE_LIKE);
|
||||
|
||||
switch (mType){
|
||||
switch (mType) {
|
||||
case MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE_LIKE:
|
||||
vb.tvTitle.setText(getString(R.string.text_like_song));
|
||||
boxLikeSongs = ObjectBoxManager.queryAllLike();
|
||||
AdapterLikeSong adapterLikeSong = new AdapterLikeSong();
|
||||
AdapterLikeSong adapterLikeSong = new AdapterLikeSong(this, vmApplication);
|
||||
adapterLikeSong.setHomeItemClickListener(this);
|
||||
adapterLikeSong.setData(boxLikeSongs);
|
||||
vb.recycler.setLayoutManager(new LinearLayoutManager(this));
|
||||
vb.recycler.setAdapter(adapterLikeSong);
|
||||
vb.tvSongSize.setText(String.format(getString(R.string.like_song), boxLikeSongs.size()));
|
||||
MyDownloadService.addDownloadListener(vmApplication);
|
||||
vmApplication.downloadChange.observe(this, new Observer<Pair<Boolean, Download>>() {
|
||||
@Override
|
||||
public void onChanged(Pair<Boolean, Download> booleanDownloadPair) {
|
||||
Boolean first = booleanDownloadPair.first;
|
||||
Download downloads = booleanDownloadPair.second;
|
||||
|
||||
String id = downloads.request.id;
|
||||
for (Pair<Integer,String> pair:downloadList){
|
||||
Integer position = pair.first;
|
||||
String videoId = pair.second;
|
||||
if(id.equals(videoId)){
|
||||
adapterLikeSong.updateDownloadStatus(first,position,videoId);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE_DOWNLOAD:
|
||||
@ -95,15 +116,15 @@ public class LikeSongActivity extends BaseActivity<ActivityLikeSongBinding> impl
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(v.equals(vb.imBack)){
|
||||
finish();
|
||||
}
|
||||
if (v.equals(vb.imBack)) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickLikeSong(BoxLikeSong boxLikeSong, int index) {
|
||||
List<ResponsePlayListInfo> playList = new ArrayList<>();
|
||||
for(BoxLikeSong song:boxLikeSongs){
|
||||
for (BoxLikeSong song : boxLikeSongs) {
|
||||
String videoId1 = song.getVideoId();
|
||||
String songName = song.getSongName();
|
||||
String covert = song.getCovert();
|
||||
@ -111,13 +132,13 @@ public class LikeSongActivity extends BaseActivity<ActivityLikeSongBinding> impl
|
||||
long durationMs = song.getDurationMs();
|
||||
String duration = song.getDuration();
|
||||
|
||||
ResponsePlayListInfo playListInfo = new ResponsePlayListInfo(covert, songName, singerName, durationMs, videoId1,duration);
|
||||
ResponsePlayListInfo playListInfo = new ResponsePlayListInfo(covert, songName, singerName, durationMs, videoId1, duration);
|
||||
playList.add(playListInfo);
|
||||
}
|
||||
vmApplication.reSetPlayList(playList);
|
||||
|
||||
String videoId = boxLikeSong.getVideoId();
|
||||
CommonUtils.LogMsg("-------------like进入 传值 videoId= "+videoId);
|
||||
CommonUtils.LogMsg("-------------like进入 传值 videoId= " + videoId);
|
||||
Intent intent = new Intent(this, PlayActivity.class);
|
||||
intent.putExtra(MyValue.KEY_PLAY_VIDEO_ID, videoId);
|
||||
intent.putExtra(MyValue.KEY_PLAY_INDEX, index);
|
||||
@ -125,12 +146,26 @@ public class LikeSongActivity extends BaseActivity<ActivityLikeSongBinding> impl
|
||||
startActivity(intent);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public void onClickDownloadSong(Download download, int index) {
|
||||
|
||||
// MyDownloadService.updateDownloadUi(vmApplication)
|
||||
|
||||
String videoId = download.request.id;
|
||||
CommonUtils.LogMsg("------------Download进入 传值 videoId= " + videoId);
|
||||
Intent intent = new Intent(this, PlayActivity.class);
|
||||
intent.putExtra(MyValue.KEY_PLAY_VIDEO_ID, videoId);
|
||||
intent.putExtra(MyValue.KEY_PLAY_INDEX, index);
|
||||
intent.putExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_DOWNLOAD);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadSong(String videoId, int index) {
|
||||
Pair<Integer, String> integerStringPair = new Pair<>(index, videoId);
|
||||
downloadList.add(integerStringPair);
|
||||
}
|
||||
}
|
||||
@ -20,6 +20,7 @@ import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.MediaMetadata;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.datasource.cache.SimpleCache;
|
||||
import androidx.media3.exoplayer.offline.Download;
|
||||
import androidx.media3.exoplayer.offline.DownloadManager;
|
||||
import androidx.media3.exoplayer.offline.DownloadRequest;
|
||||
@ -36,9 +37,11 @@ import com.bumptech.glide.request.target.Target;
|
||||
import com.google.gson.Gson;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.adapter.AdapterDownloadSong;
|
||||
import com.hi.music.player.adapter.AdapterPlayList;
|
||||
import com.hi.music.player.api.LikeSongListener;
|
||||
import com.hi.music.player.api.MediaControllerListener;
|
||||
import com.hi.music.player.api.onCheckDownload;
|
||||
import com.hi.music.player.api.onImageColorListener;
|
||||
import com.hi.music.player.api.onPlayNextListener;
|
||||
import com.hi.music.player.databinding.ActivityPlayBinding;
|
||||
@ -46,6 +49,7 @@ import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.BoxDownloadSong;
|
||||
import com.hi.music.player.javabean.BoxLikeSong;
|
||||
import com.hi.music.player.javabean.CustomerDownload;
|
||||
import com.hi.music.player.javabean.CustomerUrlInfo;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
||||
@ -53,11 +57,13 @@ import com.hi.music.player.javabean.response.child.ResponseCategory;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
||||
import com.hi.music.player.media3.MyDownloadService;
|
||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
||||
import com.hi.music.player.media3.MyPlayCacheManager;
|
||||
import com.hi.music.player.objectbox.ObjectBoxManager;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMPlay;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements SeekBar.OnSeekBarChangeListener {
|
||||
@ -106,6 +112,8 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
//0 不循环、1 列表循环、2 单曲循环、
|
||||
private int currentMode = 0;
|
||||
|
||||
private List<BoxDownloadSong> downloadSongList = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected ActivityPlayBinding getViewBinding() {
|
||||
return ActivityPlayBinding.inflate(getLayoutInflater());
|
||||
@ -113,16 +121,13 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
|
||||
@Override
|
||||
protected void onCreateInit() {
|
||||
vmPlay = getActivityScopeViewModel(VMPlay.class);
|
||||
// vmApplication = getApplicationScopeViewModel(VMApplication.class);
|
||||
initMediaController();
|
||||
// vb.progressBarLoading.setVisibility(View.VISIBLE);
|
||||
|
||||
vmPlay = getActivityScopeViewModel(VMPlay.class);
|
||||
initMediaController();
|
||||
Intent intent = getIntent();
|
||||
mEnterType = intent.getIntExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_SOURCE_SINGLE);
|
||||
initPlayerView();
|
||||
initProgressHandler();
|
||||
addDownloadListener();
|
||||
|
||||
CommonUtils.LogMsg("--------mEnterType=" + mEnterType);
|
||||
switch (mEnterType) {
|
||||
@ -135,6 +140,12 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
params = responseSingle.getParams();
|
||||
musicVideoType = responseSingle.getMusicVideoType();
|
||||
mDefaultPlayStartIndex = intent.getIntExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST_INDEX, mDefaultPlayStartIndex);
|
||||
|
||||
SimpleCache playCache = MyPlayCacheManager.getPlayCache();
|
||||
// boolean songCached = CommonUtils.isSongCached(playCache, videoId);
|
||||
|
||||
// CommonUtils.LogMsg("---------------是否有播放缓存--songCached="+songCached +"--name="+responseSingle.getSongTitle());
|
||||
|
||||
vmPlay.getPlayMusicList(playlistId, videoId, params, musicVideoType);
|
||||
vmPlay.playList.observe(this, new Observer<List<ResponsePlayListInfo>>() {
|
||||
@Override
|
||||
@ -185,11 +196,18 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
updateMediaPlayList();
|
||||
videoId = intent.getStringExtra(MyValue.KEY_PLAY_VIDEO_ID);
|
||||
mDefaultPlayStartIndex = intent.getIntExtra(MyValue.KEY_PLAY_INDEX, mDefaultPlayStartIndex);
|
||||
CommonUtils.LogMsg("-------------like进入 videoId= "+videoId+"---mDefaultPlayStartIndex="+mDefaultPlayStartIndex);
|
||||
CommonUtils.LogMsg("-------------like进入 videoId= " + videoId + "---mDefaultPlayStartIndex=" + mDefaultPlayStartIndex);
|
||||
break;
|
||||
|
||||
case MyValue.TYPE_ENTER_DOWNLOAD:
|
||||
// 5--从下载歌曲进入
|
||||
videoId = intent.getStringExtra(MyValue.KEY_PLAY_VIDEO_ID);
|
||||
mDefaultPlayStartIndex = intent.getIntExtra(MyValue.KEY_PLAY_INDEX, mDefaultPlayStartIndex);
|
||||
CommonUtils.LogMsg("-------------下载歌曲 videoId= " + videoId + "---mDefaultPlayStartIndex=" + mDefaultPlayStartIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
addDownloadListener();
|
||||
vmPlay.playUrlLiveData.observe(this, new Observer<CustomerUrlInfo>() {
|
||||
@Override
|
||||
public void onChanged(CustomerUrlInfo customerUrlInfo) {
|
||||
@ -205,10 +223,9 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
return;
|
||||
}
|
||||
int second = customerUrlInfo.getPlayMusicIndex();
|
||||
boolean needPlayNow = customerUrlInfo.isNeedPlayNow();
|
||||
if (needPlayNow) {
|
||||
if (customerUrlInfo.isNeedPlayNow()) {
|
||||
mediaControllerManager.playPositionMusic(second);
|
||||
mediaControllerManager.play();
|
||||
// mediaControllerManager.play();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -217,6 +234,9 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新播放列表
|
||||
*/
|
||||
private void updateMediaPlayList() {
|
||||
vmApplication.playList.observe(this, new Observer<List<ResponsePlayListInfo>>() {
|
||||
@Override
|
||||
@ -233,7 +253,6 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
updateErrorLayout(null, false);
|
||||
setPlayListAndGetUrl(playList, videoId, mDefaultPlayStartIndex);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -255,10 +274,26 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
* @param id
|
||||
* @param index
|
||||
*/
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private void setPlayListAndGetUrl(List<ResponsePlayListInfo> list, String id, int index) {
|
||||
mediaControllerManager.resetPlayList();
|
||||
MyMediaControllerManager.getInstance().setPlayList(list);
|
||||
vmPlay.getPlayUrl(id, index, true);
|
||||
MyDownloadService.queryIsDownload(id, new onCheckDownload() {
|
||||
@Override
|
||||
public void onHasDownload(CustomerDownload customerDownload) {
|
||||
if(customerDownload.isDownload()){
|
||||
MediaItem mediaItem = CommonUtils.downloadToMediaItem(customerDownload.getDownloadData());
|
||||
mediaControllerManager.replaceMediaItem(index,mediaItem);
|
||||
CommonUtils.LogMsg("-------------setPlayListAndGetUrl已经下载过 index" + index + "---playNow=" + true);
|
||||
mediaControllerManager.playPositionMusic(index);
|
||||
}else {
|
||||
CommonUtils.LogMsg("-------------setPlayListAndGetUrl index" + index + "---playNow=" + true);
|
||||
vmPlay.getPlayUrl(id, index, true);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@ -369,7 +404,6 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
|
||||
|
||||
String s = CommonUtils.convertMillisToTime(contentPos);
|
||||
CommonUtils.LogMsg("---------播放进度-----contentPos=" + contentPos + "-----s=" + s);
|
||||
vb.tvCurrent.setText(s);
|
||||
vb.playProgress.setProgress((int) contentPos);
|
||||
vb.progressBarBuffer.setProgress((int) bufferPos);
|
||||
@ -389,9 +423,8 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
*/
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private void loadInfo(MediaItem mediaItem) {
|
||||
|
||||
MediaMetadata mediaMetadata = mediaItem.mediaMetadata;
|
||||
CommonUtils.LogMsg("--------------加载当前播放歌曲信息 mediaMetadata.description="+mediaMetadata.description);
|
||||
CommonUtils.LogMsg("--------------加载当前播放歌曲信息 title=" + mediaMetadata.title);
|
||||
if (mediaMetadata.artworkUri != null) {
|
||||
loadCovert(mediaMetadata.artworkUri.toString());
|
||||
}
|
||||
@ -412,13 +445,21 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
boolean isLike = ObjectBoxManager.queryIsLike(mediaItem.mediaId);
|
||||
vb.imLike.setSelected(isLike);
|
||||
|
||||
//刷新当前歌曲的下载状态
|
||||
String mediaId = mediaItem.mediaId;
|
||||
MyDownloadService.queryIsDownload(mediaId, new onCheckDownload() {
|
||||
@Override
|
||||
public void onHasDownload(CustomerDownload customerDownload) {
|
||||
vb.imDownload.setSelected(customerDownload.isDownload());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void loadCovert(String url) {
|
||||
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(16))))
|
||||
.load(url)
|
||||
.placeholder(R.drawable.placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@ -434,8 +475,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
vb.playerView.setDefaultArtwork(resource);
|
||||
|
||||
vb.imCovert.setImageDrawable(resource);
|
||||
CommonUtils.getMainColor(resource, new onImageColorListener() {
|
||||
@Override
|
||||
public void onImageColor(int color) {
|
||||
@ -455,28 +495,6 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
}
|
||||
}
|
||||
});
|
||||
// CommonUtils.getDominantDarkColor1(resource, new onImageColorListener() {
|
||||
// @Override
|
||||
// public void onImageColor(int color) {
|
||||
// if (color == -1) {
|
||||
// return;
|
||||
// }
|
||||
// lighterColor = CommonUtils.adjustBrightness(color, 1f); // 比原始颜色亮 20%
|
||||
// darkerColor = CommonUtils.adjustBrightness(color, 0.6f); // 比原始颜色暗 20%
|
||||
// gradientDrawable = new GradientDrawable(
|
||||
// GradientDrawable.Orientation.TOP_BOTTOM,
|
||||
// new int[]{lighterColor, darkerColor} // 浅到深渐变
|
||||
// );
|
||||
// vb.rootLayout.setBackground(gradientDrawable);
|
||||
//
|
||||
// if (vb.layoutPlayList.linearLayout.getVisibility() == View.VISIBLE) {
|
||||
// updatePlayListColor();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
// });
|
||||
|
||||
return false;
|
||||
}
|
||||
})
|
||||
@ -592,12 +610,12 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
boolean newSelect = vb.imLike.isSelected();
|
||||
MediaItem curMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
MediaMetadata mediaMetadata = curMediaItem.mediaMetadata;
|
||||
if (mediaMetadata.title != null && mediaMetadata.artist != null&&mediaMetadata.durationMs!= null&&mediaMetadata.description!= null) {
|
||||
BoxLikeSong boxLikeSong = new BoxLikeSong(mediaMetadata.title.toString(),
|
||||
if (mediaMetadata.title != null && mediaMetadata.artist != null && mediaMetadata.durationMs != null && mediaMetadata.description != null) {
|
||||
BoxLikeSong boxLikeSong = new BoxLikeSong(mediaMetadata.title.toString(),
|
||||
mediaMetadata.artist.toString(),
|
||||
curMediaItem.mediaId,
|
||||
String.valueOf(mediaMetadata.artworkUri),
|
||||
mediaMetadata.durationMs,mediaMetadata.description.toString());
|
||||
mediaMetadata.durationMs, mediaMetadata.description.toString());
|
||||
if (newSelect) {
|
||||
ObjectBoxManager.insertOrUpdateLike(boxLikeSong);
|
||||
} else {
|
||||
@ -606,18 +624,23 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
}
|
||||
|
||||
|
||||
}else if(v.equals(vb.layoutDownload)){
|
||||
} else if (v.equals(vb.layoutDownload)) {
|
||||
if (vb.imDownload.isSelected()) {
|
||||
//已经下载
|
||||
Toast.makeText(this,getText(R.string.text_has_downloaded),Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
vb.downloadPb.setVisibility(View.VISIBLE);
|
||||
vb.imDownload.setVisibility(View.INVISIBLE);
|
||||
BoxDownloadSong curMediaItemInfo = getCurMediaItemInfo();
|
||||
if(curMediaItemInfo!= null){
|
||||
if (curMediaItemInfo != null) {
|
||||
Gson gson = new Gson();
|
||||
String info = gson.toJson(curMediaItemInfo);
|
||||
byte[] data = info.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
String videoId1 = curMediaItemInfo.getVideoId();
|
||||
CommonUtils.LogMsg("----------------开始下载 id="+videoId1);
|
||||
String contentUri= "https://rr3---sn-tt1e7nlz.googlevideo.com/videoplayback?expire=1730203742&ei=_nsgZ4KrKsCW2_gP3vHpsQk&ip=146.19.167.8&id=o-AMLbkjliQ0-OoP2NcJ1EcdlaKQ7tyJP2QHMOIxrhiBKx&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&met=1730182142%2C&mh=HX&mm=31%2C29&mn=sn-tt1e7nlz%2Csn-vgqsrnzd&ms=au%2Crdu&mv=m&mvi=3&pl=24&rms=au%2Cau&gcr=us&initcwndbps=241250&svpuc=1&sabr=1&rqh=1&mt=1730181899&fvip=1&keepalive=yes&fexp=51312688%2C51326932&c=ANDROID&sparams=expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Cgcr%2Csvpuc%2Csabr%2Crqh&sig=AJfQdSswRgIhAOxvUuLE3tfOLtuF9OP0zmy8tl4HQvm-6BlDjOnkhyGZAiEAjjL2jOFMqrjDgHMtwkWaQb9CNXz6lNqi1ShWWzGjtjY%3D&lsparams=met%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Crms%2Cinitcwndbps&lsig=ACJ0pHgwRQIhAJ7XPfdAxtoFrNQ13TkFhqHiGYGaKaBfxC6gb9fbB369AiBfx8gshE7jEgx0wOHce2IVHrZ_4aQvYptrSh23tfZqqA%3D%3D";
|
||||
DownloadRequest downloadRequest = new DownloadRequest.Builder(videoId1, Uri.parse(contentUri))
|
||||
CommonUtils.LogMsg("----------------开始下载 id=" + videoId1);
|
||||
DownloadRequest downloadRequest = new DownloadRequest.Builder(videoId1, Uri.parse(curMediaItemInfo.getVideoUrl()))
|
||||
.setMimeType("video/mp4")
|
||||
.setData(data)
|
||||
.build();
|
||||
@ -632,22 +655,20 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private BoxDownloadSong getCurMediaItemInfo(){
|
||||
private BoxDownloadSong getCurMediaItemInfo() {
|
||||
MediaItem curMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
if(curMediaItem== null){
|
||||
if (curMediaItem == null) {
|
||||
return null;
|
||||
}
|
||||
MediaMetadata mediaMetadata = curMediaItem.mediaMetadata;
|
||||
if(mediaMetadata.title== null||mediaMetadata.artist== null||mediaMetadata.description==null
|
||||
||mediaMetadata.durationMs==null){
|
||||
if (mediaMetadata.title == null || mediaMetadata.artist == null || mediaMetadata.description == null
|
||||
|| mediaMetadata.durationMs == null || curMediaItem.localConfiguration == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -657,7 +678,8 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
boxDownloadSong.setSongName((String) mediaMetadata.title);
|
||||
boxDownloadSong.setSingerName((String) mediaMetadata.artist);
|
||||
boxDownloadSong.setDuration((String) mediaMetadata.description);
|
||||
boxDownloadSong.setDurationMs( mediaMetadata.durationMs);
|
||||
boxDownloadSong.setDurationMs(mediaMetadata.durationMs);
|
||||
boxDownloadSong.setVideoUrl(String.valueOf(curMediaItem.localConfiguration.uri));
|
||||
|
||||
return boxDownloadSong;
|
||||
}
|
||||
@ -675,14 +697,32 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
vb.contentLayout.setVisibility(View.GONE);
|
||||
|
||||
if (!initPlayList) {
|
||||
List<ResponsePlayListInfo> playList = mediaControllerManager.getPlayList();
|
||||
List<ResponsePlayListInfo> playList;
|
||||
if (mEnterType == MyValue.TYPE_ENTER_DOWNLOAD){
|
||||
playList = new ArrayList<>();
|
||||
for(BoxDownloadSong data:downloadSongList){
|
||||
ResponsePlayListInfo playListInfo = new ResponsePlayListInfo();
|
||||
playListInfo.setSongTitle(data.getSongName());
|
||||
playListInfo.setSingerName(data.getSingerName());
|
||||
playListInfo.setCovert(data.getCovert());
|
||||
playListInfo.setSmallCovert(data.getCovert());
|
||||
playListInfo.setVideoId(data.getVideoId());
|
||||
playListInfo.setDuration(data.getDuration());
|
||||
playListInfo.setDurationMs(data.getDurationMs());
|
||||
playList.add(playListInfo);
|
||||
}
|
||||
|
||||
}else {
|
||||
playList = mediaControllerManager.getPlayList();
|
||||
}
|
||||
adapterPlayList = new AdapterPlayList();
|
||||
vb.layoutPlayList.recyclerList.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication));
|
||||
adapterPlayList.setData(playList);
|
||||
// TODO: 2024/10/16
|
||||
// TODO: 2024/10/16 播放列表显示
|
||||
vb.layoutPlayList.recyclerList.setAdapter(adapterPlayList);
|
||||
vb.layoutPlayList.imPlay.setOnClickListener(this);
|
||||
initPlayList = true;
|
||||
|
||||
}
|
||||
updatePlayListUi();
|
||||
|
||||
@ -705,7 +745,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
private void updatePlayListUi() {
|
||||
CommonUtils.LogMsg("----------更新播放列表的显示");
|
||||
|
||||
MediaItem currentMediaItem = mediaControllerManager.getMediaController().getCurrentMediaItem();
|
||||
MediaItem currentMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
if (currentMediaItem != null) {
|
||||
if (adapterPlayList != null) {
|
||||
adapterPlayList.setCurVideId(currentMediaItem.mediaId);
|
||||
@ -735,7 +775,7 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
})
|
||||
.into(vb.layoutPlayList.topIm);
|
||||
}
|
||||
vb.layoutPlayList.imPlay.setSelected(mediaControllerManager.getMediaController().isPlaying());
|
||||
vb.layoutPlayList.imPlay.setSelected(mediaControllerManager.getIsPlaying());
|
||||
}
|
||||
|
||||
private void updatePlayListColor() {
|
||||
@ -783,7 +823,40 @@ public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements S
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private void addDownloadListener(){
|
||||
private void addDownloadListener() {
|
||||
MyDownloadService.addDownloadListener(vmApplication);
|
||||
vmApplication.downloadData.observe(this, new Observer<List<Download>>() {
|
||||
@Override
|
||||
public void onChanged(List<Download> downloads) {
|
||||
if (downloads == null || downloads.size() == 0) {
|
||||
return;
|
||||
}
|
||||
String id = downloads.get(downloads.size() - 1).request.id;
|
||||
|
||||
MediaItem curMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
if (curMediaItem != null) {
|
||||
String mediaId = mediaControllerManager.getCurMediaItem().mediaId;
|
||||
if (mediaId.equals(id)) {
|
||||
vb.downloadPb.setVisibility(View.GONE);
|
||||
vb.imDownload.setVisibility(View.VISIBLE);
|
||||
vb.imDownload.setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
CommonUtils.LogMsg("-------onChanged id=" + id);
|
||||
if (mEnterType == MyValue.TYPE_ENTER_DOWNLOAD) {
|
||||
//下载进入播放,这里进行重置播放列表并播放
|
||||
mediaControllerManager.resetPlayList();
|
||||
for (Download data : downloads) {
|
||||
BoxDownloadSong boxDownloadSong = CommonUtils.downloadToBean(data);
|
||||
downloadSongList.add(boxDownloadSong);
|
||||
MediaItem mediaItem = CommonUtils.downloadToMediaItem(data);
|
||||
mediaControllerManager.addMusicPlayList(mediaItem);
|
||||
}
|
||||
mediaControllerManager.playPositionMusic(mDefaultPlayStartIndex);
|
||||
mediaControllerManager.play();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -161,12 +161,4 @@ public class ResultListActivity extends BaseActivity<ActivityResultListBinding>
|
||||
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void onClickResultAlbum(ResponseResultListChild child, int index) {
|
||||
// Intent intent = new Intent(this, CategoryListActivity.class);
|
||||
//// intent.putExtra(MyValue.KEY_CATEGORY_LIST_TYPE, pageType);
|
||||
// intent.putExtra(MyValue.KEY_CATEGORY_LIST_SINGER_NAME, child.getSongName());
|
||||
// intent.putExtra(MyValue.KEY_CATEGORY_LIST_BROWSER_ID, child.getBrowserId());
|
||||
// startActivity(intent);
|
||||
// }
|
||||
}
|
||||
@ -37,15 +37,20 @@ public class VMApplication extends ViewModel {
|
||||
|
||||
|
||||
private MutableLiveData<Integer> _playStatus = new MutableLiveData<Integer>();
|
||||
public LiveData<Integer> playStatus = _playStatus;
|
||||
public LiveData<Integer> playStatus = _playStatus;
|
||||
|
||||
|
||||
private MutableLiveData<List<Download>> _downloadData = new MutableLiveData<>();
|
||||
public LiveData<List<Download>> downloadData = _downloadData;
|
||||
|
||||
|
||||
private MutableLiveData<Pair<Boolean,Download>> _downloadChange = new MutableLiveData<>();
|
||||
public LiveData<Pair<Boolean,Download>> downloadChange = _downloadChange;
|
||||
|
||||
|
||||
/**
|
||||
* 重置播放列表
|
||||
*
|
||||
* @param list
|
||||
*/
|
||||
public void reSetPlayList(List<ResponsePlayListInfo> list) {
|
||||
@ -58,16 +63,14 @@ public class VMApplication extends ViewModel {
|
||||
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
public void setDownloadData( List<Download> downloadList) {
|
||||
//
|
||||
// byte[] data = download.request.data;
|
||||
// String additionalData = new String(data, StandardCharsets.UTF_8);
|
||||
// Gson gson = new Gson();
|
||||
// BoxDownloadSong boxDownloadSong = gson.fromJson(additionalData, BoxDownloadSong.class);
|
||||
// String covert = boxDownloadSong.getCovert();
|
||||
// String count = String.valueOf(downloadCount);
|
||||
//
|
||||
// Pair<String, String> stringStringPair = new Pair(covert,count);
|
||||
public void setDownloadData(List<Download> downloadList) {
|
||||
|
||||
_downloadData.setValue(downloadList);
|
||||
}
|
||||
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
public void setDownloadChange(Pair<Boolean,Download> download) {
|
||||
_downloadChange.setValue(download);
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +78,6 @@ public class VMPlay extends ViewModel {
|
||||
return;
|
||||
}
|
||||
MyMediaControllerManager.getInstance().UpdateAudioUrl(responsePlayUrl,playListIndex);
|
||||
// MyMediaControllerManager.getInstance().addMusicToPlayList(responsePlayUrl,playListIndex);
|
||||
customerUrlInfo.setPlayUrl(responsePlayUrl);
|
||||
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import androidx.lifecycle.ViewModel;
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import com.hi.music.player.helper.ViewModelScope;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
||||
|
||||
|
||||
public abstract class BaseFragment<T extends ViewBinding> extends Fragment {
|
||||
@ -20,6 +21,7 @@ public abstract class BaseFragment<T extends ViewBinding> extends Fragment {
|
||||
protected T Vb;
|
||||
|
||||
protected AppCompatActivity mActivity;
|
||||
protected VMApplication vmApplication;
|
||||
public BaseFragment() {
|
||||
|
||||
}
|
||||
@ -32,6 +34,7 @@ public abstract class BaseFragment<T extends ViewBinding> extends Fragment {
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
Vb = getFragmentVb();
|
||||
vmApplication = getApplicationScopeViewModel(VMApplication.class);
|
||||
initView();
|
||||
return Vb.getRoot();
|
||||
}
|
||||
|
||||
@ -2,17 +2,24 @@ package com.hi.music.player.ui.fragmnt;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.RestrictionsManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.adapter.AdapterHome;
|
||||
import com.hi.music.player.api.HomeItemClickListener;
|
||||
import com.hi.music.player.api.OnHasUrlAction;
|
||||
import com.hi.music.player.api.RequestListener;
|
||||
import com.hi.music.player.databinding.FragmentHomeBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
@ -74,6 +81,25 @@ public class HomeFragment extends BaseFragment<FragmentHomeBinding> implements H
|
||||
requestCount--;
|
||||
return;
|
||||
}
|
||||
|
||||
Glide.with(requireContext())
|
||||
.asDrawable()
|
||||
.load(responseHome.getBackgroundUrl())
|
||||
.placeholder(R.drawable.placeholder)
|
||||
.error(R.drawable.placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
// Vb.linearLayout.setBackground(resource);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.preload();
|
||||
List<ResponseHomeChild> childList1 = responseHome.getChildList();
|
||||
if (childList1 == null) return;
|
||||
childList.addAll(childList1);
|
||||
|
||||
@ -35,7 +35,7 @@ public class ProfileFragment extends BaseFragment<FragmentProfileBinding> implem
|
||||
private int likeSongCount = 0;
|
||||
private int downloadSongCount = 0;
|
||||
|
||||
private VMApplication vmApplication;
|
||||
|
||||
|
||||
@Override
|
||||
protected FragmentProfileBinding getFragmentVb() {
|
||||
@ -46,7 +46,7 @@ public class ProfileFragment extends BaseFragment<FragmentProfileBinding> implem
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
protected void initView() {
|
||||
vmApplication = getApplicationScopeViewModel(VMApplication.class);
|
||||
|
||||
dataSubscription = ObjectBoxManager.setLikeDataListener(new LikeSongListener() {
|
||||
@Override
|
||||
public void onLikeSongChange(List<BoxLikeSong> data) {
|
||||
|
||||
23
app/src/main/res/drawable/bg_profile.xml
Normal file
23
app/src/main/res/drawable/bg_profile.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
|
||||
|
||||
<!-- 顶部的渐变色背景 -->
|
||||
<item >
|
||||
<shape>
|
||||
<gradient
|
||||
android:angle="270"
|
||||
android:endColor="@color/home_bg2"
|
||||
android:startColor="@color/home_bg1" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<!-- 底部的黑色背景 -->
|
||||
<item android:top="400dp"> <!-- 调整此值控制黑色区域的高度 -->
|
||||
<shape>
|
||||
<solid android:color="#000000" />
|
||||
<size android:height="400dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
@ -1,4 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:width="36dp"
|
||||
android:height="36dp"
|
||||
android:viewportWidth="36"
|
||||
@ -7,13 +8,14 @@
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M18,18m-17.5,0a17.5,17.5 0,1 1,35 0a17.5,17.5 0,1 1,-35 0"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#80F988"/>
|
||||
android:strokeColor="#55B15B"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M4,4h28v28h-28z"/>
|
||||
android:pathData="M4,4h28v28h-28z"
|
||||
tools:ignore="VectorRaster" />
|
||||
<path
|
||||
android:pathData="M18,25.875C18.478,25.875 18.875,25.478 18.875,25V21.499C18.875,21.021 18.478,20.624 18,20.624C17.522,20.624 17.125,21.021 17.125,21.499V25C17.125,25.478 17.522,25.875 18,25.875ZM8.41,11.966C7.243,12.876 6.322,14.743 6.322,16.213V24.264C6.322,27.24 8.737,29.667 11.712,29.667H24.288C27.263,29.667 29.678,27.251 29.678,24.276V16.365C29.678,14.79 28.663,12.853 27.38,11.955L20.66,7.252C18.828,5.969 16.017,6.039 14.255,7.404L8.41,11.966Z"
|
||||
android:fillColor="#80F988"
|
||||
android:fillColor="#55B15B"
|
||||
android:fillType="evenOdd"/>
|
||||
</group>
|
||||
</vector>
|
||||
|
||||
15
app/src/main/res/drawable/ic_download_done.xml
Normal file
15
app/src/main/res/drawable/ic_download_done.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64.3dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="1028"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M510,1024a510,510 0,0 1,-360.6 -870.5,510 510,0 1,1 721.3,721.2A506.7,506.7 0,0 1,510 1024zM510.3,93.9a420.3,420.3 0,1 0,420.3 420.3,420.7 420.7,0 0,0 -420.3,-420.3z"
|
||||
android:fillColor="@color/panel_bg"/>
|
||||
<path
|
||||
android:pathData="M300.2,514.3l60,-60 180.1,180.1 -60,60z"
|
||||
android:fillColor="@color/panel_bg"/>
|
||||
<path
|
||||
android:pathData="M690.5,364.1l60,60L480.3,694.4l-60,-60z"
|
||||
android:fillColor="@color/panel_bg"/>
|
||||
</vector>
|
||||
@ -7,8 +7,8 @@
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M18,18m-17.5,0a17.5,17.5 0,1 1,35 0a17.5,17.5 0,1 1,-35 0"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#80F988"/>
|
||||
android:strokeColor="#55B15B"/>
|
||||
<path
|
||||
android:pathData="M22.445,22.593C24.09,21.548 25.351,19.998 26.039,18.176C26.728,16.354 26.806,14.357 26.262,12.486C25.719,10.615 24.582,8.972 23.024,7.802C21.466,6.632 19.571,6 17.623,6C15.675,6 13.779,6.632 12.221,7.802C10.663,8.972 9.527,10.615 8.983,12.486C8.44,14.357 8.518,16.354 9.206,18.176C9.894,19.998 11.156,21.548 12.8,22.593C11.519,23.199 10.419,24.131 9.612,25.297C8.804,26.462 8.317,27.819 8.2,29.232C8.195,29.43 8.269,29.622 8.405,29.766C8.541,29.91 8.728,29.994 8.926,30H26.362C26.46,29.998 26.557,29.976 26.647,29.936C26.738,29.896 26.819,29.839 26.887,29.768C26.955,29.696 27.008,29.612 27.044,29.521C27.079,29.429 27.096,29.331 27.094,29.232C26.973,27.814 26.479,26.453 25.663,25.287C24.847,24.121 23.737,23.191 22.445,22.593ZM21.749,19.132C21.231,19.715 20.601,20.189 19.896,20.525C19.192,20.861 18.427,21.052 17.647,21.087H17.443C15.913,20.956 14.492,20.243 13.472,19.096C13.405,19.019 13.354,18.929 13.322,18.833C13.29,18.736 13.277,18.633 13.285,18.532C13.294,18.43 13.322,18.331 13.369,18.24C13.416,18.15 13.48,18.069 13.559,18.004C13.637,17.939 13.728,17.89 13.826,17.86C13.923,17.831 14.026,17.821 14.127,17.832C14.229,17.842 14.327,17.873 14.417,17.922C14.506,17.971 14.585,18.038 14.648,18.118C15.403,18.949 16.439,19.471 17.557,19.581C18.631,19.635 19.704,19.114 20.748,18.076C20.889,17.942 21.077,17.869 21.271,17.872C21.466,17.875 21.651,17.953 21.789,18.091C21.926,18.228 22.005,18.414 22.007,18.608C22.01,18.802 21.937,18.99 21.803,19.132H21.749Z"
|
||||
android:fillColor="#80F988"/>
|
||||
android:fillColor="@color/panel_bg"/>
|
||||
</vector>
|
||||
|
||||
@ -1,36 +1,21 @@
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<layer-list
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- 渐变背景层 -->
|
||||
<item>
|
||||
<!-- 只设置顶部的圆角 -->
|
||||
|
||||
|
||||
<item>
|
||||
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:topLeftRadius="24dp" android:topRightRadius="24dp" />
|
||||
<solid android:color="@color/home_tab_color"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item >
|
||||
<shape android:shape="rectangle">
|
||||
<!-- 只设置顶部的圆角 -->
|
||||
<corners
|
||||
android:topLeftRadius="24dp"
|
||||
android:topRightRadius="24dp"
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp" />
|
||||
|
||||
<!-- 渐变效果 -->
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:endColor="#0080EF88"
|
||||
android:startColor="#8080EF88" />
|
||||
<corners android:topLeftRadius="24dp" android:topRightRadius="24dp" />
|
||||
<solid android:color="@color/white_15_color"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<!-- 半透明覆盖层 -->
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<!-- 同样只设置顶部的圆角 -->
|
||||
<corners
|
||||
android:topLeftRadius="24dp"
|
||||
android:topRightRadius="24dp"
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp" />
|
||||
|
||||
<!-- 半透明的颜色覆盖层 -->
|
||||
<solid android:color="#26FFFFFF" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
||||
@ -1,4 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:width="36dp"
|
||||
android:height="36dp"
|
||||
android:viewportWidth="36"
|
||||
@ -7,16 +8,17 @@
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M18,18m-17.5,0a17.5,17.5 0,1 1,35 0a17.5,17.5 0,1 1,-35 0"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#80F988"/>
|
||||
android:strokeColor="#55B15B"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M32,4l-28,0l-0,28l28,0z"/>
|
||||
android:pathData="M32,4l-28,0l-0,28l28,0z"
|
||||
tools:ignore="VectorRaster" />
|
||||
<path
|
||||
android:pathData="M17.5,6C11.149,6 6,11.149 6,17.5C6,23.851 11.149,29 17.5,29C23.851,29 29,23.851 29,17.5C29,11.149 23.851,6 17.5,6ZM15.354,10.861C15.819,10.795 16.176,10.395 16.176,9.912C16.176,9.383 15.747,8.954 15.218,8.954C15.16,8.954 15.104,8.959 15.049,8.968C11.923,9.472 9.472,11.923 8.968,15.049C8.959,15.104 8.954,15.16 8.954,15.218C8.954,15.747 9.383,16.176 9.912,16.176C10.395,16.176 10.795,15.819 10.861,15.354C11.233,13.044 13.044,11.233 15.354,10.861Z"
|
||||
android:fillColor="#80F988"
|
||||
android:fillColor="#55B15B"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M29.431,29.434C29.745,29.107 29.745,28.594 29.431,28.279L27.264,26.111C26.938,25.796 26.425,25.796 26.111,26.111C25.796,26.437 25.796,26.95 26.111,27.265L28.278,29.434C28.429,29.585 28.639,29.667 28.848,29.667C29.058,29.667 29.268,29.585 29.431,29.434Z"
|
||||
android:fillColor="#80F988"/>
|
||||
android:fillColor="#55B15B"/>
|
||||
</group>
|
||||
</vector>
|
||||
|
||||
6
app/src/main/res/drawable/selector_download.xml
Normal file
6
app/src/main/res/drawable/selector_download.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="true" android:drawable="@drawable/ic_download_done"/>
|
||||
<item android:state_selected="false" android:drawable="@drawable/ic_download"/>
|
||||
|
||||
</selector>
|
||||
@ -1,16 +1,23 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/home_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/home_background"
|
||||
android:background="@color/black"
|
||||
tools:context=".ui.activity.HomeActivity">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/view"
|
||||
android:background="@mipmap/bg_home" />
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/home_view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
|
||||
android:background="@color/color_transparent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/home_tab_layout"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@ -18,8 +25,9 @@
|
||||
android:id="@+id/home_tab_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="72dp"
|
||||
app:tabRippleColor="@android:color/transparent"
|
||||
app:tabIndicatorHeight="0dp"
|
||||
android:background="@drawable/rounded_rectangle_tab_layout"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:tabBackground="@color/color_transparent"
|
||||
app:tabIndicatorHeight="0dp"
|
||||
app:tabRippleColor="@android:color/transparent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black"
|
||||
android:background="@mipmap/bg_like"
|
||||
tools:context=".ui.activity.LikeSongActivity">
|
||||
|
||||
<ImageView
|
||||
|
||||
@ -29,19 +29,7 @@
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<!-- <ImageView-->
|
||||
<!-- android:id="@+id/im_covert"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="300dp"-->
|
||||
<!-- android:layout_marginStart="40dp"-->
|
||||
<!-- android:layout_marginTop="30dp"-->
|
||||
<!-- android:layout_marginEnd="40dp"-->
|
||||
<!-- android:scaleType="centerCrop"-->
|
||||
<!-- android:visibility="gone"-->
|
||||
<!-- android:src="@drawable/placeholder"-->
|
||||
<!-- app:layout_constraintLeft_toLeftOf="parent"-->
|
||||
<!-- app:layout_constraintRight_toRightOf="parent"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@id/im_back" />-->
|
||||
|
||||
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
@ -66,6 +54,17 @@
|
||||
app:show_buffering="when_playing"
|
||||
app:show_shuffle_button="false"
|
||||
app:use_controller="false" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/im_covert"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/im_back" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
|
||||
@ -89,44 +88,6 @@
|
||||
app:layout_constraintLeft_toLeftOf="@id/card_playerView"
|
||||
app:layout_constraintRight_toRightOf="@id/card_playerView"
|
||||
app:layout_constraintTop_toTopOf="@id/card_playerView" />
|
||||
<!-- <LinearLayout-->
|
||||
<!-- android:id="@+id/linear_retry"-->
|
||||
<!-- android:layout_width="210dp"-->
|
||||
<!-- android:layout_height="120dp"-->
|
||||
<!-- android:background="@drawable/bg_retry"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:orientation="vertical"-->
|
||||
<!-- android:visibility="gone"-->
|
||||
<!-- app:layout_constraintBottom_toBottomOf="@id/card_playerView"-->
|
||||
<!-- app:layout_constraintLeft_toLeftOf="@id/card_playerView"-->
|
||||
<!-- app:layout_constraintRight_toRightOf="@id/card_playerView"-->
|
||||
<!-- app:layout_constraintTop_toTopOf="@id/card_playerView">-->
|
||||
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/tv_error_msg"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:text="@string/An_error_occurred"-->
|
||||
<!-- android:textColor="@color/white"-->
|
||||
<!-- android:textSize="18sp" />-->
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/tv_retry"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginTop="15dp"-->
|
||||
<!-- android:background="@drawable/bg_retry_btn"-->
|
||||
<!-- android:paddingStart="15dp"-->
|
||||
<!-- android:paddingTop="8dp"-->
|
||||
<!-- android:paddingEnd="15dp"-->
|
||||
<!-- android:paddingBottom="8dp"-->
|
||||
<!-- android:text="@string/retry"-->
|
||||
<!-- android:textColor="@color/white"-->
|
||||
<!-- android:textSize="17sp" />-->
|
||||
|
||||
<!-- </LinearLayout>-->
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_song_name"
|
||||
@ -199,7 +160,7 @@
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/ic_download" />
|
||||
android:src="@drawable/selector_download" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/download_pb"
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/linearLayout"
|
||||
android:background="@color/color_transparent"
|
||||
tools:context=".ui.fragmnt.HomeFragment">
|
||||
|
||||
<TextView
|
||||
|
||||
@ -4,9 +4,14 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black"
|
||||
android:id="@+id/layout"
|
||||
tools:context=".ui.fragmnt.ProfileFragment">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- 第一行: 左边文字,右边控件 -->
|
||||
<TextView
|
||||
android:id="@+id/titleText"
|
||||
|
||||
@ -2,8 +2,9 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_height="60dp">
|
||||
android:background="@color/black">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card"
|
||||
@ -33,34 +34,49 @@
|
||||
app:layout_constraintTop_toTopOf="@id/card">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/like_song"
|
||||
android:id="@+id/tv_title"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_singer_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/like_song"
|
||||
android:id="@+id/tv_singer_name"
|
||||
android:textColor="@color/white_60_color"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="35dp"
|
||||
android:layout_height="30dp"
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:id="@+id/im_download"
|
||||
android:src="@drawable/ic_download"
|
||||
android:padding="10dp"
|
||||
android:id="@+id/layout_download"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/im_download"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/selector_download" />
|
||||
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/download_pb"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:indeterminateTint="@color/panel_bg"
|
||||
android:progressBackgroundTint="@color/panel_bg"
|
||||
android:progressTint="@color/panel_bg"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
BIN
app/src/main/res/mipmap-xxxhdpi/bg_home.png
Normal file
BIN
app/src/main/res/mipmap-xxxhdpi/bg_home.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 385 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/bg_library.png
Normal file
BIN
app/src/main/res/mipmap-xxxhdpi/bg_library.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 85 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/bg_like.png
Normal file
BIN
app/src/main/res/mipmap-xxxhdpi/bg_like.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/bg_profile.png
Normal file
BIN
app/src/main/res/mipmap-xxxhdpi/bg_profile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 189 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/tab_bg.png
Normal file
BIN
app/src/main/res/mipmap-xxxhdpi/tab_bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
@ -14,7 +14,7 @@
|
||||
<color name="default_play_list_color">#1A1A1A</color>
|
||||
<color name="cur_play_music">#4DFFFFFF</color>
|
||||
<color name="dark_music">#FF424242</color>
|
||||
<color name="panel_bg">#80F988</color>
|
||||
<color name="panel_bg">#55B15B</color>
|
||||
<color name="retry_bg">#E03D3D3F</color>
|
||||
<color name="library_color">#242529</color>
|
||||
|
||||
@ -22,4 +22,9 @@
|
||||
<color name="retry_layout">#000000</color>
|
||||
<color name="test">#2D9C31</color>
|
||||
<color name="best_result_bg">#282A2C</color>
|
||||
|
||||
<color name="home_bg1">#2EB06F</color>
|
||||
<color name="home_bg2">#B9D1A6</color>
|
||||
<color name="white_15_color">#26FFFFFF</color>
|
||||
<color name="home_tab_color">#339ED3A2</color>
|
||||
</resources>
|
||||
@ -38,4 +38,5 @@
|
||||
<string name="download_song">Offline %d</string>
|
||||
<string name="text_like_song">Favorite Songs</string>
|
||||
<string name="text_offline_song">Offline Songs</string>
|
||||
<string name="text_has_downloaded">It\'s already downloaded</string>
|
||||
</resources>
|
||||
Loading…
Reference in New Issue
Block a user