diff --git a/app/objectbox-models/default.json b/app/objectbox-models/default.json index 6018d3a..38ec0a8 100644 --- a/app/objectbox-models/default.json +++ b/app/objectbox-models/default.json @@ -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 } \ No newline at end of file diff --git a/app/src/main/java/com/hi/music/player/MusicApplication.java b/app/src/main/java/com/hi/music/player/MusicApplication.java index 3bab6dc..6aabe15 100644 --- a/app/src/main/java/com/hi/music/player/MusicApplication.java +++ b/app/src/main/java/com/hi/music/player/MusicApplication.java @@ -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) { diff --git a/app/src/main/java/com/hi/music/player/adapter/AdapterDownloadSong.java b/app/src/main/java/com/hi/music/player/adapter/AdapterDownloadSong.java index d03b501..2a8f413 100644 --- a/app/src/main/java/com/hi/music/player/adapter/AdapterDownloadSong.java +++ b/app/src/main/java/com/hi/music/player/adapter/AdapterDownloadSong.java @@ -38,7 +38,7 @@ public class AdapterDownloadSong extends BaseAdapter { + private VMApplication vmApplication; + + private List> 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 itemHolder = (VHolder) holder; ItemLikeSongBinding vb = itemHolder.getVb(); BoxLikeSong boxLikeSong = data.get(position); + String videoId = boxLikeSong.getVideoId(); + for(Pair 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() { + + @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() { -// -// @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; diff --git a/app/src/main/java/com/hi/music/player/media3/MyCacheManager.java b/app/src/main/java/com/hi/music/player/media3/MyDownloadCacheManager.java similarity index 93% rename from app/src/main/java/com/hi/music/player/media3/MyCacheManager.java rename to app/src/main/java/com/hi/music/player/media3/MyDownloadCacheManager.java index 5eeadce..4f3b0e6 100644 --- a/app/src/main/java/com/hi/music/player/media3/MyCacheManager.java +++ b/app/src/main/java/com/hi/music/player/media3/MyDownloadCacheManager.java @@ -12,7 +12,10 @@ import com.hi.music.player.MusicApplication; import java.io.File; -public class MyCacheManager { +/** + * 下载缓存 + */ +public class MyDownloadCacheManager { private static SimpleCache downloadCache; diff --git a/app/src/main/java/com/hi/music/player/media3/MyDownloadService.java b/app/src/main/java/com/hi/music/player/media3/MyDownloadService.java index accba57..263a1ab 100644 --- a/app/src/main/java/com/hi/music/player/media3/MyDownloadService.java +++ b/app/src/main/java/com/hi/music/player/media3/MyDownloadService.java @@ -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(); } diff --git a/app/src/main/java/com/hi/music/player/media3/MyMediaControllerManager.java b/app/src/main/java/com/hi/music/player/media3/MyMediaControllerManager.java index 8626f2b..aaf5fcf 100644 --- a/app/src/main/java/com/hi/music/player/media3/MyMediaControllerManager.java +++ b/app/src/main/java/com/hi/music/player/media3/MyMediaControllerManager.java @@ -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 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 listInfo) { playList = listInfo; - List 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(); } diff --git a/app/src/main/java/com/hi/music/player/media3/MyPlayCacheManager.java b/app/src/main/java/com/hi/music/player/media3/MyPlayCacheManager.java new file mode 100644 index 0000000..c5b9a1e --- /dev/null +++ b/app/src/main/java/com/hi/music/player/media3/MyPlayCacheManager.java @@ -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; + } +} diff --git a/app/src/main/java/com/hi/music/player/media3/PlaybackService.java b/app/src/main/java/com/hi/music/player/media3/PlaybackService.java index 78eeae1..9ba9aa3 100644 --- a/app/src/main/java/com/hi/music/player/media3/PlaybackService.java +++ b/app/src/main/java/com/hi/music/player/media3/PlaybackService.java @@ -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> onAddMediaItems(MediaSession mediaSession, MediaSession.ControllerInfo controller, List 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) { diff --git a/app/src/main/java/com/hi/music/player/network/JsonHelper.java b/app/src/main/java/com/hi/music/player/network/JsonHelper.java index 4b4870f..d9c30a2 100644 --- a/app/src/main/java/com/hi/music/player/network/JsonHelper.java +++ b/app/src/main/java/com/hi/music/player/network/JsonHelper.java @@ -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") diff --git a/app/src/main/java/com/hi/music/player/ui/activity/BaseActivity.java b/app/src/main/java/com/hi/music/player/ui/activity/BaseActivity.java index 2b245b5..842b412 100644 --- a/app/src/main/java/com/hi/music/player/ui/activity/BaseActivity.java +++ b/app/src/main/java/com/hi/music/player/ui/activity/BaseActivity.java @@ -153,7 +153,7 @@ public abstract class BaseActivity 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; diff --git a/app/src/main/java/com/hi/music/player/ui/activity/HomeActivity.java b/app/src/main/java/com/hi/music/player/ui/activity/HomeActivity.java index 197025e..a8822e6 100644 --- a/app/src/main/java/com/hi/music/player/ui/activity/HomeActivity.java +++ b/app/src/main/java/com/hi/music/player/ui/activity/HomeActivity.java @@ -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 { @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 { } } - - private void updateTabIcon(TabLayout.Tab tab, boolean isSelected) { HomeTabCustomBinding tabBinding = HomeTabCustomBinding.bind(tab.getCustomView()); int position = tab.getPosition(); diff --git a/app/src/main/java/com/hi/music/player/ui/activity/LikeSongActivity.java b/app/src/main/java/com/hi/music/player/ui/activity/LikeSongActivity.java index e438af7..4b594f3 100644 --- a/app/src/main/java/com/hi/music/player/ui/activity/LikeSongActivity.java +++ b/app/src/main/java/com/hi/music/player/ui/activity/LikeSongActivity.java @@ -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 impl private List boxLikeSongs; private int mType; + + private List> downloadList = new ArrayList<>(); + @Override protected ActivityLikeSongBinding getViewBinding() { return ActivityLikeSongBinding.inflate(getLayoutInflater()); @@ -41,16 +45,33 @@ public class LikeSongActivity extends BaseActivity 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>() { + @Override + public void onChanged(Pair booleanDownloadPair) { + Boolean first = booleanDownloadPair.first; + Download downloads = booleanDownloadPair.second; + + String id = downloads.request.id; + for (Pair 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 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 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 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 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 integerStringPair = new Pair<>(index, videoId); + downloadList.add(integerStringPair); } } \ No newline at end of file diff --git a/app/src/main/java/com/hi/music/player/ui/activity/PlayActivity.java b/app/src/main/java/com/hi/music/player/ui/activity/PlayActivity.java index 8694c67..3065d4e 100644 --- a/app/src/main/java/com/hi/music/player/ui/activity/PlayActivity.java +++ b/app/src/main/java/com/hi/music/player/ui/activity/PlayActivity.java @@ -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 implements SeekBar.OnSeekBarChangeListener { @@ -106,6 +112,8 @@ public class PlayActivity extends BaseActivity implements S //0 不循环、1 列表循环、2 单曲循环、 private int currentMode = 0; + private List downloadSongList = new ArrayList<>(); + @Override protected ActivityPlayBinding getViewBinding() { return ActivityPlayBinding.inflate(getLayoutInflater()); @@ -113,16 +121,13 @@ public class PlayActivity extends BaseActivity 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 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>() { @Override @@ -185,11 +196,18 @@ public class PlayActivity extends BaseActivity 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() { @Override public void onChanged(CustomerUrlInfo customerUrlInfo) { @@ -205,10 +223,9 @@ public class PlayActivity extends BaseActivity 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 implements S } + /** + * 更新播放列表 + */ private void updateMediaPlayList() { vmApplication.playList.observe(this, new Observer>() { @Override @@ -233,7 +253,6 @@ public class PlayActivity extends BaseActivity implements S updateErrorLayout(null, false); setPlayListAndGetUrl(playList, videoId, mDefaultPlayStartIndex); } - } }); } @@ -255,10 +274,26 @@ public class PlayActivity extends BaseActivity implements S * @param id * @param index */ + @OptIn(markerClass = UnstableApi.class) private void setPlayListAndGetUrl(List 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 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 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 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() { @@ -434,8 +475,7 @@ public class PlayActivity extends BaseActivity implements S @OptIn(markerClass = UnstableApi.class) @Override public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target 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 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 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 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 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 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 implements S vb.contentLayout.setVisibility(View.GONE); if (!initPlayList) { - List playList = mediaControllerManager.getPlayList(); + List 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 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 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 implements S } @OptIn(markerClass = UnstableApi.class) - private void addDownloadListener(){ + private void addDownloadListener() { MyDownloadService.addDownloadListener(vmApplication); + vmApplication.downloadData.observe(this, new Observer>() { + @Override + public void onChanged(List 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(); + } + } + }); } } \ No newline at end of file diff --git a/app/src/main/java/com/hi/music/player/ui/activity/ResultListActivity.java b/app/src/main/java/com/hi/music/player/ui/activity/ResultListActivity.java index 64d6fb6..d4aa873 100644 --- a/app/src/main/java/com/hi/music/player/ui/activity/ResultListActivity.java +++ b/app/src/main/java/com/hi/music/player/ui/activity/ResultListActivity.java @@ -161,12 +161,4 @@ public class ResultListActivity extends BaseActivity } -// @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); -// } } \ No newline at end of file diff --git a/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMApplication.java b/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMApplication.java index ee17cf5..0fff645 100644 --- a/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMApplication.java +++ b/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMApplication.java @@ -37,15 +37,20 @@ public class VMApplication extends ViewModel { private MutableLiveData _playStatus = new MutableLiveData(); - public LiveData playStatus = _playStatus; + public LiveData playStatus = _playStatus; private MutableLiveData> _downloadData = new MutableLiveData<>(); public LiveData> downloadData = _downloadData; + private MutableLiveData> _downloadChange = new MutableLiveData<>(); + public LiveData> downloadChange = _downloadChange; + + /** * 重置播放列表 + * * @param list */ public void reSetPlayList(List list) { @@ -58,16 +63,14 @@ public class VMApplication extends ViewModel { @OptIn(markerClass = UnstableApi.class) - public void setDownloadData( List 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 stringStringPair = new Pair(covert,count); + public void setDownloadData(List downloadList) { + _downloadData.setValue(downloadList); } + + + @OptIn(markerClass = UnstableApi.class) + public void setDownloadChange(Pair download) { + _downloadChange.setValue(download); + } } diff --git a/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMPlay.java b/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMPlay.java index 29fddc4..abd777b 100644 --- a/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMPlay.java +++ b/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/VMPlay.java @@ -78,7 +78,6 @@ public class VMPlay extends ViewModel { return; } MyMediaControllerManager.getInstance().UpdateAudioUrl(responsePlayUrl,playListIndex); -// MyMediaControllerManager.getInstance().addMusicToPlayList(responsePlayUrl,playListIndex); customerUrlInfo.setPlayUrl(responsePlayUrl); } diff --git a/app/src/main/java/com/hi/music/player/ui/fragmnt/BaseFragment.java b/app/src/main/java/com/hi/music/player/ui/fragmnt/BaseFragment.java index 5f2874f..496ca3f 100644 --- a/app/src/main/java/com/hi/music/player/ui/fragmnt/BaseFragment.java +++ b/app/src/main/java/com/hi/music/player/ui/fragmnt/BaseFragment.java @@ -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 extends Fragment { @@ -20,6 +21,7 @@ public abstract class BaseFragment extends Fragment { protected T Vb; protected AppCompatActivity mActivity; + protected VMApplication vmApplication; public BaseFragment() { } @@ -32,6 +34,7 @@ public abstract class BaseFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Vb = getFragmentVb(); + vmApplication = getApplicationScopeViewModel(VMApplication.class); initView(); return Vb.getRoot(); } diff --git a/app/src/main/java/com/hi/music/player/ui/fragmnt/HomeFragment.java b/app/src/main/java/com/hi/music/player/ui/fragmnt/HomeFragment.java index 02d3d89..b40f95f 100644 --- a/app/src/main/java/com/hi/music/player/ui/fragmnt/HomeFragment.java +++ b/app/src/main/java/com/hi/music/player/ui/fragmnt/HomeFragment.java @@ -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 implements H requestCount--; return; } + + Glide.with(requireContext()) + .asDrawable() + .load(responseHome.getBackgroundUrl()) + .placeholder(R.drawable.placeholder) + .error(R.drawable.placeholder) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target target, boolean isFirstResource) { + return false; + } + + @Override + public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target target, @NonNull DataSource dataSource, boolean isFirstResource) { +// Vb.linearLayout.setBackground(resource); + return false; + } + }) + .preload(); List childList1 = responseHome.getChildList(); if (childList1 == null) return; childList.addAll(childList1); diff --git a/app/src/main/java/com/hi/music/player/ui/fragmnt/ProfileFragment.java b/app/src/main/java/com/hi/music/player/ui/fragmnt/ProfileFragment.java index 25c2354..e9a1dc1 100644 --- a/app/src/main/java/com/hi/music/player/ui/fragmnt/ProfileFragment.java +++ b/app/src/main/java/com/hi/music/player/ui/fragmnt/ProfileFragment.java @@ -35,7 +35,7 @@ public class ProfileFragment extends BaseFragment 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 implem @OptIn(markerClass = UnstableApi.class) @Override protected void initView() { - vmApplication = getApplicationScopeViewModel(VMApplication.class); + dataSubscription = ObjectBoxManager.setLikeDataListener(new LikeSongListener() { @Override public void onLikeSongChange(List data) { diff --git a/app/src/main/res/drawable/bg_profile.xml b/app/src/main/res/drawable/bg_profile.xml new file mode 100644 index 0000000..872beec --- /dev/null +++ b/app/src/main/res/drawable/bg_profile.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/home_select.xml b/app/src/main/res/drawable/home_select.xml index ea2f40c..0d6b237 100644 --- a/app/src/main/res/drawable/home_select.xml +++ b/app/src/main/res/drawable/home_select.xml @@ -1,4 +1,5 @@ + android:strokeColor="#55B15B"/> + android:pathData="M4,4h28v28h-28z" + tools:ignore="VectorRaster" /> diff --git a/app/src/main/res/drawable/ic_download_done.xml b/app/src/main/res/drawable/ic_download_done.xml new file mode 100644 index 0000000..ca73dba --- /dev/null +++ b/app/src/main/res/drawable/ic_download_done.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/profile_select.xml b/app/src/main/res/drawable/profile_select.xml index bb4bdb1..957684f 100644 --- a/app/src/main/res/drawable/profile_select.xml +++ b/app/src/main/res/drawable/profile_select.xml @@ -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"/> + android:fillColor="@color/panel_bg"/> diff --git a/app/src/main/res/drawable/rounded_rectangle_tab_layout.xml b/app/src/main/res/drawable/rounded_rectangle_tab_layout.xml index 45e448d..489a08f 100644 --- a/app/src/main/res/drawable/rounded_rectangle_tab_layout.xml +++ b/app/src/main/res/drawable/rounded_rectangle_tab_layout.xml @@ -1,36 +1,21 @@ - + - - + + + + + + + + + + + + - - - - - + + - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/search_select.xml b/app/src/main/res/drawable/search_select.xml index 10747da..74567d9 100644 --- a/app/src/main/res/drawable/search_select.xml +++ b/app/src/main/res/drawable/search_select.xml @@ -1,4 +1,5 @@ + android:strokeColor="#55B15B"/> + android:pathData="M32,4l-28,0l-0,28l28,0z" + tools:ignore="VectorRaster" /> + android:fillColor="#55B15B"/> diff --git a/app/src/main/res/drawable/selector_download.xml b/app/src/main/res/drawable/selector_download.xml new file mode 100644 index 0000000..a50226c --- /dev/null +++ b/app/src/main/res/drawable/selector_download.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index 0465ce4..568335f 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -1,16 +1,23 @@ + + @@ -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" /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_like_song.xml b/app/src/main/res/layout/activity_like_song.xml index 1ca08dd..fc7d440 100644 --- a/app/src/main/res/layout/activity_like_song.xml +++ b/app/src/main/res/layout/activity_like_song.xml @@ -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"> - - - - - - - - - - - - - + + + @@ -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" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:src="@drawable/selector_download" /> + + + + + + android:background="@color/black"> - + app:layout_constraintTop_toTopOf="parent"> + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-xxxhdpi/bg_home.png b/app/src/main/res/mipmap-xxxhdpi/bg_home.png new file mode 100644 index 0000000..7ee12e1 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/bg_home.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/bg_library.png b/app/src/main/res/mipmap-xxxhdpi/bg_library.png new file mode 100644 index 0000000..d2ab49f Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/bg_library.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/bg_like.png b/app/src/main/res/mipmap-xxxhdpi/bg_like.png new file mode 100644 index 0000000..f3d5357 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/bg_like.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/bg_profile.png b/app/src/main/res/mipmap-xxxhdpi/bg_profile.png new file mode 100644 index 0000000..fb6f5cf Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/bg_profile.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/tab_bg.png b/app/src/main/res/mipmap-xxxhdpi/tab_bg.png new file mode 100644 index 0000000..4098ffa Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/tab_bg.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 839cf76..134ff9d 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -14,7 +14,7 @@ #1A1A1A #4DFFFFFF #FF424242 - #80F988 + #55B15B #E03D3D3F #242529 @@ -22,4 +22,9 @@ #000000 #2D9C31 #282A2C + + #2EB06F + #B9D1A6 + #26FFFFFF + #339ED3A2 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6d0fd6b..cc51459 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -38,4 +38,5 @@ Offline %d Favorite Songs Offline Songs + It\'s already downloaded \ No newline at end of file