Revert "和并A到main"
This reverts commit238ddf48fe, reversing changes made tof1cd9ec8ca.
This commit is contained in:
parent
238ddf48fe
commit
9d7a136173
@ -1,57 +0,0 @@
|
|||||||
package com.hi.music.player;
|
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
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 com.hi.music.player.api.MediaControllerStatusListener;
|
|
||||||
import com.hi.music.player.firebase.RemoteConfigJava;
|
|
||||||
import com.hi.music.player.firebase.Sp;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.media3.MyDownloadService;
|
|
||||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
|
||||||
import com.hi.music.player.objectbox.ObjectBoxManager;
|
|
||||||
|
|
||||||
public class MusicApplication extends Application {
|
|
||||||
|
|
||||||
public static Context myApplication;
|
|
||||||
|
|
||||||
public static String visitorData;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void setVisitorData(String visitorData) {
|
|
||||||
MusicApplication.visitorData = visitorData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getVisitorData() {
|
|
||||||
return visitorData;
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
myApplication = this;
|
|
||||||
Sp.init(this);
|
|
||||||
RemoteConfigJava.getInstance().init(this);
|
|
||||||
ObjectBoxManager.init(this);
|
|
||||||
|
|
||||||
StandaloneDatabaseProvider databaseProvider = new StandaloneDatabaseProvider(this);
|
|
||||||
MyDownloadService.init(this,databaseProvider);
|
|
||||||
MyMediaControllerManager.getInstance().init(new MediaControllerStatusListener() {
|
|
||||||
@Override
|
|
||||||
public void onMediaControllerComplete(boolean isOk) {
|
|
||||||
CommonUtils.LogMsg("=-----mediaController+" + isOk);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
package com.hi.music.player.adapter;
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
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.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.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.databinding.ItemCategoryBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.helper.MyValue;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseCategory;
|
|
||||||
|
|
||||||
public class AdapterCategory extends BaseAdapter<ResponseCategory, ItemCategoryBinding>{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ItemCategoryBinding getViewBinding(ViewGroup parent) {
|
|
||||||
return ItemCategoryBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
|
||||||
|
|
||||||
int itemViewType = getItemViewType(position);
|
|
||||||
if (itemViewType == TYPE_ITEM) {
|
|
||||||
VHolder<ItemCategoryBinding> itemHolder = (VHolder<ItemCategoryBinding>) holder;
|
|
||||||
ItemCategoryBinding vb = itemHolder.getVb();
|
|
||||||
ResponseCategory responseCategory = data.get(position);
|
|
||||||
String pageType = responseCategory.getPageType();
|
|
||||||
Glide.with(MusicApplication.myApplication)
|
|
||||||
.asDrawable()
|
|
||||||
.load(responseCategory.getCovert())
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.into(vb.header);
|
|
||||||
vb.tvTitle.setText(responseCategory.getTwoTitle());
|
|
||||||
vb.tvSubtitle.setText(responseCategory.getTwoSubtitle());
|
|
||||||
CommonUtils.LogMsg("title="+responseCategory.getTwoTitle()+"----------pageType="+pageType
|
|
||||||
+"---browserId="+responseCategory.getBrowseId()+"---videoId="+responseCategory.getVideoId()+"---playListId="+responseCategory.getPlayListId());
|
|
||||||
if(pageType == null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// if(pageType.equals(MyValue.PAGE_TYPE_MV)||pageType.equals(MyValue.PAGE_TYPE_MV_LIST)){
|
|
||||||
// ViewGroup.LayoutParams layoutParams = vb.header.getLayoutParams();
|
|
||||||
// layoutParams.width = CommonUtils.dpToPx(280);
|
|
||||||
// vb.header.setLayoutParams(layoutParams);
|
|
||||||
// vb.header.setBackgroundResource(R.drawable.bg_black_13);
|
|
||||||
//
|
|
||||||
// }else {
|
|
||||||
// ViewGroup.LayoutParams layoutParams = vb.header.getLayoutParams();
|
|
||||||
// layoutParams.width = CommonUtils.dpToPx(170);
|
|
||||||
// vb.header.setLayoutParams(layoutParams);
|
|
||||||
// vb.header.setBackground(null);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
vb.header.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (homeItemClickListener != null) {
|
|
||||||
homeItemClickListener.onClickItemCategory(responseCategory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,105 +0,0 @@
|
|||||||
package com.hi.music.player.adapter;
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.OptIn;
|
|
||||||
import androidx.media3.common.util.UnstableApi;
|
|
||||||
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.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.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.api.onImageColorListener;
|
|
||||||
import com.hi.music.player.databinding.ItemCategoryListBinding;
|
|
||||||
import com.hi.music.player.databinding.ItemSingerBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.helper.MyValue;
|
|
||||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseCategoryListChild;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
|
||||||
|
|
||||||
public class AdapterCategoryList extends BaseAdapter<ResponsePlayListInfo, ItemCategoryListBinding> {
|
|
||||||
|
|
||||||
|
|
||||||
private String mPageType;
|
|
||||||
|
|
||||||
public void setPageType(String mPageType) {
|
|
||||||
this.mPageType = mPageType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ItemCategoryListBinding getViewBinding(ViewGroup parent) {
|
|
||||||
return ItemCategoryListBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
|
||||||
VHolder<ItemCategoryListBinding> itemHolder = (VHolder<ItemCategoryListBinding>) holder;
|
|
||||||
ResponsePlayListInfo child = data.get(position);
|
|
||||||
|
|
||||||
ItemCategoryListBinding vb = itemHolder.getVb();
|
|
||||||
vb.tvSongName.setText(child.getSongTitle());
|
|
||||||
vb.tvDuration.setText(child.getDuration());
|
|
||||||
String singerName = child.getSingerName();
|
|
||||||
String describe = child.getDescribe();
|
|
||||||
|
|
||||||
switch (mPageType){
|
|
||||||
case MyValue.PAGE_TYPE_ALBUM:
|
|
||||||
vb.tvSingerName.setText(describe);
|
|
||||||
vb.imCard.setVisibility(View.GONE);
|
|
||||||
vb.tvPosition.setVisibility(View.VISIBLE);
|
|
||||||
vb.tvPosition.setText(String.valueOf(position+1));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vb.tvSingerName.setText(singerName);
|
|
||||||
|
|
||||||
vb.imCard.setVisibility(View.VISIBLE);
|
|
||||||
vb.tvPosition.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
Glide.with(MusicApplication.myApplication)
|
|
||||||
.asDrawable()
|
|
||||||
.load(child.getSmallCovert())
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into(vb.image);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
homeItemClickListener.onClickItemCategoryList(child, itemHolder.getAbsoluteAdapterPosition());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if(position == data.size() - 1){
|
|
||||||
vb.place.setVisibility(View.VISIBLE);
|
|
||||||
}else {
|
|
||||||
vb.place.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
package com.hi.music.player.adapter;
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.media3.exoplayer.offline.Download;
|
|
||||||
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.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.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.databinding.ItemLikeSongBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.javabean.BoxDownloadSong;
|
|
||||||
import com.hi.music.player.javabean.BoxLikeSong;
|
|
||||||
|
|
||||||
public class AdapterDownloadSong extends BaseAdapter<Download, ItemLikeSongBinding> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ItemLikeSongBinding getViewBinding(ViewGroup parent) {
|
|
||||||
return ItemLikeSongBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
|
||||||
VHolder<ItemLikeSongBinding> itemHolder = (VHolder<ItemLikeSongBinding>) holder;
|
|
||||||
ItemLikeSongBinding vb = itemHolder.getVb();
|
|
||||||
Download download = data.get(position);
|
|
||||||
BoxDownloadSong boxDownloadSong = CommonUtils.downloadToBean(download);
|
|
||||||
|
|
||||||
if (position == data.size()-1){
|
|
||||||
vb.place.setVisibility(View.VISIBLE);
|
|
||||||
}else {
|
|
||||||
vb.place.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
vb.layoutDownload.setVisibility(View.GONE);
|
|
||||||
Glide.with(MusicApplication.myApplication)
|
|
||||||
.asDrawable()
|
|
||||||
.load(boxDownloadSong.getCovert())
|
|
||||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into(vb.imCovert);
|
|
||||||
vb.tvTitle.setText(boxDownloadSong.getSongName());
|
|
||||||
vb.tvSingerName.setText(boxDownloadSong.getSingerName());
|
|
||||||
|
|
||||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if(homeItemClickListener!= null){
|
|
||||||
int absoluteAdapterPosition = itemHolder.getAbsoluteAdapterPosition();
|
|
||||||
homeItemClickListener.onClickDownloadSong(download,absoluteAdapterPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
package com.hi.music.player.adapter;
|
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.databinding.ItemFooterLoadingBinding;
|
|
||||||
import com.hi.music.player.databinding.ItemHomeBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseCategory;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseHomeChild;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class AdapterHome extends BaseAdapter<ResponseHomeChild, ItemHomeBinding> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ItemHomeBinding getViewBinding(ViewGroup parent) {
|
|
||||||
|
|
||||||
return ItemHomeBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
|
||||||
int itemViewType = getItemViewType(position);
|
|
||||||
if (itemViewType == TYPE_ITEM) {
|
|
||||||
VHolder<ItemHomeBinding> itemHolder = (VHolder<ItemHomeBinding>) holder;
|
|
||||||
ItemHomeBinding vb = itemHolder.getVb();
|
|
||||||
ResponseHomeChild responseHomeChild = data.get(position);
|
|
||||||
vb.headTitle.setText(responseHomeChild.getHeaderTitle());
|
|
||||||
|
|
||||||
List<ResponseSingle> singleList = responseHomeChild.getSingleList();
|
|
||||||
List<ResponseCategory> categoryList = responseHomeChild.getCategoryList();
|
|
||||||
CommonUtils.LogMsg("position="+position+"-----------headTitle-=" + responseHomeChild.getHeaderTitle()+"--singleList="+singleList+"---categoryList="+categoryList);
|
|
||||||
if (singleList != null && singleList.size() > 0) {
|
|
||||||
vb.recyclerSinger.setVisibility(View.VISIBLE);
|
|
||||||
AdapterSinger adapterSinger = new AdapterSinger();
|
|
||||||
adapterSinger.setHomeItemClickListener(homeItemClickListener);
|
|
||||||
adapterSinger.addData(singleList);
|
|
||||||
vb.recyclerSinger.setLayoutManager(new GridLayoutManager(MusicApplication.myApplication, 4, RecyclerView.HORIZONTAL, false));
|
|
||||||
vb.recyclerSinger.setAdapter(adapterSinger);
|
|
||||||
} else {
|
|
||||||
vb.recyclerSinger.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (categoryList != null && categoryList.size() > 0) {
|
|
||||||
vb.recyclerCategory.setVisibility(View.VISIBLE);
|
|
||||||
AdapterCategory adapterCategory = new AdapterCategory();
|
|
||||||
adapterCategory.setHomeItemClickListener(homeItemClickListener);
|
|
||||||
adapterCategory.addData(categoryList);
|
|
||||||
vb.recyclerCategory.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication, RecyclerView.HORIZONTAL, false));
|
|
||||||
vb.recyclerCategory.setAdapter(adapterCategory);
|
|
||||||
} else {
|
|
||||||
vb.recyclerCategory.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(position == data.size() - 1){
|
|
||||||
vb.place.setVisibility(View.VISIBLE);
|
|
||||||
}else {
|
|
||||||
vb.place.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
VHolder<ItemFooterLoadingBinding> footerHolder = (VHolder<ItemFooterLoadingBinding>) holder;
|
|
||||||
FrameLayout root = footerHolder.getVb().getRoot();
|
|
||||||
if (isLoadingAdded) {
|
|
||||||
root.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
root.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,215 +0,0 @@
|
|||||||
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;
|
|
||||||
import com.bumptech.glide.load.DataSource;
|
|
||||||
import com.bumptech.glide.load.engine.GlideException;
|
|
||||||
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();
|
|
||||||
|
|
||||||
if (position == data.size()-1){
|
|
||||||
vb.place.setVisibility(View.VISIBLE);
|
|
||||||
}else {
|
|
||||||
vb.place.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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())
|
|
||||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into(vb.imCovert);
|
|
||||||
vb.tvTitle.setText(boxLikeSong.getSongName());
|
|
||||||
vb.tvSingerName.setText(boxLikeSong.getSingerName());
|
|
||||||
|
|
||||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (homeItemClickListener != null) {
|
|
||||||
int absoluteAdapterPosition = itemHolder.getAbsoluteAdapterPosition();
|
|
||||||
homeItemClickListener.onClickLikeSong(boxLikeSong, absoluteAdapterPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
package com.hi.music.player.adapter;
|
|
||||||
|
|
||||||
import static androidx.media3.session.legacy.MediaControllerCompat.getMediaController;
|
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.media3.common.MediaItem;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
|
||||||
import com.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.api.MediaControllerListener;
|
|
||||||
import com.hi.music.player.databinding.ItemPlayListBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.helper.MyValue;
|
|
||||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
|
||||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
|
||||||
|
|
||||||
public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayListBinding> {
|
|
||||||
|
|
||||||
private String mCurVideId;
|
|
||||||
|
|
||||||
private String lastVideId;
|
|
||||||
|
|
||||||
// private int curMusicPos = 0;
|
|
||||||
private MyMediaControllerManager instance = MyMediaControllerManager.getInstance();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ItemPlayListBinding getViewBinding(ViewGroup parent) {
|
|
||||||
return ItemPlayListBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCurVideId(String curVideId) {
|
|
||||||
lastVideId = mCurVideId;
|
|
||||||
this.mCurVideId = curVideId;
|
|
||||||
for (int i = 0; i < data.size(); i++) {
|
|
||||||
ResponsePlayListInfo listInfo = data.get(i);
|
|
||||||
if (listInfo.getVideoId().equals(curVideId)) {
|
|
||||||
notifyItemChanged(i);
|
|
||||||
}
|
|
||||||
if (listInfo.getVideoId().equals(lastVideId)) {
|
|
||||||
notifyItemChanged(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void updateCurMusicAnimation() {
|
|
||||||
int curIndex = instance.getCurIndex();
|
|
||||||
CommonUtils.LogMsg("--curIndex=" + curIndex);
|
|
||||||
notifyItemChanged(curIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
|
||||||
ResponsePlayListInfo listInfo = data.get(position);
|
|
||||||
VHolder<ItemPlayListBinding> itemHolder = (VHolder<ItemPlayListBinding>) holder;
|
|
||||||
ItemPlayListBinding vb = itemHolder.getVb();
|
|
||||||
|
|
||||||
vb.songName.setText(listInfo.getSongTitle());
|
|
||||||
String singerName = listInfo.getSingerName();
|
|
||||||
String describe = listInfo.getDescribe();
|
|
||||||
if (singerName != null && !singerName.isEmpty()) {
|
|
||||||
vb.artistName.setText(singerName);
|
|
||||||
} else if (describe != null && !describe.isEmpty()) {
|
|
||||||
vb.artistName.setText(describe);
|
|
||||||
}
|
|
||||||
|
|
||||||
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))))
|
|
||||||
.load(covert)
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.into(vb.imCovert);
|
|
||||||
|
|
||||||
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.getIsPlaying()) {
|
|
||||||
vb.viewPlaying.startAnimating();
|
|
||||||
lastVideId = listInfo.getVideoId();
|
|
||||||
CommonUtils.LogMsg("-------playAnimation " + itemHolder.getAbsoluteAdapterPosition());
|
|
||||||
} else {
|
|
||||||
vb.viewPlaying.pauseAnimating();
|
|
||||||
CommonUtils.LogMsg("-------pauseAnimation " + itemHolder.getAbsoluteAdapterPosition());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
vb.viewPlaying.setVisibility(View.GONE);
|
|
||||||
vb.itemLayout.setBackgroundColor(CommonUtils.getMyColor(R.color.color_transparent));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
vb.itemLayout.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
CommonUtils.LogMsg("-------onClick curMusicPos=" + itemHolder.getAbsoluteAdapterPosition());
|
|
||||||
setCurVideId(listInfo.getVideoId());
|
|
||||||
instance.playPositionMusic(itemHolder.getAbsoluteAdapterPosition());
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
package com.hi.music.player.adapter;
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
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.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.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.databinding.ItemResultListAlbumBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseResultListChild;
|
|
||||||
|
|
||||||
public class AdapterResultListAlbum extends BaseAdapter<ResponseResultListChild, ItemResultListAlbumBinding>{
|
|
||||||
@Override
|
|
||||||
protected ItemResultListAlbumBinding getViewBinding(ViewGroup parent) {
|
|
||||||
return ItemResultListAlbumBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
|
||||||
ResponseResultListChild listChild = data.get(position);
|
|
||||||
|
|
||||||
|
|
||||||
VHolder<ItemResultListAlbumBinding> itemHolder = (VHolder<ItemResultListAlbumBinding>) holder;
|
|
||||||
ItemResultListAlbumBinding vb = itemHolder.getVb();
|
|
||||||
if(position == data.size()-1){
|
|
||||||
vb.view.setVisibility(View.VISIBLE);
|
|
||||||
}else {
|
|
||||||
vb.view.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
Glide.with(MusicApplication.myApplication)
|
|
||||||
.asDrawable()
|
|
||||||
.load(listChild.getThumbnail())
|
|
||||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into(vb.header);
|
|
||||||
vb.tvTitle.setText(listChild.getSongName());
|
|
||||||
vb.tvSubtitle.setText(listChild.getSubTitle());
|
|
||||||
vb.header.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if(homeItemClickListener != null){
|
|
||||||
int absoluteAdapterPosition = itemHolder.getAbsoluteAdapterPosition();
|
|
||||||
String videoId = listChild.getVideoId();
|
|
||||||
String browserId = listChild.getBrowserId();
|
|
||||||
homeItemClickListener.onClickResultSong(listChild,absoluteAdapterPosition);
|
|
||||||
// if(videoId == null||videoId.isEmpty()){
|
|
||||||
// homeItemClickListener.onClickResultAlbum(listChild,absoluteAdapterPosition);
|
|
||||||
// }else if(browserId!= null&&!browserId.isEmpty()){
|
|
||||||
// homeItemClickListener.onClickResultSong(listChild,absoluteAdapterPosition);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
CommonUtils.LogMsg("-------Album getBrowserId="+listChild.getBrowserId()+"---getPlayListId= "+listChild.getPlayListId()+"---getVideoId="+listChild.getVideoId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
package com.hi.music.player.adapter;
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
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.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.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
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> {
|
|
||||||
@Override
|
|
||||||
protected ItemResultListSongBinding getViewBinding(ViewGroup parent) {
|
|
||||||
return ItemResultListSongBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
|
||||||
ResponseResultListChild listChild = data.get(position);
|
|
||||||
|
|
||||||
VHolder<ItemResultListSongBinding> itemHolder = (VHolder<ItemResultListSongBinding>) holder;
|
|
||||||
ItemResultListSongBinding vb = itemHolder.getVb();
|
|
||||||
|
|
||||||
Glide.with(MusicApplication.myApplication)
|
|
||||||
.asDrawable()
|
|
||||||
.load(listChild.getThumbnail())
|
|
||||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into(vb.imCovert);
|
|
||||||
vb.tvSongName.setText(listChild.getSongName());
|
|
||||||
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) {
|
|
||||||
int absoluteAdapterPosition = itemHolder.getAbsoluteAdapterPosition();
|
|
||||||
String videoId = listChild.getVideoId();
|
|
||||||
String browserId = listChild.getBrowserId();
|
|
||||||
homeItemClickListener.onClickResultSong(listChild, absoluteAdapterPosition);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
CommonUtils.LogMsg("-------Song getBrowserId=" + listChild.getBrowserId() + "---getPlayListId= " + listChild.getPlayListId() + "---getVideoId=" + listChild.getVideoId());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
package com.hi.music.player.adapter;
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
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.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.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.databinding.ItemSearchBinding;
|
|
||||||
import com.hi.music.player.databinding.ItemSearchChildBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.javabean.response.ResponseSearch;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseSearchChild;
|
|
||||||
|
|
||||||
public class AdapterSearchChild extends BaseAdapter<ResponseSearchChild, ItemSearchChildBinding> {
|
|
||||||
@Override
|
|
||||||
protected ItemSearchChildBinding getViewBinding(ViewGroup parent) {
|
|
||||||
return ItemSearchChildBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
|
||||||
ResponseSearchChild responseSearchChild = data.get(position);
|
|
||||||
VHolder<ItemSearchChildBinding> itemHolder = (VHolder<ItemSearchChildBinding>) holder;
|
|
||||||
ItemSearchChildBinding vb = itemHolder.getVb();
|
|
||||||
|
|
||||||
|
|
||||||
Glide.with(MusicApplication.myApplication)
|
|
||||||
.asDrawable()
|
|
||||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(13))))
|
|
||||||
.load(responseSearchChild.getSongCovert())
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into(vb.imCovert);
|
|
||||||
|
|
||||||
vb.tvTitle.setText(responseSearchChild.getSongTitle());
|
|
||||||
vb.tvSubtitle.setText(responseSearchChild.getSongDescribe());
|
|
||||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (homeItemClickListener != null) {
|
|
||||||
homeItemClickListener.onClickSearchResult(responseSearchChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
package com.hi.music.player.adapter;
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
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.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.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.databinding.ItemSingerBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
|
||||||
|
|
||||||
public class AdapterSinger extends BaseAdapter<ResponseSingle, ItemSingerBinding> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ItemSingerBinding getViewBinding(ViewGroup parent) {
|
|
||||||
return ItemSingerBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
|
||||||
int itemViewType = getItemViewType(position);
|
|
||||||
if (itemViewType == TYPE_ITEM) {
|
|
||||||
VHolder<ItemSingerBinding> itemHolder = (VHolder<ItemSingerBinding>) holder;
|
|
||||||
ItemSingerBinding vb = itemHolder.getVb();
|
|
||||||
ResponseSingle responseSingle = data.get(position);
|
|
||||||
|
|
||||||
Glide.with(MusicApplication.myApplication)
|
|
||||||
.asDrawable()
|
|
||||||
.load(responseSingle.getSingerHead())
|
|
||||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into(vb.header);
|
|
||||||
vb.tvSingerName.setText(responseSingle.getSingerName());
|
|
||||||
vb.tvSongName.setText(responseSingle.getSongTitle());
|
|
||||||
// vb.tvDescribe.setText(responseSingle.getDescription());
|
|
||||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (homeItemClickListener != null) {
|
|
||||||
homeItemClickListener.onClickItemSinger(responseSingle);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,127 +0,0 @@
|
|||||||
package com.hi.music.player.dialog;
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.GradientDrawable;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.OptIn;
|
|
||||||
import androidx.media3.common.MediaItem;
|
|
||||||
import androidx.media3.common.util.UnstableApi;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.DataSource;
|
|
||||||
import com.bumptech.glide.load.engine.GlideException;
|
|
||||||
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.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.adapter.AdapterPlayList;
|
|
||||||
import com.hi.music.player.api.onImageColorListener;
|
|
||||||
import com.hi.music.player.databinding.DialogPlayListBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
|
||||||
import com.hi.music.player.media3.MyControllerView;
|
|
||||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class DialogPlayList extends BaseDialog<DialogPlayListBinding> {
|
|
||||||
private MyMediaControllerManager instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected DialogPlayListBinding getViewBinding(LayoutInflater inflater, ViewGroup container) {
|
|
||||||
return DialogPlayListBinding.inflate(inflater, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initView() {
|
|
||||||
|
|
||||||
instance = MyMediaControllerManager.getInstance();
|
|
||||||
initPlayListUi();
|
|
||||||
|
|
||||||
MediaItem currentMediaItem = instance.getCurMediaItem();
|
|
||||||
if (currentMediaItem != null) {
|
|
||||||
Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri;
|
|
||||||
vb.topSongName.setText(currentMediaItem.mediaMetadata.title);
|
|
||||||
vb.topSingerName.setText(currentMediaItem.mediaMetadata.artist);
|
|
||||||
|
|
||||||
Glide.with(MusicApplication.myApplication)
|
|
||||||
.asDrawable()
|
|
||||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10))))
|
|
||||||
.load(artworkUri)
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
CommonUtils.getDominantDarkColor1(resource, new onImageColorListener() {
|
|
||||||
@Override
|
|
||||||
public void onImageColor(int color) {
|
|
||||||
if (color == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int lighterColor = CommonUtils.adjustBrightness(color, 1.2f); // 比原始颜色亮 20%
|
|
||||||
int darkerColor = CommonUtils.adjustBrightness(color, 0.8f); // 比原始颜色暗 20%
|
|
||||||
// GradientDrawable gradientDrawable = new GradientDrawable(
|
|
||||||
// GradientDrawable.Orientation.TOP_BOTTOM,
|
|
||||||
// new int[]{lighterColor, darkerColor} // 浅到深渐变
|
|
||||||
// );
|
|
||||||
vb.topLayout.setBackgroundColor(darkerColor);
|
|
||||||
Drawable newDrawable = CommonUtils.getNewDrawable(lighterColor, 24f, 24f, 0, 0);
|
|
||||||
vb.listLayout.setBackground(newDrawable);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into(vb.topIm);
|
|
||||||
}
|
|
||||||
vb.imPlay.setSelected(instance.getIsPlaying());
|
|
||||||
|
|
||||||
vb.imPlay.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
vb.imPlay.setSelected(!vb.imPlay.isSelected());
|
|
||||||
if (vb.imPlay.isSelected()) {
|
|
||||||
instance.play();
|
|
||||||
} else {
|
|
||||||
instance.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFullScreen() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initPlayListUi() {
|
|
||||||
List<ResponsePlayListInfo> playList = instance.getPlayList();
|
|
||||||
AdapterPlayList adapterPlayList = new AdapterPlayList();
|
|
||||||
vb.recyclerList.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication));
|
|
||||||
adapterPlayList.addData(playList);
|
|
||||||
vb.recyclerList.setAdapter(adapterPlayList);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
package com.hi.music.player.javabean.requestbody.child;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
public class ContextBody {
|
|
||||||
|
|
||||||
private Client client = new Client();
|
|
||||||
|
|
||||||
private ThirdParty thirdParty = new ThirdParty();
|
|
||||||
|
|
||||||
|
|
||||||
// public ThirdParty getThirdParty() {
|
|
||||||
// return thirdParty;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public Client getClient() {
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClient(Client client) {
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static class ThirdParty{
|
|
||||||
//https://www.youtube.com/watch?v=UqyT8IEBkvY
|
|
||||||
private String embedUrl;
|
|
||||||
|
|
||||||
public void setEmbedUrl(String embedUrl) {
|
|
||||||
this.embedUrl = embedUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,199 +0,0 @@
|
|||||||
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;
|
|
||||||
import androidx.media3.common.util.UnstableApi;
|
|
||||||
import androidx.media3.database.StandaloneDatabaseProvider;
|
|
||||||
import androidx.media3.datasource.DefaultHttpDataSource;
|
|
||||||
import androidx.media3.datasource.cache.SimpleCache;
|
|
||||||
import androidx.media3.exoplayer.offline.Download;
|
|
||||||
import androidx.media3.exoplayer.offline.DownloadCursor;
|
|
||||||
import androidx.media3.exoplayer.offline.DownloadIndex;
|
|
||||||
import androidx.media3.exoplayer.offline.DownloadManager;
|
|
||||||
import androidx.media3.exoplayer.offline.DownloadNotificationHelper;
|
|
||||||
import androidx.media3.exoplayer.offline.DownloadService;
|
|
||||||
import androidx.media3.exoplayer.scheduler.Scheduler;
|
|
||||||
|
|
||||||
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.CustomerDownload;
|
|
||||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
import io.reactivex.Observable;
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.disposables.Disposable;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
|
||||||
|
|
||||||
|
|
||||||
@UnstableApi
|
|
||||||
public class MyDownloadService extends DownloadService {
|
|
||||||
private static final int FOREGROUND_NOTIFICATION_ID = 1;
|
|
||||||
private static final String CHANNEL_ID = "download_song_channel_id";
|
|
||||||
|
|
||||||
private static DownloadManager mDownloadManager;
|
|
||||||
|
|
||||||
private static SimpleCache downloadCache;
|
|
||||||
|
|
||||||
public MyDownloadService() {
|
|
||||||
super(FOREGROUND_NOTIFICATION_ID,
|
|
||||||
DEFAULT_FOREGROUND_NOTIFICATION_UPDATE_INTERVAL,
|
|
||||||
CHANNEL_ID, // 通知渠道 ID
|
|
||||||
R.string.app_name, // 通知渠道名称
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SimpleCache getDownloadCache() {
|
|
||||||
return downloadCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void init(Context context, StandaloneDatabaseProvider databaseProvider) {
|
|
||||||
if (mDownloadManager == null) {
|
|
||||||
downloadCache = MyDownloadCacheManager.getMyCache(databaseProvider);
|
|
||||||
DefaultHttpDataSource.Factory factory = new DefaultHttpDataSource.Factory();
|
|
||||||
Executor downloadExecutor = Runnable::run;
|
|
||||||
|
|
||||||
mDownloadManager = new DownloadManager(
|
|
||||||
context,
|
|
||||||
databaseProvider, // 数据库提供者
|
|
||||||
downloadCache,
|
|
||||||
factory, // 数据源工厂
|
|
||||||
downloadExecutor // 线程池
|
|
||||||
);
|
|
||||||
|
|
||||||
mDownloadManager.setMaxParallelDownloads(3); // 设置最大并行下载数
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static synchronized DownloadManager getMyDownloadManager() {
|
|
||||||
|
|
||||||
return mDownloadManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void addDownloadListener(VMApplication vmApplication) {
|
|
||||||
mDownloadManager.addListener(new DownloadManager.Listener() {
|
|
||||||
@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
|
|
||||||
public void onDownloadRemoved(DownloadManager downloadManager, Download download) {
|
|
||||||
String id = download.request.id;
|
|
||||||
CommonUtils.LogMsg("----------------onDownloadRemoved id=" + id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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(() -> {
|
|
||||||
// 第一部分操作:在IO线程
|
|
||||||
DownloadIndex downloadIndex = mDownloadManager.getDownloadIndex();
|
|
||||||
DownloadCursor downloads = downloadIndex.getDownloads(Download.STATE_COMPLETED);
|
|
||||||
|
|
||||||
return downloads;
|
|
||||||
})
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
// .observeOn(Schedulers.computation()) // 切换到计算线程
|
|
||||||
// .map(result -> {
|
|
||||||
// // 第二部分操作:在computation线程
|
|
||||||
// return result + " -> Step 2 completed";
|
|
||||||
// })
|
|
||||||
.observeOn(AndroidSchedulers.mainThread()) // 切换到主线程
|
|
||||||
.subscribe(finalResult -> {
|
|
||||||
// 最终结果处理:在主线程
|
|
||||||
Download curDownload = null;
|
|
||||||
// int count = finalResult.getCount();
|
|
||||||
// if (finalResult.moveToLast()) {
|
|
||||||
// curDownload = finalResult.getDownload();
|
|
||||||
// }
|
|
||||||
List<Download> downloadList = new ArrayList<>();
|
|
||||||
while (finalResult.moveToNext()) {
|
|
||||||
Download download = finalResult.getDownload();
|
|
||||||
downloadList.add(download);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CommonUtils.LogMsg("----------------下载总数量 -count=" + downloadList.size());
|
|
||||||
vmApplication.setDownloadData(downloadList);
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
protected DownloadManager getDownloadManager() {
|
|
||||||
return getMyDownloadManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
protected Scheduler getScheduler() {
|
|
||||||
// 返回 null 表示不需要使用调度器
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Notification getForegroundNotification(List<Download> downloads, int notMetRequirements) {
|
|
||||||
// 构建用于显示下载进度的通知
|
|
||||||
return buildNotification(downloads, notMetRequirements);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Notification buildNotification(
|
|
||||||
List<Download> downloads, int notMetRequirements) {
|
|
||||||
|
|
||||||
return new DownloadNotificationHelper(this, CHANNEL_ID)
|
|
||||||
.buildProgressNotification(this, R.drawable.ic_download, null, null, downloads, notMetRequirements);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,421 +0,0 @@
|
|||||||
package com.hi.music.player.media3;
|
|
||||||
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.OptIn;
|
|
||||||
import androidx.media3.common.MediaItem;
|
|
||||||
import androidx.media3.common.MediaMetadata;
|
|
||||||
import androidx.media3.common.PlaybackException;
|
|
||||||
import androidx.media3.common.Player;
|
|
||||||
import androidx.media3.common.util.UnstableApi;
|
|
||||||
import androidx.media3.session.MediaController;
|
|
||||||
import androidx.media3.session.SessionToken;
|
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.common.util.concurrent.MoreExecutors;
|
|
||||||
import com.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.api.MediaControllerListener;
|
|
||||||
import com.hi.music.player.api.MediaControllerStatusListener;
|
|
||||||
import com.hi.music.player.api.OnHasUrlAction;
|
|
||||||
import com.hi.music.player.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;
|
|
||||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
|
|
||||||
public class MyMediaControllerManager {
|
|
||||||
|
|
||||||
private static volatile MyMediaControllerManager myMediaControllerManagerInstance;
|
|
||||||
|
|
||||||
private MediaController mediaController;
|
|
||||||
|
|
||||||
private MediaControllerListener mListener;
|
|
||||||
|
|
||||||
private VMApplication mVmApplication;
|
|
||||||
|
|
||||||
|
|
||||||
//播放列表总数量
|
|
||||||
private List<ResponsePlayListInfo> playList;
|
|
||||||
|
|
||||||
public static MyMediaControllerManager getInstance() {
|
|
||||||
if (myMediaControllerManagerInstance == null) {
|
|
||||||
synchronized (RetrofitManager.class) {
|
|
||||||
if (myMediaControllerManagerInstance == null) {
|
|
||||||
myMediaControllerManagerInstance = new MyMediaControllerManager();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return myMediaControllerManagerInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init(MediaControllerStatusListener statusListener) {
|
|
||||||
SessionToken sessionToken =
|
|
||||||
new SessionToken(MusicApplication.myApplication, new ComponentName(MusicApplication.myApplication, PlaybackService.class));
|
|
||||||
ListenableFuture<MediaController> controllerFuture =
|
|
||||||
new MediaController.Builder(MusicApplication.myApplication, sessionToken).buildAsync();
|
|
||||||
controllerFuture.addListener(() -> {
|
|
||||||
// Call controllerFuture.get() to retrieve the MediaController.
|
|
||||||
// MediaController implements the Player interface, so it can be
|
|
||||||
// attached to the PlayerView UI component.
|
|
||||||
// playerView.setPlayer(controllerFuture.get());
|
|
||||||
try {
|
|
||||||
mediaController = controllerFuture.get();
|
|
||||||
statusListener.onMediaControllerComplete(true);
|
|
||||||
CommonUtils.LogMsg("=-----mediaController+" + mediaController);
|
|
||||||
} catch (ExecutionException | InterruptedException e) {
|
|
||||||
CommonUtils.LogErrorMsg(e.getMessage());
|
|
||||||
statusListener.onMediaControllerComplete(false);
|
|
||||||
}
|
|
||||||
}, MoreExecutors.directExecutor());
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addListener(VMApplication vmApplication, MediaControllerListener listener) {
|
|
||||||
mVmApplication = vmApplication;
|
|
||||||
mListener = listener;
|
|
||||||
mediaController.addListener(new Player.Listener() {
|
|
||||||
@Override
|
|
||||||
public void onPlayerError(PlaybackException error) {
|
|
||||||
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_ERROR);
|
|
||||||
mVmApplication.setPlayStatus(MyValue.PLAY_STATUS_CODE_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMediaItemTransition(@Nullable MediaItem mediaItem, int reason) {
|
|
||||||
//当前媒体项发生变化,切歌
|
|
||||||
if (mediaItem == null) {
|
|
||||||
//第二次进入PlayActitivity ,调用resetPlayList(),这里为null
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mListener.onChangeMusic(mediaItem);
|
|
||||||
mVmApplication.setPlayStatus(MyValue.PLAY_STATUS_CHANGE_MUSIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onIsPlayingChanged(boolean isPlaying) {
|
|
||||||
|
|
||||||
if (isPlaying) {
|
|
||||||
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PLAYING);
|
|
||||||
mVmApplication.setPlayStatus(MyValue.PLAY_STATUS_CODE_PLAYING);
|
|
||||||
// TODO: 2024/10/15 自动播放完成切歌到下一首播放没有触发这里请求下一首
|
|
||||||
checkUrl(false);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// 播放器暂停或停止
|
|
||||||
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PAUSE);
|
|
||||||
mVmApplication.setPlayStatus(MyValue.PLAY_STATUS_CODE_PAUSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPlaybackStateChanged(int playbackState) {
|
|
||||||
mListener.onPlayStatus(playbackState);
|
|
||||||
mVmApplication.setPlayStatus(playbackState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPositionDiscontinuity(Player.PositionInfo oldPosition, Player.PositionInfo newPosition, int reason) {
|
|
||||||
// 快进、快退等操作
|
|
||||||
// CommonUtils.LogMsg("=-----快进、快退+" + newPosition.positionMs);
|
|
||||||
// mediaControllerListener.onPlayStatus(playbackState);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkUrl(boolean playNextNow) {
|
|
||||||
if (mediaController.hasNextMediaItem()) {
|
|
||||||
int nextMediaItemIndex = mediaController.getNextMediaItemIndex();
|
|
||||||
onCallRequestUrl(nextMediaItemIndex, playNextNow, new OnHasUrlAction() {
|
|
||||||
@Override
|
|
||||||
public void onHasUrl() {
|
|
||||||
CommonUtils.LogMsg("-------------有有效URl--播放检查下一首 位置=" + nextMediaItemIndex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (mediaController.hasPreviousMediaItem()) {
|
|
||||||
int previousMediaItemIndex = mediaController.getPreviousMediaItemIndex();
|
|
||||||
onCallRequestUrl(previousMediaItemIndex, false, new OnHasUrlAction() {
|
|
||||||
@Override
|
|
||||||
public void onHasUrl() {
|
|
||||||
CommonUtils.LogMsg("-------------有有效URl--播放检查上一首 位置=" + previousMediaItemIndex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MediaController getMediaController() {
|
|
||||||
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;
|
|
||||||
return mediaController.getContentPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getBufferPos() {
|
|
||||||
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 列表循环、
|
|
||||||
*
|
|
||||||
* @param mode
|
|
||||||
*/
|
|
||||||
public void setMode(int mode) {
|
|
||||||
switch (mode) {
|
|
||||||
case 0:
|
|
||||||
mediaController.setRepeatMode(Player.REPEAT_MODE_OFF);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
mediaController.setRepeatMode(Player.REPEAT_MODE_ONE);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
mediaController.setRepeatMode(Player.REPEAT_MODE_ALL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRepeatMode() {
|
|
||||||
return mediaController.getRepeatMode();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCurVideoId() {
|
|
||||||
MediaItem currentMediaItem = mediaController.getCurrentMediaItem();
|
|
||||||
if (currentMediaItem != null) {
|
|
||||||
return currentMediaItem.mediaId;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新播放列表中的音频url
|
|
||||||
*
|
|
||||||
* @param playUrl
|
|
||||||
*/
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
public void UpdateAudioUrl(ResponsePlayUrl playUrl, int index) {
|
|
||||||
for (int i = 0; i < mediaController.getMediaItemCount(); i++) {
|
|
||||||
MediaItem mediaItemAt = mediaController.getMediaItemAt(i);
|
|
||||||
if (mediaItemAt.mediaId.equals(playUrl.getVideoId())) {
|
|
||||||
|
|
||||||
MediaItem.Builder builder = mediaItemAt.buildUpon();
|
|
||||||
builder.setMediaId(playUrl.getVideoId());
|
|
||||||
builder.setUri(playUrl.getVideoUrlMedium());
|
|
||||||
// builder.setCustomCacheKey(playUrl.getVideoUrlMedium());
|
|
||||||
//针对于,已经从分类合集列表页面进入播放页面的数据(只有小的封面图)
|
|
||||||
if (mediaItemAt.mediaMetadata.artworkUri == null) {
|
|
||||||
MediaMetadata.Builder builder1 = mediaItemAt.mediaMetadata.buildUpon();
|
|
||||||
builder1.setArtworkUri(Uri.parse(playUrl.getBigCovert()));
|
|
||||||
builder.setMediaMetadata(builder1.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
CharSequence title = mediaController.getMediaItemAt(i).mediaMetadata.title;
|
|
||||||
CommonUtils.LogMsg("-------------更新播放列表中的音频--id=" + playUrl.getVideoId());
|
|
||||||
mediaController.replaceMediaItem(i, builder.build());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlayList(List<ResponsePlayListInfo> playList) {
|
|
||||||
this.playList = playList;
|
|
||||||
addMusicPlayList(playList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ResponsePlayListInfo> getPlayList() {
|
|
||||||
return playList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetPlayList() {
|
|
||||||
mediaController.clearMediaItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加播放列表(不带音频url)
|
|
||||||
* 注意没有setUri的不会被实际添加到mediaController(mediaController.getMediaItemCount())
|
|
||||||
* 这里setUri 一个占位
|
|
||||||
*
|
|
||||||
* @param listInfo
|
|
||||||
*/
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
public void addMusicPlayList(List<ResponsePlayListInfo> listInfo) {
|
|
||||||
playList = listInfo;
|
|
||||||
for (int i = 0; i < listInfo.size(); i++) {
|
|
||||||
ResponsePlayListInfo playInfo = listInfo.get(i);
|
|
||||||
|
|
||||||
MediaItem.Builder builder = new MediaItem.Builder();
|
|
||||||
String videoId = playInfo.getVideoId();
|
|
||||||
//唯一标识符
|
|
||||||
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())
|
|
||||||
MediaMetadata_builder.setArtworkUri(Uri.parse(playInfo.getCovert()));
|
|
||||||
MediaMetadata_builder.setTitle(playInfo.getSongTitle());
|
|
||||||
|
|
||||||
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());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addMusicPlayList(MediaItem mediaItem) {
|
|
||||||
mediaController.addMediaItem(mediaItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void play() {
|
|
||||||
if (!mediaController.isPlaying()) {
|
|
||||||
CommonUtils.LogMsg("-----------prepare");
|
|
||||||
mediaController.prepare();
|
|
||||||
mediaController.play();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pause() {
|
|
||||||
if (mediaController.isPlaying())
|
|
||||||
mediaController.pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
if (mediaController.isPlaying())
|
|
||||||
mediaController.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void playNext(onPlayNextListener listener) {
|
|
||||||
if (mediaController.hasNextMediaItem()) {
|
|
||||||
int nextMediaItemIndex = mediaController.getNextMediaItemIndex();
|
|
||||||
|
|
||||||
onCallRequestUrl(nextMediaItemIndex, true, new OnHasUrlAction() {
|
|
||||||
@Override
|
|
||||||
public void onHasUrl() {
|
|
||||||
mediaController.seekToNextMediaItem();
|
|
||||||
mediaController.play();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
listener.onPlayNext(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void playPrevious() {
|
|
||||||
if (mediaController.hasPreviousMediaItem()) {
|
|
||||||
|
|
||||||
int previousMediaItemIndex = mediaController.getPreviousMediaItemIndex();
|
|
||||||
onCallRequestUrl(previousMediaItemIndex, true, new OnHasUrlAction() {
|
|
||||||
@Override
|
|
||||||
public void onHasUrl() {
|
|
||||||
mediaController.seekToPreviousMediaItem();
|
|
||||||
mediaController.play();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
mediaController.seekTo(0);
|
|
||||||
mediaController.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 播放指定播放列表位置的歌曲
|
|
||||||
*
|
|
||||||
* @param index
|
|
||||||
*/
|
|
||||||
public void playPositionMusic(int index) {
|
|
||||||
if (index >= mediaController.getMediaItemCount()) {
|
|
||||||
CommonUtils.LogErrorMsg("-------------数组越界");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stop();
|
|
||||||
mediaController.seekTo(index, 0);
|
|
||||||
onCallRequestUrl(index, true, new OnHasUrlAction() {
|
|
||||||
@Override
|
|
||||||
public void onHasUrl() {
|
|
||||||
mediaController.play();
|
|
||||||
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) {
|
|
||||||
//查看
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
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,176 +0,0 @@
|
|||||||
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.datasource.DataSource;
|
|
||||||
import androidx.media3.datasource.DataSpec;
|
|
||||||
import androidx.media3.datasource.DefaultDataSource;
|
|
||||||
import androidx.media3.datasource.DefaultHttpDataSource;
|
|
||||||
import androidx.media3.datasource.ResolvingDataSource;
|
|
||||||
import androidx.media3.datasource.TransferListener;
|
|
||||||
import androidx.media3.datasource.cache.CacheDataSource;
|
|
||||||
import androidx.media3.datasource.cache.SimpleCache;
|
|
||||||
import androidx.media3.exoplayer.DefaultLoadControl;
|
|
||||||
import androidx.media3.exoplayer.ExoPlayer;
|
|
||||||
|
|
||||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
|
||||||
import androidx.media3.exoplayer.source.MediaSource;
|
|
||||||
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
|
|
||||||
import androidx.media3.session.MediaSession;
|
|
||||||
import androidx.media3.session.MediaSessionService;
|
|
||||||
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class PlaybackService extends MediaSessionService {
|
|
||||||
private MediaSession mediaSession = null;
|
|
||||||
private ExoPlayer player;
|
|
||||||
|
|
||||||
private SimpleCache playCache, downloadCache;
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
|
|
||||||
DynamicMediaSourceFactory customMediaSourceFactory = new DynamicMediaSourceFactory(getCacheDataSourceFactory(this));
|
|
||||||
ProgressiveMediaSource.Factory factory = new ProgressiveMediaSource.Factory(getUrlFactory());
|
|
||||||
|
|
||||||
|
|
||||||
// 创建 DefaultLoadControl,配置缓冲参数
|
|
||||||
DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
|
|
||||||
.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(factory)
|
|
||||||
.setLoadControl(loadControl)
|
|
||||||
.build();
|
|
||||||
mediaSession = new MediaSession.Builder(this, player)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建带缓存的数据源工厂
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
private CacheDataSource.Factory getCacheDataSourceFactory(Context context) {
|
|
||||||
DefaultDataSource.Factory factory = new DefaultDataSource.Factory(this);
|
|
||||||
playCache = MyPlayCacheManager.getInitPlayCache(context);
|
|
||||||
CacheDataSource.Factory factory1 = new CacheDataSource.Factory().setCache(playCache)
|
|
||||||
.setUpstreamDataSourceFactory(new DefaultHttpDataSource.Factory()
|
|
||||||
.setConnectTimeoutMs(16000)
|
|
||||||
.setReadTimeoutMs(8000)
|
|
||||||
.setUserAgent("Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0"))
|
|
||||||
.setEventListener(new CacheDataSource.EventListener() {
|
|
||||||
@Override
|
|
||||||
public void onCachedBytesRead(long cacheSizeBytes, long cachedBytesRead) {
|
|
||||||
CommonUtils.LogMsg("-----------缓存2 -PlayCache-" + cacheSizeBytes + "----cacheSizeBytes=" + cachedBytesRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCacheIgnored(int reason) {
|
|
||||||
CommonUtils.LogMsg("-----------缓存2忽略 PlayCache=" + reason);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
downloadCache = MyDownloadService.getDownloadCache();
|
|
||||||
return new CacheDataSource.Factory()
|
|
||||||
.setCache(downloadCache)
|
|
||||||
.setUpstreamDataSourceFactory(factory1)
|
|
||||||
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
|
|
||||||
.setEventListener(new CacheDataSource.EventListener() {
|
|
||||||
@Override
|
|
||||||
public void onCachedBytesRead(long cacheSizeBytes, long cachedBytesRead) {
|
|
||||||
CommonUtils.LogMsg("-----------缓存1 DownloadCache --" + cacheSizeBytes + "----cacheSizeBytes=" + cachedBytesRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCacheIgnored(int reason) {
|
|
||||||
CommonUtils.LogMsg("-----------缓存1忽略DownloadCache =" + reason);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// .setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
private DataSource.Factory getUrlFactory() {
|
|
||||||
long chunkLength = 512 * 1024L;
|
|
||||||
return new ResolvingDataSource.Factory(getCacheDataSourceFactory(this), new ResolvingDataSource.Resolver() {
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataSpec resolveDataSpec(DataSpec dataSpec) {
|
|
||||||
CommonUtils.LogMsg("--------resolveDataSpec dataSpec.key=" + dataSpec.key+"---dataSpec.uri="+dataSpec.uri);
|
|
||||||
return dataSpec;
|
|
||||||
|
|
||||||
// long length = 1L;
|
|
||||||
// String videoId = dataSpec.key;
|
|
||||||
// long position = dataSpec.position;
|
|
||||||
// if (dataSpec.length >= 0) {
|
|
||||||
// length = dataSpec.length;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (downloadCache.isCached(videoId,position,length)){
|
|
||||||
// CommonUtils.LogMsg("--------resolveDataSpec downloadCache" );
|
|
||||||
// return dataSpec;
|
|
||||||
// }else if(playCache.isCached(videoId,position,chunkLength)){
|
|
||||||
// CommonUtils.LogMsg("--------resolveDataSpec playCache" );
|
|
||||||
// return dataSpec;
|
|
||||||
// }else {
|
|
||||||
// CommonUtils.LogMsg("--------resolveDataSpec uri" );
|
|
||||||
// return dataSpec;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Uri resolveReportedUri(Uri uri) {
|
|
||||||
CommonUtils.LogMsg("--------resolveDataSpec uri=" + uri);
|
|
||||||
return ResolvingDataSource.Resolver.super.resolveReportedUri(Uri.parse("---"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) {
|
|
||||||
return mediaSession;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTaskRemoved(@Nullable Intent rootIntent) {
|
|
||||||
Player player = mediaSession.getPlayer();
|
|
||||||
if (!player.getPlayWhenReady()
|
|
||||||
|| player.getMediaItemCount() == 0
|
|
||||||
|| player.getPlaybackState() == Player.STATE_ENDED) {
|
|
||||||
// Stop the service if not playing, continue playing in the background
|
|
||||||
// otherwise.
|
|
||||||
stopSelf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
mediaSession.getPlayer().release();
|
|
||||||
mediaSession.release();
|
|
||||||
mediaSession = null;
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,207 +0,0 @@
|
|||||||
package com.hi.music.player.network;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.api.RequestListener;
|
|
||||||
import com.hi.music.player.javabean.requestbody.BodyHome;
|
|
||||||
import com.hi.music.player.javabean.requestbody.BodyPlay;
|
|
||||||
import com.hi.music.player.javabean.requestbody.BodyPlayUrl;
|
|
||||||
import com.hi.music.player.javabean.requestbody.BodySearch;
|
|
||||||
import com.hi.music.player.javabean.requestbody.BodySearchSuggestion;
|
|
||||||
import com.hi.music.player.javabean.requestbody.child.Client;
|
|
||||||
import com.hi.music.player.javabean.requestbody.child.ContextBody;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.ResponseBody;
|
|
||||||
import okhttp3.logging.HttpLoggingInterceptor;
|
|
||||||
import retrofit2.Retrofit;
|
|
||||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
|
||||||
import retrofit2.converter.gson.GsonConverterFactory;
|
|
||||||
|
|
||||||
public class RetrofitManager {
|
|
||||||
|
|
||||||
private String base_Host = "https://music.youtube.com/";
|
|
||||||
|
|
||||||
private String base_Host_test = "https://rr2---sn-tt1e7nlz.googlevideo.com/";
|
|
||||||
private static volatile RetrofitManager REQUEST_MANAGER;
|
|
||||||
|
|
||||||
private Retrofit retrofit;
|
|
||||||
public MediaType JSON = MediaType.get("application/json; charset=utf-8");
|
|
||||||
private MusicApi musicApi;
|
|
||||||
|
|
||||||
private String header1 = "playlistPanelVideoRenderer(title,navigationEndpoint,longBylineText,shortBylineText,thumbnail,lengthText)";
|
|
||||||
private String header = "contents.singleColumnMusicWatchNextResultsRenderer.tabbedRenderer.watchNextTabbedResultsRenderer.tabs.tabRenderer.content.musicQueueRenderer.content.playlistPanelRenderer(continuations,contents(automixPreviewVideoRenderer," + header1 + "))";
|
|
||||||
|
|
||||||
private RetrofitManager() {
|
|
||||||
|
|
||||||
musicApi = getRetrofit().create(MusicApi.class);
|
|
||||||
}
|
|
||||||
private synchronized Retrofit getRetrofit() {
|
|
||||||
if (retrofit == null) {
|
|
||||||
long DEFAULT_TIMEOUT = 5;
|
|
||||||
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
|
|
||||||
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
|
|
||||||
OkHttpClient client = new OkHttpClient.Builder()
|
|
||||||
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
|
|
||||||
.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
|
|
||||||
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
|
|
||||||
.addInterceptor(httpLoggingInterceptor)
|
|
||||||
.build();
|
|
||||||
retrofit = new Retrofit.Builder()
|
|
||||||
.baseUrl(base_Host)
|
|
||||||
.client(client)
|
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
|
||||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
return retrofit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RetrofitManager getInstance() {
|
|
||||||
if (REQUEST_MANAGER == null) {
|
|
||||||
synchronized (RetrofitManager.class) { //锁,防止线程问题
|
|
||||||
if (REQUEST_MANAGER == null) {
|
|
||||||
REQUEST_MANAGER = new RetrofitManager();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return REQUEST_MANAGER;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void getHomeData(RequestListener<ResponseBody> requestListener) {
|
|
||||||
BodyHome bodyHome = new BodyHome();
|
|
||||||
Gson gson = new Gson();
|
|
||||||
String s = gson.toJson(bodyHome);
|
|
||||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
|
||||||
musicApi.getHomeData(requestBody)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.unsubscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(new ObserverWrapper<ResponseBody>(requestListener));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getHomeMoreData(String continuation, String itct, String visitorData, RequestListener<ResponseBody> requestListener) {
|
|
||||||
BodyHome bodyHome = new BodyHome();
|
|
||||||
bodyHome.getContext().getClient().setVisitorData(visitorData);
|
|
||||||
Gson gson = new Gson();
|
|
||||||
String s = gson.toJson(bodyHome);
|
|
||||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
|
||||||
|
|
||||||
HashMap<String, String> stringHashMap = new HashMap<>();
|
|
||||||
stringHashMap.put("ctoken", continuation);
|
|
||||||
stringHashMap.put("continuation", continuation);
|
|
||||||
stringHashMap.put("type", "next");
|
|
||||||
stringHashMap.put("itct", itct);
|
|
||||||
stringHashMap.put("prettyPrint", "false");
|
|
||||||
musicApi.getHomeMoreData(continuation, continuation, "next", itct, false, requestBody)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.unsubscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(new ObserverWrapper<ResponseBody>(requestListener));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void getPlayList(String params, String playlistId, String videoId, String musicVideoType, RequestListener<ResponseBody> requestListener) {
|
|
||||||
BodyPlay bodyPlay = new BodyPlay();
|
|
||||||
bodyPlay.setParams(params);
|
|
||||||
bodyPlay.setPlaylistId(playlistId);
|
|
||||||
bodyPlay.setVideoId(videoId);
|
|
||||||
bodyPlay.getWatchEndpointMusicSupportedConfigs().setMusicVideoType(musicVideoType);
|
|
||||||
Gson gson = new Gson();
|
|
||||||
String s = gson.toJson(bodyPlay);
|
|
||||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
|
||||||
musicApi.getMusicPlayPage(header, requestBody)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.unsubscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(new ObserverWrapper<ResponseBody>(requestListener));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void getPlayUrl(String videoId, RequestListener<ResponseBody> requestListener) {
|
|
||||||
BodyPlayUrl bodyPlay = new BodyPlayUrl();
|
|
||||||
bodyPlay.setVideoId(videoId);
|
|
||||||
Client client = bodyPlay.getContext().getClient();
|
|
||||||
client.setClientName("ANDROID");
|
|
||||||
client.setClientVersion("19.05.36");
|
|
||||||
client.setPlatform("DESKTOP");
|
|
||||||
String visitorData = MusicApplication.getVisitorData();
|
|
||||||
// client.setVisitorData("CgtWN1RXaURPN3LNZyiZK9e4BjIKCgJVUXIEGgAgPW%3D%3D");
|
|
||||||
client.setVisitorData(visitorData);
|
|
||||||
// bodyPlay.getContext().getThirdParty().setEmbedUrl("https://www.youtube.com/watch?v="+videoId);
|
|
||||||
|
|
||||||
|
|
||||||
Gson gson = new Gson();
|
|
||||||
String s = gson.toJson(bodyPlay);
|
|
||||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
|
||||||
musicApi.getMusicPlayUrl(requestBody)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.unsubscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(new ObserverWrapper<ResponseBody>(requestListener));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void getCategoryList(String browserId, RequestListener<ResponseBody> requestListener) {
|
|
||||||
BodyHome bodyHome = new BodyHome();
|
|
||||||
bodyHome.setBrowseId(browserId);
|
|
||||||
// bodyHome.setBrowseId("VLPLI-asvmHZWNo_xjMMfD_v2O2lTyCdrjaK");
|
|
||||||
|
|
||||||
Client client = bodyHome.getContext().getClient();
|
|
||||||
client.setClientVersion("1.20240506.01.00");
|
|
||||||
|
|
||||||
|
|
||||||
Gson gson = new Gson();
|
|
||||||
String s = gson.toJson(bodyHome);
|
|
||||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
|
||||||
|
|
||||||
|
|
||||||
musicApi.getCategoryList(requestBody)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.unsubscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(new ObserverWrapper<>(requestListener));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void getSearchSuggestion(String input, RequestListener<ResponseBody> requestListener) {
|
|
||||||
BodySearchSuggestion body = new BodySearchSuggestion();
|
|
||||||
body.setInput(input);
|
|
||||||
Client client = body.getContext().getClient();
|
|
||||||
client.setClientVersion("1.20240506.01.00");
|
|
||||||
Gson gson = new Gson();
|
|
||||||
String s = gson.toJson(body);
|
|
||||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
|
||||||
musicApi.getSearchSuggestion(requestBody)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.unsubscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(new ObserverWrapper<>(requestListener));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void getSearch(String query, RequestListener<ResponseBody> requestListener) {
|
|
||||||
BodySearch body = new BodySearch();
|
|
||||||
body.setQuery(query);
|
|
||||||
Client client = body.getContext().getClient();
|
|
||||||
client.setClientVersion("1.20240506.01.00");
|
|
||||||
Gson gson = new Gson();
|
|
||||||
String s = gson.toJson(body);
|
|
||||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
|
||||||
musicApi.getSearch(requestBody)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.unsubscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(new ObserverWrapper<>(requestListener));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,252 +0,0 @@
|
|||||||
package com.hi.music.player.ui.activity;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.OptIn;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.view.WindowCompat;
|
|
||||||
import androidx.core.view.WindowInsetsControllerCompat;
|
|
||||||
import androidx.lifecycle.Observer;
|
|
||||||
import androidx.lifecycle.ViewModel;
|
|
||||||
import androidx.media3.common.MediaItem;
|
|
||||||
import androidx.media3.common.Player;
|
|
||||||
import androidx.media3.common.util.UnstableApi;
|
|
||||||
import androidx.viewbinding.ViewBinding;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.CircleCrop;
|
|
||||||
import com.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.api.onPlayNextListener;
|
|
||||||
import com.hi.music.player.databinding.ActivityBaseBinding;
|
|
||||||
import com.hi.music.player.databinding.LayoutPanelBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.helper.MyValue;
|
|
||||||
import com.hi.music.player.helper.ViewModelScope;
|
|
||||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
|
||||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
|
||||||
|
|
||||||
public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActivity implements View.OnClickListener {
|
|
||||||
|
|
||||||
private final ViewModelScope mViewModelScope = new ViewModelScope();
|
|
||||||
|
|
||||||
protected T vb;
|
|
||||||
|
|
||||||
private Window window;
|
|
||||||
private View decorView;
|
|
||||||
protected View mView;
|
|
||||||
private ActivityBaseBinding rootVb;
|
|
||||||
|
|
||||||
protected VMApplication vmApplication;
|
|
||||||
protected MyMediaControllerManager mediaControllerManager;
|
|
||||||
|
|
||||||
private Handler mHandler;
|
|
||||||
private Runnable mRunnable;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
vb = getViewBinding();
|
|
||||||
View root = vb.getRoot();
|
|
||||||
rootVb = ActivityBaseBinding.inflate(getLayoutInflater(), null, false);
|
|
||||||
rootVb.frameLayout.addView(root);
|
|
||||||
setContentView(rootVb.getRoot());
|
|
||||||
window = getWindow();
|
|
||||||
decorView = window.getDecorView();
|
|
||||||
mView = decorView.getRootView();
|
|
||||||
vmApplication = getApplicationScopeViewModel(VMApplication.class);
|
|
||||||
mediaControllerManager = MyMediaControllerManager.getInstance();
|
|
||||||
|
|
||||||
if (showPanel())
|
|
||||||
initPanel();
|
|
||||||
setStatusBar();
|
|
||||||
if (isFullScreen()) {
|
|
||||||
// ImmersionBar.with(this).init();//设置沉浸式效果
|
|
||||||
// ImmersionBar.setStatusBarView(this,0);
|
|
||||||
initFullScreen();
|
|
||||||
}
|
|
||||||
onCreateInit();
|
|
||||||
onInitClick();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract T getViewBinding();
|
|
||||||
|
|
||||||
|
|
||||||
protected abstract void onCreateInit();
|
|
||||||
|
|
||||||
protected abstract void onInitClick();
|
|
||||||
|
|
||||||
public abstract boolean isFullScreen();
|
|
||||||
|
|
||||||
public abstract boolean statusBarLight();
|
|
||||||
|
|
||||||
public abstract boolean showPanel();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void initPanel() {
|
|
||||||
LayoutPanelBinding panelVb = LayoutPanelBinding.inflate(getLayoutInflater());
|
|
||||||
View panelView = panelVb.getRoot();
|
|
||||||
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
|
||||||
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
||||||
CommonUtils.dpToPx(74)
|
|
||||||
);
|
|
||||||
initProgressHandler(panelVb);
|
|
||||||
panelVb.imPlay.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
panelVb.imPlay.setSelected(!panelVb.imPlay.isSelected());
|
|
||||||
if (panelVb.imPlay.isSelected()) {
|
|
||||||
mediaControllerManager.play();
|
|
||||||
} else {
|
|
||||||
mediaControllerManager.pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
panelVb.imNext.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
mediaControllerManager.playNext(new onPlayNextListener() {
|
|
||||||
@Override
|
|
||||||
public void onPlayNext(boolean hasNext) {
|
|
||||||
if (!hasNext) {
|
|
||||||
Toast.makeText(MusicApplication.myApplication, getString(R.string.no_next_song_yet), Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
panelVb.layoutPanel.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
Intent intent = new Intent(MusicApplication.myApplication, PlayActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_PANEL);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this instanceof HomeActivity) {
|
|
||||||
layoutParams.setMargins(CommonUtils.dpToPx(22), 0, CommonUtils.dpToPx(22), CommonUtils.dpToPx(82));
|
|
||||||
} else {
|
|
||||||
layoutParams.setMargins(CommonUtils.dpToPx(22), 0, CommonUtils.dpToPx(22), CommonUtils.dpToPx(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
layoutParams.gravity = Gravity.BOTTOM;
|
|
||||||
vmApplication.playStatus.observe(this, new Observer<Integer>() {
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
@Override
|
|
||||||
public void onChanged(Integer integer) {
|
|
||||||
CommonUtils.LogMsg("----------面板 播放状态更新=" + integer);
|
|
||||||
if (panelView.getParent() == null) {
|
|
||||||
CommonUtils.LogMsg("----------显示面板");
|
|
||||||
rootVb.frameLayout.addView(panelView, layoutParams);
|
|
||||||
mHandler.post(mRunnable);
|
|
||||||
}
|
|
||||||
MediaItem currentMediaItem = mediaControllerManager.getCurMediaItem();
|
|
||||||
if(currentMediaItem!= null){
|
|
||||||
Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri;
|
|
||||||
CharSequence title = currentMediaItem.mediaMetadata.title;
|
|
||||||
CharSequence artist = currentMediaItem.mediaMetadata.artist;
|
|
||||||
|
|
||||||
if (currentMediaItem.mediaMetadata.durationMs != null) {
|
|
||||||
long durationMs = currentMediaItem.mediaMetadata.durationMs;
|
|
||||||
panelVb.circularPb.setMaxProgress((int) durationMs);
|
|
||||||
}
|
|
||||||
if(artworkUri!= null){
|
|
||||||
CommonUtils.LogMsg("----------artworkUri="+artworkUri.toString());
|
|
||||||
Glide.with(MusicApplication.myApplication)
|
|
||||||
.load(artworkUri.toString())
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.transform(new CircleCrop())
|
|
||||||
.into(panelVb.image);
|
|
||||||
}
|
|
||||||
panelVb.title.setText(title);
|
|
||||||
panelVb.singer.setText(artist);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (integer) {
|
|
||||||
case Player.STATE_IDLE:
|
|
||||||
|
|
||||||
case Player.STATE_ENDED:
|
|
||||||
case Player.STATE_READY:
|
|
||||||
|
|
||||||
case MyValue.PLAY_STATUS_CODE_PAUSE:
|
|
||||||
case Player.STATE_BUFFERING:
|
|
||||||
case MyValue.PLAY_STATUS_CODE_ERROR:
|
|
||||||
|
|
||||||
//快进没有缓冲的时候触发
|
|
||||||
//播放完成
|
|
||||||
panelVb.imPlay.setSelected(false);
|
|
||||||
break;
|
|
||||||
case MyValue.PLAY_STATUS_CHANGE_MUSIC:
|
|
||||||
case MyValue.PLAY_STATUS_CODE_PLAYING:
|
|
||||||
panelVb.imPlay.setSelected(true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void initProgressHandler(LayoutPanelBinding panelBinding) {
|
|
||||||
mHandler = new Handler();
|
|
||||||
mRunnable = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
updatePlaybackProgress(panelBinding);
|
|
||||||
mHandler.postDelayed(this, 1000);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updatePlaybackProgress(LayoutPanelBinding panelBinding) {
|
|
||||||
// 获取当前播放位置
|
|
||||||
long contentPos = mediaControllerManager.getContentPos();
|
|
||||||
long bufferPos = mediaControllerManager.getBufferPos();
|
|
||||||
|
|
||||||
// CommonUtils.LogMsg("---------播放进度-----contentPos=" + contentPos + "-----缓冲进度=" + bufferPos);
|
|
||||||
panelBinding.circularPb.setProgress((int) contentPos);
|
|
||||||
}
|
|
||||||
private void setStatusBar() {
|
|
||||||
//深色模式
|
|
||||||
WindowInsetsControllerCompat insetsController = WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView());
|
|
||||||
insetsController.setAppearanceLightStatusBars(statusBarLight());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initFullScreen() {
|
|
||||||
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
|
||||||
// mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
|
||||||
mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <K extends ViewModel> K getActivityScopeViewModel(@NonNull Class<K> modelClass) {
|
|
||||||
return mViewModelScope.getActivityScopeViewModel(this, modelClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <K extends ViewModel> K getApplicationScopeViewModel(@NonNull Class<K> modelClass) {
|
|
||||||
return mViewModelScope.getApplicationScopeViewModel(modelClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
if (mHandler != null && mRunnable != null)
|
|
||||||
mHandler.removeCallbacks(mRunnable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,259 +0,0 @@
|
|||||||
package com.hi.music.player.ui.activity;
|
|
||||||
|
|
||||||
import static com.bumptech.glide.request.RequestOptions.bitmapTransform;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.OptIn;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.lifecycle.Observer;
|
|
||||||
import androidx.media3.common.util.UnstableApi;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.GradientDrawable;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.DataSource;
|
|
||||||
import com.bumptech.glide.load.engine.GlideException;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransitionOptions;
|
|
||||||
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.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.adapter.AdapterCategoryList;
|
|
||||||
import com.hi.music.player.api.HomeItemClickListener;
|
|
||||||
import com.hi.music.player.api.onImageColorListener;
|
|
||||||
import com.hi.music.player.databinding.ActivityCategoryListBinding;
|
|
||||||
import com.hi.music.player.databinding.ActivityHomeBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.helper.MyValue;
|
|
||||||
import com.hi.music.player.javabean.response.ResponseCategoryList;
|
|
||||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseCategory;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
|
||||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
|
||||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMCategoryList;
|
|
||||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMHome;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import jp.wasabeef.glide.transformations.BlurTransformation;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 音乐合集或者专辑列表页面
|
|
||||||
*/
|
|
||||||
public class CategoryListActivity extends BaseActivity<ActivityCategoryListBinding> implements HomeItemClickListener {
|
|
||||||
|
|
||||||
|
|
||||||
private VMCategoryList vm;
|
|
||||||
// private VMApplication vmApplication;
|
|
||||||
|
|
||||||
private ResponseCategoryList mCategoryList;
|
|
||||||
private String mPageType;
|
|
||||||
private String twoSubtitle;
|
|
||||||
private String browseId;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActivityCategoryListBinding getViewBinding() {
|
|
||||||
return ActivityCategoryListBinding.inflate(getLayoutInflater());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreateInit() {
|
|
||||||
vm = getActivityScopeViewModel(VMCategoryList.class);
|
|
||||||
// vmApplication = getApplicationScopeViewModel(VMApplication.class);
|
|
||||||
Intent intent = getIntent();
|
|
||||||
if (intent == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mPageType= intent.getStringExtra(MyValue.KEY_CATEGORY_LIST_TYPE);
|
|
||||||
twoSubtitle = intent.getStringExtra(MyValue.KEY_CATEGORY_LIST_SINGER_NAME);
|
|
||||||
browseId = intent.getStringExtra(MyValue.KEY_CATEGORY_LIST_BROWSER_ID);
|
|
||||||
|
|
||||||
vb.pbLoading.setVisibility(View.VISIBLE);
|
|
||||||
vm.getList(browseId);
|
|
||||||
vm.data.observe(this, new Observer<ResponseCategoryList>() {
|
|
||||||
@Override
|
|
||||||
public void onChanged(ResponseCategoryList responseCategoryList) {
|
|
||||||
if (responseCategoryList == null) {
|
|
||||||
vb.pbLoading.setVisibility(View.GONE);
|
|
||||||
updateErrorLayout(getString(R.string.playList_loading_failed),true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mCategoryList = responseCategoryList;
|
|
||||||
loadInfo(mCategoryList);
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
private void updateErrorLayout(String msg, boolean isShow) {
|
|
||||||
if (isShow)
|
|
||||||
vb.layoutError.linearRetry.setVisibility(View.VISIBLE);
|
|
||||||
else vb.layoutError.linearRetry.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
if(msg!= null&&!msg.isEmpty()){
|
|
||||||
vb.layoutError.tvErrorMsg.setText(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected void onInitClick() {
|
|
||||||
vb.imBack.setOnClickListener(this);
|
|
||||||
vb.btnPlay.setOnClickListener(this);
|
|
||||||
vb.layoutError.tvRetry.setOnClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFullScreen() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean statusBarLight() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean showPanel() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (v.equals(vb.imBack)) {
|
|
||||||
finish();
|
|
||||||
} else if (v.equals(vb.btnPlay)) {
|
|
||||||
int musicIndex = 0;
|
|
||||||
Intent intent = new Intent(this, PlayActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST, mCategoryList.getList().get(musicIndex));
|
|
||||||
// intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST_INDEX,musicIndex);
|
|
||||||
intent.putExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_SOURCE_CATEGORY);
|
|
||||||
startActivity(intent);
|
|
||||||
vmApplication.reSetPlayList(mCategoryList.getList());
|
|
||||||
}else if(v.equals(vb.layoutError.tvRetry)){
|
|
||||||
vb.pbLoading.setVisibility(View.VISIBLE);
|
|
||||||
updateErrorLayout(null,false);
|
|
||||||
vm.getList(browseId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadInfo(ResponseCategoryList info) {
|
|
||||||
vb.btnPlay.setVisibility(View.VISIBLE);
|
|
||||||
switch (mPageType) {
|
|
||||||
case MyValue.PAGE_TYPE_LIST:
|
|
||||||
vb.tvSingerName.setVisibility(View.GONE);
|
|
||||||
break;
|
|
||||||
case MyValue.PAGE_TYPE_ALBUM:
|
|
||||||
vb.tvSingerName.setVisibility(View.VISIBLE);
|
|
||||||
String singNameValue = "";
|
|
||||||
String singName = info.getSingName();
|
|
||||||
if(singName!= null&&!singName.isEmpty()){
|
|
||||||
singNameValue= singName;
|
|
||||||
}else {
|
|
||||||
String[] split = twoSubtitle.split("•");
|
|
||||||
if (split != null && split.length > 1) {
|
|
||||||
singNameValue = split[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CommonUtils.LogMsg("singNameValue=" + singNameValue);
|
|
||||||
vb.tvSingerName.setText(singNameValue);
|
|
||||||
for (ResponsePlayListInfo playListInfo : info.getList()) {
|
|
||||||
playListInfo.setSingerName(singNameValue);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
vb.tvTitle.setText(info.getTitle());
|
|
||||||
vb.tvSubTitle.setText(info.getDescription());
|
|
||||||
|
|
||||||
AdapterCategoryList adapterCategoryList = new AdapterCategoryList();
|
|
||||||
adapterCategoryList.setHomeItemClickListener(this);
|
|
||||||
adapterCategoryList.setPageType(mPageType);
|
|
||||||
vb.recyclerview.setLayoutManager(new LinearLayoutManager(this));
|
|
||||||
adapterCategoryList.setData(info.getList());
|
|
||||||
vb.recyclerview.setAdapter(adapterCategoryList);
|
|
||||||
loadCovert(info.getCovert());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void loadCovert(String url) {
|
|
||||||
// 加载图片并应用高斯模糊效果
|
|
||||||
Glide.with(this)
|
|
||||||
.load(url)
|
|
||||||
.apply(bitmapTransform(new BlurTransformation(25, 3))) // 设置模糊半径和模糊采样
|
|
||||||
.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) {
|
|
||||||
CommonUtils.extractColorsFromImage(resource,vb.imBg);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.preload();
|
|
||||||
|
|
||||||
|
|
||||||
Glide.with(MusicApplication.myApplication)
|
|
||||||
.asDrawable()
|
|
||||||
// .apply(bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10))))
|
|
||||||
.load(url)
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
vb.pbLoading.setVisibility(View.GONE);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
// CommonUtils.getDominantDarkColor1(resource, new onImageColorListener() {
|
|
||||||
// @Override
|
|
||||||
// public void onImageColor(int color) {
|
|
||||||
// if (color == -1) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
vb.pbLoading.setVisibility(View.GONE);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into(vb.imCovert);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClickItemCategoryList(ResponsePlayListInfo data, int musicIndex) {
|
|
||||||
Intent intent = new Intent(this, PlayActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST, data);
|
|
||||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST_INDEX, musicIndex);
|
|
||||||
intent.putExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_SOURCE_CATEGORY);
|
|
||||||
startActivity(intent);
|
|
||||||
vmApplication.reSetPlayList(mCategoryList.getList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,862 +0,0 @@
|
|||||||
package com.hi.music.player.ui.activity;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.GradientDrawable;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.animation.Animation;
|
|
||||||
import android.view.animation.AnimationUtils;
|
|
||||||
import android.widget.SeekBar;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.OptIn;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.lifecycle.Observer;
|
|
||||||
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;
|
|
||||||
import androidx.media3.exoplayer.offline.DownloadService;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.DataSource;
|
|
||||||
import com.bumptech.glide.load.engine.GlideException;
|
|
||||||
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.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;
|
|
||||||
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;
|
|
||||||
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 {
|
|
||||||
|
|
||||||
|
|
||||||
//单曲进入传递的数据
|
|
||||||
private ResponseSingle responseSingle;
|
|
||||||
private VMPlay vmPlay;
|
|
||||||
|
|
||||||
|
|
||||||
private Handler mHandler;
|
|
||||||
private Runnable mRunnable;
|
|
||||||
|
|
||||||
|
|
||||||
private AdapterPlayList adapterPlayList;
|
|
||||||
|
|
||||||
|
|
||||||
//播放列表ui初始化
|
|
||||||
private boolean initPlayList = false;
|
|
||||||
|
|
||||||
private GradientDrawable gradientDrawable;
|
|
||||||
private int lighterColor, darkerColor;
|
|
||||||
|
|
||||||
// 0 播放列表请求失败 1 立即播放的歌曲请求失败 2 封面图加载失败
|
|
||||||
private int netError = 0;
|
|
||||||
|
|
||||||
|
|
||||||
// 请求失败的立即播放的歌曲信息
|
|
||||||
private CustomerUrlInfo mCustomerUrlInfo;
|
|
||||||
private int mEnterType;
|
|
||||||
|
|
||||||
|
|
||||||
//-------单曲进入播放列表接口请求需要的参数
|
|
||||||
private String playlistId, videoId, params, musicVideoType = "";
|
|
||||||
//-------单曲进入播放列表接口请求需要的参数
|
|
||||||
|
|
||||||
private int mDefaultPlayStartIndex = 0;
|
|
||||||
|
|
||||||
|
|
||||||
private int[] imageStates = {
|
|
||||||
R.drawable.icon_looper_no,
|
|
||||||
R.drawable.icon_looper_1,
|
|
||||||
R.drawable.icon_looper
|
|
||||||
};
|
|
||||||
|
|
||||||
//0 不循环、1 列表循环、2 单曲循环、
|
|
||||||
private int currentMode = 0;
|
|
||||||
|
|
||||||
private List<BoxDownloadSong> downloadSongList = new ArrayList<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActivityPlayBinding getViewBinding() {
|
|
||||||
return ActivityPlayBinding.inflate(getLayoutInflater());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreateInit() {
|
|
||||||
// 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();
|
|
||||||
|
|
||||||
CommonUtils.LogMsg("--------mEnterType=" + mEnterType);
|
|
||||||
switch (mEnterType) {
|
|
||||||
case MyValue.TYPE_ENTER_SOURCE_SINGLE:
|
|
||||||
// 0--首页单曲进入
|
|
||||||
updateMediaPlayList();
|
|
||||||
responseSingle = (ResponseSingle) intent.getSerializableExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER);
|
|
||||||
playlistId = responseSingle.getPlaylistId();
|
|
||||||
videoId = responseSingle.getVideoId();
|
|
||||||
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
|
|
||||||
public void onChanged(List<ResponsePlayListInfo> listInfos) {
|
|
||||||
vmApplication.reSetPlayList(listInfos);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case MyValue.TYPE_ENTER_SOURCE_CATEGORY:
|
|
||||||
// 1--首页音乐分类合集列表进入
|
|
||||||
|
|
||||||
updateMediaPlayList();
|
|
||||||
ResponsePlayListInfo playListInfo = (ResponsePlayListInfo) intent.getSerializableExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST);
|
|
||||||
mDefaultPlayStartIndex = intent.getIntExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST_INDEX, mDefaultPlayStartIndex);
|
|
||||||
videoId = playListInfo.getVideoId();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MyValue.TYPE_ENTER_SOURCE_MV:
|
|
||||||
// 2--首页单个视频mv进入
|
|
||||||
|
|
||||||
updateMediaPlayList();
|
|
||||||
ResponseCategory responseCategory = (ResponseCategory) intent.getSerializableExtra(MyValue.KEY_PLAY_ACTIVITY_MV);
|
|
||||||
videoId = responseCategory.getVideoId();
|
|
||||||
playlistId = responseCategory.getPlayListId();
|
|
||||||
params = responseCategory.getParams();
|
|
||||||
musicVideoType = responseCategory.getMusicVideoType();
|
|
||||||
vmPlay.getPlayMusicList(playlistId, videoId, params, musicVideoType);
|
|
||||||
vmPlay.playList.observe(this, new Observer<List<ResponsePlayListInfo>>() {
|
|
||||||
@Override
|
|
||||||
public void onChanged(List<ResponsePlayListInfo> listInfos) {
|
|
||||||
vmApplication.reSetPlayList(listInfos);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MyValue.TYPE_ENTER_PANEL:
|
|
||||||
// 3--控制面板进入
|
|
||||||
MediaItem curMediaItem = mediaControllerManager.getCurMediaItem();
|
|
||||||
loadInfo(curMediaItem);
|
|
||||||
mHandler.post(mRunnable);
|
|
||||||
vb.progressBarLoading.setVisibility(View.GONE);
|
|
||||||
vb.btnPlay.setSelected(mediaControllerManager.getIsPlaying());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MyValue.TYPE_ENTER_LIKE:
|
|
||||||
// 4--从喜爱歌曲进入
|
|
||||||
updateMediaPlayList();
|
|
||||||
videoId = intent.getStringExtra(MyValue.KEY_PLAY_VIDEO_ID);
|
|
||||||
mDefaultPlayStartIndex = intent.getIntExtra(MyValue.KEY_PLAY_INDEX, 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) {
|
|
||||||
if (customerUrlInfo.isNeedPlayNow() && customerUrlInfo.getPlayUrl() == null) {
|
|
||||||
// TODO: 2024/9/26 需要马上播放这首歌曲,但是此次网络请求失败
|
|
||||||
CommonUtils.LogErrorMsg("-------------需要马上播放这首歌曲,但是此次网络请求失败");
|
|
||||||
updateErrorLayout(getString(R.string.song_loading_failed), true);
|
|
||||||
netError = 1;
|
|
||||||
mCustomerUrlInfo = customerUrlInfo;
|
|
||||||
initShowPlayList(false);
|
|
||||||
vb.progressBarLoading.setVisibility(View.GONE);
|
|
||||||
mediaControllerManager.pause();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int second = customerUrlInfo.getPlayMusicIndex();
|
|
||||||
if (customerUrlInfo.isNeedPlayNow()) {
|
|
||||||
mediaControllerManager.playPositionMusic(second);
|
|
||||||
// mediaControllerManager.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新播放列表
|
|
||||||
*/
|
|
||||||
private void updateMediaPlayList() {
|
|
||||||
vmApplication.playList.observe(this, new Observer<List<ResponsePlayListInfo>>() {
|
|
||||||
@Override
|
|
||||||
public void onChanged(List<ResponsePlayListInfo> playList) {
|
|
||||||
if (playList == null) {
|
|
||||||
CommonUtils.LogErrorMsg("--------更新-playList null");
|
|
||||||
netError = 0;
|
|
||||||
updateErrorLayout(getString(R.string.playList_loading_failed), true);
|
|
||||||
vb.progressBarLoading.setVisibility(View.GONE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CommonUtils.LogMsg("--------更新-playList " + playList.size() + "--videoId=" + videoId);
|
|
||||||
if (playList.size() > 0) {
|
|
||||||
updateErrorLayout(null, false);
|
|
||||||
setPlayListAndGetUrl(playList, videoId, mDefaultPlayStartIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateErrorLayout(String msg, boolean isShow) {
|
|
||||||
if (isShow)
|
|
||||||
vb.layoutError.linearRetry.setVisibility(View.VISIBLE);
|
|
||||||
else vb.layoutError.linearRetry.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
if (msg != null && !msg.isEmpty()) {
|
|
||||||
vb.layoutError.tvErrorMsg.setText(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置播放列表,并请求当前需要播放的音乐url
|
|
||||||
*
|
|
||||||
* @param list
|
|
||||||
* @param id
|
|
||||||
* @param index
|
|
||||||
*/
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
private void setPlayListAndGetUrl(List<ResponsePlayListInfo> list, String id, int index) {
|
|
||||||
mediaControllerManager.resetPlayList();
|
|
||||||
MyMediaControllerManager.getInstance().setPlayList(list);
|
|
||||||
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)
|
|
||||||
private void initPlayerView() {
|
|
||||||
vb.playerView.setShowRewindButton(false);
|
|
||||||
vb.playerView.setShowPreviousButton(false);
|
|
||||||
vb.playerView.setPlayer(mediaControllerManager.getMediaController());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initMediaController() {
|
|
||||||
int repeatMode = mediaControllerManager.getRepeatMode();
|
|
||||||
CommonUtils.LogMsg("-------------repeatMode=" + repeatMode);
|
|
||||||
vb.btnLoop.setImageResource(imageStates[repeatMode]);
|
|
||||||
mediaControllerManager.addListener(vmApplication, new MediaControllerListener() {
|
|
||||||
@Override
|
|
||||||
public void onPlayStatus(int playStatus) {
|
|
||||||
|
|
||||||
switch (playStatus) {
|
|
||||||
case Player.STATE_IDLE:
|
|
||||||
CommonUtils.LogMsg("-------------IDLE");
|
|
||||||
break;
|
|
||||||
case Player.STATE_BUFFERING:
|
|
||||||
//快进没有缓冲的时候触发
|
|
||||||
vb.btnPlay.setSelected(false);
|
|
||||||
// vb.progressBarLoading.setVisibility(View.VISIBLE);
|
|
||||||
CommonUtils.LogMsg("-------------缓冲");
|
|
||||||
break;
|
|
||||||
case Player.STATE_READY:
|
|
||||||
vb.btnPlay.setSelected(true);
|
|
||||||
mHandler.post(mRunnable);
|
|
||||||
vb.progressBarLoading.setVisibility(View.GONE);
|
|
||||||
CommonUtils.LogMsg("-------------准备");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Player.STATE_ENDED:
|
|
||||||
//播放完成
|
|
||||||
vb.btnPlay.setSelected(false);
|
|
||||||
CommonUtils.LogMsg("------------- 播放完成");
|
|
||||||
mHandler.removeCallbacks(mRunnable); // 停止更新
|
|
||||||
updatePlayComplete();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MyValue.PLAY_STATUS_CODE_PAUSE:
|
|
||||||
CommonUtils.LogMsg("------------- 暂停");
|
|
||||||
vb.btnPlay.setSelected(false);
|
|
||||||
vb.layoutPlayList.imPlay.setSelected(false);
|
|
||||||
break;
|
|
||||||
case MyValue.PLAY_STATUS_CODE_PLAYING:
|
|
||||||
|
|
||||||
CommonUtils.LogMsg("------------- 播放ing getCurIndex=" + mediaControllerManager.getCurIndex());
|
|
||||||
vb.progressBarLoading.setVisibility(View.GONE);
|
|
||||||
updateErrorLayout(null, false);
|
|
||||||
vb.btnPlay.setSelected(true);
|
|
||||||
vb.layoutPlayList.imPlay.setSelected(true);
|
|
||||||
break;
|
|
||||||
case MyValue.PLAY_STATUS_CODE_ERROR:
|
|
||||||
vb.progressBarLoading.setVisibility(View.GONE);
|
|
||||||
int currentMediaItemIndex = mediaControllerManager.getMediaController().getCurrentMediaItemIndex();
|
|
||||||
CommonUtils.LogMsg("------------- 播放错误 currentMediaItemIndex=" + currentMediaItemIndex);
|
|
||||||
mediaControllerManager.playPositionMusic(currentMediaItemIndex);
|
|
||||||
// TODO: 2024/10/16
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestNextUri(String videoId, int playListIndex, boolean playNow) {
|
|
||||||
if (playNow) {
|
|
||||||
// vb.progressBarLoading.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
vmPlay.getPlayUrl(videoId, playListIndex, playNow);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onChangeMusic(MediaItem mediaItem) {
|
|
||||||
CommonUtils.LogMsg("歌曲切换-" + mediaItem.mediaMetadata.title + "---id=" + mediaItem.mediaId);
|
|
||||||
loadInfo(mediaItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onInitClick() {
|
|
||||||
vb.btnPlay.setOnClickListener(this);
|
|
||||||
vb.playProgress.setOnSeekBarChangeListener(this);
|
|
||||||
vb.btnNext.setOnClickListener(this);
|
|
||||||
vb.btnPrevious.setOnClickListener(this);
|
|
||||||
vb.imBack.setOnClickListener(this);
|
|
||||||
vb.btnMusicList.setOnClickListener(this);
|
|
||||||
vb.layoutError.tvRetry.setOnClickListener(this);
|
|
||||||
vb.btnLoop.setOnClickListener(this);
|
|
||||||
vb.layoutLike.setOnClickListener(this);
|
|
||||||
vb.layoutDownload.setOnClickListener(this);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新播放进度Ui、缓冲进度
|
|
||||||
*/
|
|
||||||
private void updatePlaybackProgress() {
|
|
||||||
// 获取当前播放位置
|
|
||||||
long contentPos = mediaControllerManager.getContentPos();
|
|
||||||
long bufferPos = mediaControllerManager.getBufferPos();
|
|
||||||
|
|
||||||
|
|
||||||
String s = CommonUtils.convertMillisToTime(contentPos);
|
|
||||||
vb.tvCurrent.setText(s);
|
|
||||||
vb.playProgress.setProgress((int) contentPos);
|
|
||||||
vb.progressBarBuffer.setProgress((int) bufferPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 播放完成 更新播放进度Ui
|
|
||||||
*/
|
|
||||||
private void updatePlayComplete() {
|
|
||||||
vb.tvCurrent.setText(vb.tvDuration.getText().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加载当前播放歌曲信息
|
|
||||||
*/
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
private void loadInfo(MediaItem mediaItem) {
|
|
||||||
MediaMetadata mediaMetadata = mediaItem.mediaMetadata;
|
|
||||||
CommonUtils.LogMsg("--------------加载当前播放歌曲信息 title=" + mediaMetadata.title);
|
|
||||||
if (mediaMetadata.artworkUri != null) {
|
|
||||||
loadCovert(mediaMetadata.artworkUri.toString());
|
|
||||||
}
|
|
||||||
vb.tvSongName.setText(mediaMetadata.title);
|
|
||||||
vb.tvSingerName.setText(mediaMetadata.artist);
|
|
||||||
vb.tvDuration.setText(mediaMetadata.description);
|
|
||||||
|
|
||||||
if (mediaMetadata.durationMs != null) {
|
|
||||||
long durationMs = mediaMetadata.durationMs;
|
|
||||||
vb.playProgress.setMax((int) durationMs);
|
|
||||||
vb.progressBarBuffer.setMax((int) durationMs);
|
|
||||||
}
|
|
||||||
if (vb.layoutPlayList.linearLayout.getVisibility() == View.VISIBLE) {
|
|
||||||
updatePlayListUi();
|
|
||||||
}
|
|
||||||
|
|
||||||
//刷新当前歌曲的喜爱状态
|
|
||||||
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()
|
|
||||||
.load(url)
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
// netError = 2;
|
|
||||||
// vb.tvErrorMsg.setText(getString(R.string.image_loading_failed));
|
|
||||||
// vb.linearRetry.setVisibility(View.VISIBLE);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
vb.imCovert.setImageDrawable(resource);
|
|
||||||
CommonUtils.getMainColor(resource, new onImageColorListener() {
|
|
||||||
@Override
|
|
||||||
public void onImageColor(int color) {
|
|
||||||
if (color == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lighterColor = CommonUtils.adjustBrightness(color, 0.8f); // 比原始颜色亮 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;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.preload();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void initProgressHandler() {
|
|
||||||
mHandler = new Handler();
|
|
||||||
mRunnable = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
updatePlaybackProgress();
|
|
||||||
mHandler.postDelayed(this, 1000);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFullScreen() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean statusBarLight() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean showPanel() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (v.equals(vb.btnPlay)) {
|
|
||||||
vb.btnPlay.setSelected(!vb.btnPlay.isSelected());
|
|
||||||
if (vb.btnPlay.isSelected()) {
|
|
||||||
mediaControllerManager.play();
|
|
||||||
} else {
|
|
||||||
mediaControllerManager.pause();
|
|
||||||
}
|
|
||||||
} else if (v.equals(vb.btnNext)) {
|
|
||||||
mediaControllerManager.playNext(new onPlayNextListener() {
|
|
||||||
@Override
|
|
||||||
public void onPlayNext(boolean hasNext) {
|
|
||||||
if (!hasNext) {
|
|
||||||
Toast.makeText(PlayActivity.this, getString(R.string.no_next_song_yet), Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (v.equals(vb.btnPrevious)) {
|
|
||||||
mediaControllerManager.playPrevious();
|
|
||||||
} else if (v.equals(vb.imBack)) {
|
|
||||||
finish();
|
|
||||||
} else if (v.equals(vb.btnMusicList)) {
|
|
||||||
initShowPlayList(true);
|
|
||||||
} else if (v.equals(vb.layoutPlayList.imPlay)) {
|
|
||||||
vb.layoutPlayList.imPlay.setSelected(!vb.layoutPlayList.imPlay.isSelected());
|
|
||||||
if (vb.layoutPlayList.imPlay.isSelected()) {
|
|
||||||
mediaControllerManager.play();
|
|
||||||
} else {
|
|
||||||
mediaControllerManager.pause();
|
|
||||||
}
|
|
||||||
if (adapterPlayList != null) {
|
|
||||||
adapterPlayList.updateCurMusicAnimation();
|
|
||||||
}
|
|
||||||
} else if (v.equals(vb.layoutError.tvRetry)) {
|
|
||||||
//重试按钮
|
|
||||||
updateErrorLayout(null, false);
|
|
||||||
switch (netError) {
|
|
||||||
case 0:
|
|
||||||
switch (mEnterType) {
|
|
||||||
case MyValue.TYPE_ENTER_SOURCE_SINGLE:
|
|
||||||
vmPlay.getPlayMusicList(playlistId, videoId, params, musicVideoType);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
vb.progressBarLoading.setVisibility(View.VISIBLE);
|
|
||||||
int curIndex = mediaControllerManager.getCurIndex();
|
|
||||||
|
|
||||||
String curVideoId = mediaControllerManager.getCurVideoId();
|
|
||||||
|
|
||||||
String videoId1 = mCustomerUrlInfo.getVideoId();
|
|
||||||
int playMusicIndex = mCustomerUrlInfo.getPlayMusicIndex();
|
|
||||||
|
|
||||||
CommonUtils.LogMsg("-------重试 curIndex=" + curIndex + "----curVideoId=" + curVideoId + "---videoId1=" + videoId1 + "---playMusicIndex=" + playMusicIndex);
|
|
||||||
|
|
||||||
vmPlay.getPlayUrl(mCustomerUrlInfo.getVideoId(), mCustomerUrlInfo.getPlayMusicIndex(), true);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
MediaItem curMediaItem = mediaControllerManager.getCurMediaItem();
|
|
||||||
MediaMetadata mediaMetadata = curMediaItem.mediaMetadata;
|
|
||||||
if (mediaMetadata.artworkUri != null) {
|
|
||||||
loadCovert(mediaMetadata.artworkUri.toString());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (v.equals(vb.btnLoop)) {
|
|
||||||
currentMode = (currentMode + 1) % imageStates.length;
|
|
||||||
vb.btnLoop.setImageResource(imageStates[currentMode]);
|
|
||||||
CommonUtils.LogMsg("----currentMode=" + currentMode);
|
|
||||||
mediaControllerManager.setMode(currentMode);
|
|
||||||
} else if (v.equals(vb.layoutLike)) {
|
|
||||||
boolean selected = vb.imLike.isSelected();
|
|
||||||
vb.imLike.setSelected(!selected);
|
|
||||||
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(),
|
|
||||||
mediaMetadata.artist.toString(),
|
|
||||||
curMediaItem.mediaId,
|
|
||||||
String.valueOf(mediaMetadata.artworkUri),
|
|
||||||
mediaMetadata.durationMs, mediaMetadata.description.toString());
|
|
||||||
if (newSelect) {
|
|
||||||
ObjectBoxManager.insertOrUpdateLike(boxLikeSong);
|
|
||||||
} else {
|
|
||||||
ObjectBoxManager.deleteLike(boxLikeSong);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} 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) {
|
|
||||||
Gson gson = new Gson();
|
|
||||||
String info = gson.toJson(curMediaItemInfo);
|
|
||||||
byte[] data = info.getBytes(StandardCharsets.UTF_8);
|
|
||||||
|
|
||||||
String videoId1 = curMediaItemInfo.getVideoId();
|
|
||||||
CommonUtils.LogMsg("----------------开始下载 id=" + videoId1);
|
|
||||||
DownloadRequest downloadRequest = new DownloadRequest.Builder(videoId1, Uri.parse(curMediaItemInfo.getVideoUrl()))
|
|
||||||
.setMimeType("video/mp4")
|
|
||||||
.setData(data)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// 启动 DownloadService 进行下载
|
|
||||||
DownloadService.sendAddDownload(
|
|
||||||
this,
|
|
||||||
MyDownloadService.class, // 上面定义的下载服务类
|
|
||||||
downloadRequest,
|
|
||||||
true // 是否在前台运行
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
private BoxDownloadSong getCurMediaItemInfo() {
|
|
||||||
MediaItem curMediaItem = mediaControllerManager.getCurMediaItem();
|
|
||||||
if (curMediaItem == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
MediaMetadata mediaMetadata = curMediaItem.mediaMetadata;
|
|
||||||
if (mediaMetadata.title == null || mediaMetadata.artist == null || mediaMetadata.description == null
|
|
||||||
|| mediaMetadata.durationMs == null || curMediaItem.localConfiguration == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
BoxDownloadSong boxDownloadSong = new BoxDownloadSong();
|
|
||||||
boxDownloadSong.setVideoId(curMediaItem.mediaId);
|
|
||||||
boxDownloadSong.setCovert(String.valueOf(mediaMetadata.artworkUri));
|
|
||||||
boxDownloadSong.setSongName((String) mediaMetadata.title);
|
|
||||||
boxDownloadSong.setSingerName((String) mediaMetadata.artist);
|
|
||||||
boxDownloadSong.setDuration((String) mediaMetadata.description);
|
|
||||||
boxDownloadSong.setDurationMs(mediaMetadata.durationMs);
|
|
||||||
boxDownloadSong.setVideoUrl(String.valueOf(curMediaItem.localConfiguration.uri));
|
|
||||||
|
|
||||||
return boxDownloadSong;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 控制播放列表的显示
|
|
||||||
*
|
|
||||||
* @param show
|
|
||||||
*/
|
|
||||||
private void initShowPlayList(boolean show) {
|
|
||||||
if (show) {
|
|
||||||
Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_up);
|
|
||||||
vb.layoutPlayList.linearLayout.startAnimation(animation);
|
|
||||||
vb.layoutPlayList.linearLayout.setVisibility(View.VISIBLE);
|
|
||||||
vb.contentLayout.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
if (!initPlayList) {
|
|
||||||
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 播放列表显示
|
|
||||||
vb.layoutPlayList.recyclerList.setAdapter(adapterPlayList);
|
|
||||||
vb.layoutPlayList.imPlay.setOnClickListener(this);
|
|
||||||
initPlayList = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
updatePlayListUi();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
vb.rootLayout.setBackground(gradientDrawable);
|
|
||||||
vb.contentLayout.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_down);
|
|
||||||
vb.layoutPlayList.linearLayout.startAnimation(animation);
|
|
||||||
vb.layoutPlayList.linearLayout.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新播放列表的显示
|
|
||||||
*/
|
|
||||||
private void updatePlayListUi() {
|
|
||||||
CommonUtils.LogMsg("----------更新播放列表的显示");
|
|
||||||
|
|
||||||
MediaItem currentMediaItem = mediaControllerManager.getCurMediaItem();
|
|
||||||
if (currentMediaItem != null) {
|
|
||||||
if (adapterPlayList != null) {
|
|
||||||
adapterPlayList.setCurVideId(currentMediaItem.mediaId);
|
|
||||||
}
|
|
||||||
Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri;
|
|
||||||
vb.layoutPlayList.topSongName.setText(currentMediaItem.mediaMetadata.title);
|
|
||||||
vb.layoutPlayList.topSingerName.setText(currentMediaItem.mediaMetadata.artist);
|
|
||||||
updatePlayListColor();
|
|
||||||
Glide.with(MusicApplication.myApplication)
|
|
||||||
.asDrawable()
|
|
||||||
// .apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10))))
|
|
||||||
.load(artworkUri)
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into(vb.layoutPlayList.topIm);
|
|
||||||
}
|
|
||||||
vb.layoutPlayList.imPlay.setSelected(mediaControllerManager.getIsPlaying());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updatePlayListColor() {
|
|
||||||
vb.layoutPlayList.topLayout.setBackgroundColor(darkerColor);
|
|
||||||
GradientDrawable gradientDrawable = new GradientDrawable(
|
|
||||||
GradientDrawable.Orientation.TOP_BOTTOM,
|
|
||||||
new int[]{darkerColor, darkerColor}
|
|
||||||
);
|
|
||||||
vb.rootLayout.setBackground(gradientDrawable);
|
|
||||||
Drawable newDrawable = CommonUtils.getNewDrawable(lighterColor, 24f, 24f, 0, 0);
|
|
||||||
vb.layoutPlayList.listLayout.setBackground(newDrawable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
if (mHandler != null && mRunnable != null)
|
|
||||||
mHandler.removeCallbacks(mRunnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackPressed() {
|
|
||||||
if (vb.layoutPlayList.linearLayout.getVisibility() == View.VISIBLE) {
|
|
||||||
initShowPlayList(false);
|
|
||||||
} else {
|
|
||||||
super.onBackPressed(); // 调用系统默认的返回行为
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
|
||||||
if (fromUser) {
|
|
||||||
mediaControllerManager.getMediaController().seekTo(progress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,169 +0,0 @@
|
|||||||
package com.hi.music.player.ui.activity;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.lifecycle.Observer;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.DataSource;
|
|
||||||
import com.bumptech.glide.load.engine.GlideException;
|
|
||||||
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.hi.music.player.MusicApplication;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.adapter.AdapterResult;
|
|
||||||
import com.hi.music.player.api.HomeItemClickListener;
|
|
||||||
import com.hi.music.player.databinding.ActivityResultListBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.helper.MyValue;
|
|
||||||
import com.hi.music.player.javabean.response.ResponseResult;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseResultListChild;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
|
||||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMCategoryList;
|
|
||||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMResultList;
|
|
||||||
|
|
||||||
public class ResultListActivity extends BaseActivity<ActivityResultListBinding> implements HomeItemClickListener {
|
|
||||||
private VMResultList vm;
|
|
||||||
private String key;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActivityResultListBinding getViewBinding() {
|
|
||||||
return ActivityResultListBinding.inflate(getLayoutInflater());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreateInit() {
|
|
||||||
vm = getActivityScopeViewModel(VMResultList.class);
|
|
||||||
key = getIntent().getStringExtra(MyValue.KEY_SEARCH_RESULT_BROWSER_ID);
|
|
||||||
vm.getList(key);
|
|
||||||
|
|
||||||
vm.data.observe(this, new Observer<ResponseResult>() {
|
|
||||||
@Override
|
|
||||||
public void onChanged(ResponseResult responseResult) {
|
|
||||||
vb.pbLoading.setVisibility(View.GONE);
|
|
||||||
if (responseResult == null) {
|
|
||||||
vb.layoutError.linearRetry.setVisibility(View.VISIBLE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vb.pbLoading.setVisibility(View.GONE);
|
|
||||||
loadInfo(responseResult);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadInfo(ResponseResult result) {
|
|
||||||
Glide.with(this)
|
|
||||||
.asDrawable()
|
|
||||||
.load(result.getMainCovert())
|
|
||||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.listener(new RequestListener<Drawable>() {
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
|
||||||
CommonUtils.LogMsg(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into(vb.covert);
|
|
||||||
vb.mainTitle.setText(result.getMainTitle());
|
|
||||||
AdapterResult adapterResult = new AdapterResult(this);
|
|
||||||
adapterResult.setHomeItemClickListener(this);
|
|
||||||
adapterResult.setData(result.getList());
|
|
||||||
vb.listRecycler.setAdapter(adapterResult);
|
|
||||||
vb.listRecycler.setLayoutManager(new LinearLayoutManager(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onInitClick() {
|
|
||||||
vb.imBack.setOnClickListener(this);
|
|
||||||
vb.layoutError.tvRetry.setOnClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFullScreen() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean statusBarLight() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean showPanel() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (v.equals(vb.imBack)) {
|
|
||||||
finish();
|
|
||||||
} else if (v.equals(vb.layoutError.tvRetry)) {
|
|
||||||
vm.getList(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClickResultSong(ResponseResultListChild child, int index) {
|
|
||||||
String videoId = child.getVideoId();
|
|
||||||
String playListId = child.getPlayListId();
|
|
||||||
String browserId = child.getBrowserId();
|
|
||||||
String pageType = child.getPageType();
|
|
||||||
String thumbnail = child.getThumbnail();
|
|
||||||
String songName = child.getSongName();
|
|
||||||
String subTitle = child.getSubTitle();
|
|
||||||
|
|
||||||
if (videoId != null && !videoId.isEmpty()) {
|
|
||||||
ResponseSingle responseSingle = new ResponseSingle();
|
|
||||||
responseSingle.setSongTitle(songName);
|
|
||||||
responseSingle.setSingerHead(thumbnail);
|
|
||||||
responseSingle.setVideoId(videoId);
|
|
||||||
responseSingle.setPlaylistId(playListId);
|
|
||||||
Intent intent = new Intent(this, PlayActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER, responseSingle);
|
|
||||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST_INDEX, index);
|
|
||||||
CommonUtils.LogMsg("-------------index=" + index);
|
|
||||||
startActivity(intent);
|
|
||||||
} else {
|
|
||||||
switch (pageType) {
|
|
||||||
case "MUSIC_PAGE_TYPE_ALBUM":
|
|
||||||
//专辑
|
|
||||||
CommonUtils.LogMsg("------------专辑-index=" + index + "--subTitle=" + subTitle);
|
|
||||||
case "MUSIC_PAGE_TYPE_PLAYLIST":
|
|
||||||
//精选
|
|
||||||
Intent intent1 = new Intent(this, CategoryListActivity.class);
|
|
||||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_TYPE, pageType);
|
|
||||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_SINGER_NAME, subTitle);
|
|
||||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_BROWSER_ID, browserId);
|
|
||||||
startActivity(intent1);
|
|
||||||
break;
|
|
||||||
case "MUSIC_PAGE_TYPE_ARTIST":
|
|
||||||
//粉丝可能还喜欢
|
|
||||||
Intent intent = new Intent(this, ResultListActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_SEARCH_RESULT_BROWSER_ID, browserId);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,168 +0,0 @@
|
|||||||
package com.hi.music.player.ui.fragmnt;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.RestrictionsManager;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
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.databinding.FragmentHomeBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.helper.MyValue;
|
|
||||||
import com.hi.music.player.javabean.response.ResponseHome;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseCategory;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseHomeChild;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
|
||||||
import com.hi.music.player.network.RetrofitManager;
|
|
||||||
import com.hi.music.player.ui.activity.CategoryListActivity;
|
|
||||||
import com.hi.music.player.ui.activity.PlayActivity;
|
|
||||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMHome;
|
|
||||||
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import okhttp3.ResponseBody;
|
|
||||||
|
|
||||||
public class HomeFragment extends BaseFragment<FragmentHomeBinding> implements HomeItemClickListener {
|
|
||||||
|
|
||||||
|
|
||||||
private VMHome vmHome;
|
|
||||||
|
|
||||||
|
|
||||||
private int requestCount = 1;
|
|
||||||
|
|
||||||
private int totalPage = 3;
|
|
||||||
|
|
||||||
|
|
||||||
private List<ResponseHomeChild> childList = new ArrayList<>();
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected FragmentHomeBinding getFragmentVb() {
|
|
||||||
// 返回正确的 ViewBinding 实例
|
|
||||||
return FragmentHomeBinding.inflate(getLayoutInflater());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initView() {
|
|
||||||
|
|
||||||
// //标题导航栏颜色设置
|
|
||||||
// Vb.toolbar.setTitleTextColor(getResources().getColor(R.color.white));
|
|
||||||
AdapterHome adapterHome = new AdapterHome();
|
|
||||||
adapterHome.setHomeItemClickListener(this);
|
|
||||||
|
|
||||||
|
|
||||||
vmHome = getFragmentScopeViewModel(VMHome.class);
|
|
||||||
adapterHome.addLoadingFooter();
|
|
||||||
vmHome.getHome();
|
|
||||||
Vb.tvRetry.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
adapterHome.addLoadingFooter();
|
|
||||||
vmHome.getHome();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
vmHome.data.observe(getViewLifecycleOwner(), new Observer<ResponseHome>() {
|
|
||||||
@Override
|
|
||||||
public void onChanged(ResponseHome responseHome) {
|
|
||||||
if (responseHome == null) {
|
|
||||||
adapterHome.removeLoadingFooter();
|
|
||||||
requestCount--;
|
|
||||||
if(requestCount == 0){
|
|
||||||
Vb.layoutError.setVisibility(View.VISIBLE);
|
|
||||||
Vb.recyclerSongOfTheDay.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Vb.layoutError.setVisibility(View.GONE);
|
|
||||||
Vb.recyclerSongOfTheDay.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
List<ResponseHomeChild> childList1 = responseHome.getChildList();
|
|
||||||
if (childList1 == null) return;
|
|
||||||
childList.addAll(childList1);
|
|
||||||
adapterHome.removeLoadingFooter();
|
|
||||||
adapterHome.addData(childList1);
|
|
||||||
if (requestCount == 1) {
|
|
||||||
adapterHome.addLoadingFooter();
|
|
||||||
vmHome.getHomeMore();
|
|
||||||
requestCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Vb.recyclerSongOfTheDay.setLayoutManager(new LinearLayoutManager(requireContext()));
|
|
||||||
Vb.recyclerSongOfTheDay.setAdapter(adapterHome);
|
|
||||||
Vb.recyclerSongOfTheDay.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
|
||||||
@Override
|
|
||||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
|
||||||
super.onScrolled(recyclerView, dx, dy);
|
|
||||||
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
|
||||||
if (layoutManager != null && layoutManager.findLastVisibleItemPosition() == childList.size() - 1) {
|
|
||||||
if (requestCount < totalPage && !adapterHome.isLoadingAdded()) {
|
|
||||||
CommonUtils.LogMsg("------loadmore--");
|
|
||||||
adapterHome.addLoadingFooter();
|
|
||||||
vmHome.getHomeMore();
|
|
||||||
requestCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClickItemSinger(ResponseSingle data) {
|
|
||||||
FragmentActivity activity = getActivity();
|
|
||||||
if (activity != null) {
|
|
||||||
Intent intent = new Intent(activity, PlayActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER, data);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClickItemCategory(ResponseCategory data) {
|
|
||||||
FragmentActivity activity = getActivity();
|
|
||||||
if (activity != null) {
|
|
||||||
String pageType = data.getPageType();
|
|
||||||
String browseId = data.getBrowseId();
|
|
||||||
String twoSubtitle = data.getTwoSubtitle();
|
|
||||||
if (pageType.equals(MyValue.PAGE_TYPE_MV)||pageType.equals(MyValue.PAGE_TYPE_MV_LIST)) {
|
|
||||||
Intent intent = new Intent(activity, PlayActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_MV, data);
|
|
||||||
intent.putExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_SOURCE_MV);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Intent intent = new Intent(activity, CategoryListActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_CATEGORY_LIST_TYPE, pageType);
|
|
||||||
intent.putExtra(MyValue.KEY_CATEGORY_LIST_SINGER_NAME, twoSubtitle);
|
|
||||||
intent.putExtra(MyValue.KEY_CATEGORY_LIST_BROWSER_ID, browseId);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,143 +0,0 @@
|
|||||||
package com.hi.music.player.ui.fragmnt;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.util.Pair;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.annotation.OptIn;
|
|
||||||
import androidx.lifecycle.Observer;
|
|
||||||
import androidx.media3.common.util.UnstableApi;
|
|
||||||
import androidx.media3.exoplayer.offline.Download;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.hi.music.player.R;
|
|
||||||
import com.hi.music.player.api.LikeSongListener;
|
|
||||||
import com.hi.music.player.databinding.FragmentProfileBinding;
|
|
||||||
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.media3.MyDownloadService;
|
|
||||||
import com.hi.music.player.objectbox.ObjectBoxManager;
|
|
||||||
import com.hi.music.player.ui.activity.LikeSongActivity;
|
|
||||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import io.objectbox.reactive.DataSubscription;
|
|
||||||
|
|
||||||
|
|
||||||
public class ProfileFragment extends BaseFragment<FragmentProfileBinding> implements View.OnClickListener {
|
|
||||||
|
|
||||||
|
|
||||||
private DataSubscription dataSubscription;
|
|
||||||
|
|
||||||
private int likeSongCount = 0;
|
|
||||||
private int downloadSongCount = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected FragmentProfileBinding getFragmentVb() {
|
|
||||||
return FragmentProfileBinding.inflate(getLayoutInflater());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class)
|
|
||||||
@Override
|
|
||||||
protected void initView() {
|
|
||||||
|
|
||||||
dataSubscription = ObjectBoxManager.setLikeDataListener(new LikeSongListener() {
|
|
||||||
@Override
|
|
||||||
public void onLikeSongChange(List<BoxLikeSong> data) {
|
|
||||||
CommonUtils.LogMsg("------onLikeSongChange data=" + data.size());
|
|
||||||
int size = data.size();
|
|
||||||
likeSongCount = size;
|
|
||||||
Vb.tvLikeSize.setText(String.format(getString(R.string.like_song), size));
|
|
||||||
if (size == 0) {
|
|
||||||
Vb.likeCovert.setVisibility(View.GONE);
|
|
||||||
Vb.likeDefault.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
Vb.likeCovert.setVisibility(View.VISIBLE);
|
|
||||||
Vb.likeDefault.setVisibility(View.GONE);
|
|
||||||
BoxLikeSong boxLikeSong = data.get(size - 1);
|
|
||||||
Glide.with(requireContext())
|
|
||||||
.asDrawable()
|
|
||||||
.load(boxLikeSong.getCovert())
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.error(R.mipmap.im_placeholder)
|
|
||||||
.into(Vb.likeCovert);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
MyDownloadService.updateDownloadUi(vmApplication);
|
|
||||||
|
|
||||||
vmApplication.downloadData.observe(getViewLifecycleOwner(), new Observer<List<Download>>() {
|
|
||||||
@Override
|
|
||||||
public void onChanged(List<Download> downloads) {
|
|
||||||
int size = downloads.size();
|
|
||||||
Vb.tvDownloadSize.setText(String.format(getString(R.string.download_song), size));
|
|
||||||
downloadSongCount = size;
|
|
||||||
if (size > 0) {
|
|
||||||
Download download = downloads.get(downloads.size() - 1);
|
|
||||||
BoxDownloadSong boxDownloadSong = CommonUtils.downloadToBean(download);
|
|
||||||
|
|
||||||
Vb.downloadCovert.setVisibility(View.VISIBLE);
|
|
||||||
Vb.downloadDefault.setVisibility(View.GONE);
|
|
||||||
Glide.with(requireContext())
|
|
||||||
.asDrawable()
|
|
||||||
.load(boxDownloadSong.getCovert())
|
|
||||||
.placeholder(R.mipmap.im_placeholder)
|
|
||||||
.error(R.mipmap.im_placeholder)
|
|
||||||
.into(Vb.downloadCovert);
|
|
||||||
} else {
|
|
||||||
Vb.downloadCovert.setVisibility(View.GONE);
|
|
||||||
Vb.downloadDefault.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Vb.relayoutLike.setOnClickListener(this);
|
|
||||||
Vb.relayoutDownload.setOnClickListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStart() {
|
|
||||||
super.onStart();
|
|
||||||
CommonUtils.LogMsg("------ProfileFragment-onStart");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
if (dataSubscription != null) {
|
|
||||||
dataSubscription.cancel();
|
|
||||||
}
|
|
||||||
CommonUtils.LogMsg("------ProfileFragment-onDestroyView");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
CommonUtils.LogMsg("------ProfileFragment-onDestroy");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (v.equals(Vb.relayoutLike)) {
|
|
||||||
if (likeSongCount > 0) {
|
|
||||||
Intent intent = new Intent(requireActivity(), LikeSongActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE, MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE_LIKE);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
} else if (v.equals(Vb.relayoutDownload)) {
|
|
||||||
if (downloadSongCount > 0) {
|
|
||||||
Intent intent = new Intent(requireActivity(), LikeSongActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE, MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE_DOWNLOAD);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,230 +0,0 @@
|
|||||||
package com.hi.music.player.ui.fragmnt;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.lifecycle.Observer;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
|
|
||||||
import com.hi.music.player.adapter.AdapterSearch;
|
|
||||||
import com.hi.music.player.adapter.AdapterSuggestion;
|
|
||||||
import com.hi.music.player.api.HomeItemClickListener;
|
|
||||||
import com.hi.music.player.databinding.FragmentSearchBinding;
|
|
||||||
import com.hi.music.player.helper.CommonUtils;
|
|
||||||
import com.hi.music.player.helper.MyValue;
|
|
||||||
import com.hi.music.player.javabean.response.ResponseSearch;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseSearchChild;
|
|
||||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
|
||||||
import com.hi.music.player.ui.activity.CategoryListActivity;
|
|
||||||
import com.hi.music.player.ui.activity.PlayActivity;
|
|
||||||
import com.hi.music.player.ui.activity.ResultListActivity;
|
|
||||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMSearch;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
public class SearchFragment extends BaseFragment<FragmentSearchBinding> implements HomeItemClickListener, View.OnClickListener {
|
|
||||||
|
|
||||||
|
|
||||||
private VMSearch vmSearch;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected FragmentSearchBinding getFragmentVb() {
|
|
||||||
return FragmentSearchBinding.inflate(getLayoutInflater());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initView() {
|
|
||||||
// Vb.etSearch.requestFocus();
|
|
||||||
vmSearch = getFragmentScopeViewModel(VMSearch.class);
|
|
||||||
|
|
||||||
Vb.etSearch.addTextChangedListener(new TextWatcher() {
|
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
String input = s.toString();
|
|
||||||
if (!input.isEmpty()) {
|
|
||||||
vmSearch.getSuggestion(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Vb.etSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
|
||||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
|
||||||
String s = v.getText().toString();
|
|
||||||
CommonUtils.LogMsg("------------v=" + s);
|
|
||||||
startQuery(s);
|
|
||||||
return true;
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
initSuggestionRecycler();
|
|
||||||
initResultRecycler();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initSuggestionRecycler() {
|
|
||||||
AdapterSuggestion adapterSuggestion = new AdapterSuggestion();
|
|
||||||
Vb.recyclerSuggestion.setLayoutManager(new LinearLayoutManager(requireContext()));
|
|
||||||
Vb.recyclerSuggestion.setAdapter(adapterSuggestion);
|
|
||||||
adapterSuggestion.setHomeItemClickListener(this);
|
|
||||||
Vb.imCancel.setOnClickListener(this);
|
|
||||||
vmSearch.suggestion.observe(getViewLifecycleOwner(), new Observer<List<String>>() {
|
|
||||||
@Override
|
|
||||||
public void onChanged(List<String> strings) {
|
|
||||||
if (strings != null) {
|
|
||||||
adapterSuggestion.setData(strings);
|
|
||||||
CommonUtils.LogMsg("------------更新=");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void initResultRecycler(){
|
|
||||||
AdapterSearch adapterSearch = new AdapterSearch();
|
|
||||||
adapterSearch.setHomeItemClickListener(this);
|
|
||||||
Vb.recyclerResult.setLayoutManager(new LinearLayoutManager(requireContext()));
|
|
||||||
Vb.recyclerResult.setAdapter(adapterSearch);
|
|
||||||
vmSearch.result.observe(getViewLifecycleOwner(), new Observer<List<ResponseSearch>>() {
|
|
||||||
@Override
|
|
||||||
public void onChanged(List<ResponseSearch> responseSearches) {
|
|
||||||
Vb.pbloading.setVisibility(View.GONE);
|
|
||||||
if(responseSearches == null){
|
|
||||||
Vb.recyclerResult.setVisibility(View.GONE);
|
|
||||||
Vb.layoutError.setVisibility(View.VISIBLE);
|
|
||||||
CommonUtils.LogMsg("------------更新结果 null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Vb.recyclerResult.setVisibility(View.VISIBLE);
|
|
||||||
Vb.layoutError.setVisibility(View.GONE);
|
|
||||||
adapterSearch.setData(responseSearches);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startQuery(String query){
|
|
||||||
Vb.pbloading.setVisibility(View.VISIBLE);
|
|
||||||
Vb.recyclerSuggestion.setVisibility(View.GONE);
|
|
||||||
Vb.recyclerResult.setVisibility(View.VISIBLE);
|
|
||||||
vmSearch.getSearchResult(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClickItemSuggestion(boolean isSearch, String data) {
|
|
||||||
if (isSearch) {
|
|
||||||
startQuery(data);
|
|
||||||
} else {
|
|
||||||
Vb.etSearch.setText(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (v.equals(Vb.imCancel)) {
|
|
||||||
Vb.etSearch.setText("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//点击搜索结果的play按钮
|
|
||||||
@Override
|
|
||||||
public void onClickSearchResultBest(ResponseSearch responseSearch) {
|
|
||||||
String beastBrowserId = responseSearch.getBeastBrowserId();
|
|
||||||
String beastVideoId = responseSearch.getBeastVideoId();
|
|
||||||
String beastSongTitle = responseSearch.getBeastSongTitle();
|
|
||||||
String beastSongTCovert = responseSearch.getBeastSongTCovert();
|
|
||||||
String pageType = responseSearch.getPageType();
|
|
||||||
|
|
||||||
if(beastVideoId!= null&&!beastVideoId.isEmpty()){
|
|
||||||
CommonUtils.LogMsg("---------击搜索结果的play按钮--beastVideoId="+beastVideoId);
|
|
||||||
|
|
||||||
ResponseSingle responseSingle = new ResponseSingle();
|
|
||||||
responseSingle.setSongTitle(beastSongTitle);
|
|
||||||
responseSingle.setSingerHead(beastSongTCovert);
|
|
||||||
responseSingle.setVideoId(beastVideoId);
|
|
||||||
responseSingle.setPlaylistId("");
|
|
||||||
Intent intent = new Intent(requireActivity(), PlayActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER, responseSingle);
|
|
||||||
startActivity(intent);
|
|
||||||
}else if(beastBrowserId!= null&&!beastBrowserId.isEmpty()){
|
|
||||||
CommonUtils.LogMsg("---------击搜索结果的play按钮--pageType="+pageType);
|
|
||||||
switch (pageType){
|
|
||||||
case "MUSIC_PAGE_TYPE_PLAYLIST":
|
|
||||||
case "MUSIC_PAGE_TYPE_ALBUM":
|
|
||||||
Intent intent1 = new Intent(requireActivity(), CategoryListActivity.class);
|
|
||||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_TYPE, pageType);
|
|
||||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_SINGER_NAME, responseSearch.getBeastSongDescribe());
|
|
||||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_BROWSER_ID, beastBrowserId);
|
|
||||||
startActivity(intent1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Intent intent = new Intent(requireActivity(), ResultListActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_SEARCH_RESULT_BROWSER_ID, beastBrowserId);
|
|
||||||
startActivity(intent);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//点击搜索结果普通项
|
|
||||||
@Override
|
|
||||||
public void onClickSearchResult(ResponseSearchChild responseSearchChild) {
|
|
||||||
String browserId = responseSearchChild.getBrowserId();
|
|
||||||
String songVideoId = responseSearchChild.getSongVideoId();
|
|
||||||
String songCovert = responseSearchChild.getSongCovert();
|
|
||||||
String songTitle = responseSearchChild.getSongTitle();
|
|
||||||
String songDescribe = responseSearchChild.getSongDescribe();
|
|
||||||
|
|
||||||
if(browserId!= null&&!browserId.isEmpty()){
|
|
||||||
String pageType = responseSearchChild.getPageType();
|
|
||||||
CommonUtils.LogMsg("---------点击搜索结果--pageType="+pageType);
|
|
||||||
switch (pageType){
|
|
||||||
case "MUSIC_PAGE_TYPE_ARTIST":
|
|
||||||
Intent intent = new Intent(requireActivity(), ResultListActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_SEARCH_RESULT_BROWSER_ID, browserId);
|
|
||||||
startActivity(intent);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Intent intent1 = new Intent(requireActivity(), CategoryListActivity.class);
|
|
||||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_TYPE, pageType);
|
|
||||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_SINGER_NAME, songDescribe);
|
|
||||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_BROWSER_ID, browserId);
|
|
||||||
startActivity(intent1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}else {
|
|
||||||
CommonUtils.LogMsg("---------点击搜索结果--VideoId="+songVideoId);
|
|
||||||
|
|
||||||
ResponseSingle responseSingle = new ResponseSingle();
|
|
||||||
responseSingle.setSongTitle(songTitle);
|
|
||||||
responseSingle.setSingerHead(songCovert);
|
|
||||||
responseSingle.setVideoId(songVideoId);
|
|
||||||
responseSingle.setPlaylistId("");
|
|
||||||
Intent intent = new Intent(requireActivity(), PlayActivity.class);
|
|
||||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER, responseSingle);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -60,7 +60,7 @@
|
|||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:src="@mipmap/im_placeholder" />
|
android:src="@mipmap/default_image" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<!-- 中间的两排 TextView -->
|
<!-- 中间的两排 TextView -->
|
||||||
|
|||||||
@ -1,140 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/root_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/black"
|
|
||||||
tools:context=".ui.activity.CategoryListActivity">
|
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/im_bg"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="390dp" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="390dp"
|
|
||||||
android:background="@drawable/black_gradient" />
|
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/layout_covert"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="77dp">
|
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/card_im"
|
|
||||||
app:cardBackgroundColor="@color/color_transparent"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
app:cardCornerRadius="10dp"
|
|
||||||
app:cardElevation="0dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imCovert"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:layout_width="250dp"
|
|
||||||
android:layout_height="220dp" />
|
|
||||||
</androidx.cardview.widget.CardView>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvTitle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/card_im"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginStart="20dp"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:layout_marginEnd="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="21sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvSingerName"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/tvTitle"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginStart="20dp"
|
|
||||||
android:layout_marginTop="5dp"
|
|
||||||
android:layout_marginEnd="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvSubTitle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/tvSingerName"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginStart="20dp"
|
|
||||||
android:layout_marginTop="5dp"
|
|
||||||
android:layout_marginEnd="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/btn_play"
|
|
||||||
android:layout_width="55dp"
|
|
||||||
android:layout_height="55dp"
|
|
||||||
android:layout_below="@id/tvSubTitle"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginTop="15dp"
|
|
||||||
android:src="@drawable/selector_icon_play"
|
|
||||||
android:visibility="invisible" />
|
|
||||||
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/pb_loading"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerInParent="true"
|
|
||||||
android:indeterminateTint="@color/white" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recyclerview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/im_back"
|
|
||||||
android:layout_width="42dp"
|
|
||||||
android:layout_height="42dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="35dp"
|
|
||||||
android:padding="9dp"
|
|
||||||
android:src="@drawable/arrow_bottom" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/layout_error"
|
|
||||||
layout="@layout/layout_error"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginBottom="80dp" />
|
|
||||||
</FrameLayout>
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.core.widget.NestedScrollView 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:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/black"
|
|
||||||
android:fillViewport="true"
|
|
||||||
tools:context=".ui.activity.ResultListActivity">
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/relayout_top"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="280dp"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/covert"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:src="@mipmap/im_placeholder" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/im_back"
|
|
||||||
android:layout_width="42dp"
|
|
||||||
android:layout_height="42dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="35dp"
|
|
||||||
android:padding="9dp"
|
|
||||||
android:src="@drawable/arrow_bottom" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:background="@drawable/black_gradient" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="200dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/main_title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="17sp" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/list_recycler"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="15dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/main_title" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerInParent="true"
|
|
||||||
android:id="@+id/pb_loading"
|
|
||||||
android:indeterminateTint="@color/white" />
|
|
||||||
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/layout_error"
|
|
||||||
layout="@layout/layout_error"
|
|
||||||
android:layout_centerInParent="true"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
</RelativeLayout>
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
|
||||||
@ -1,116 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_marginTop="35dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/linear_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/top_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@color/black"
|
|
||||||
android:paddingStart="10dp"
|
|
||||||
android:paddingTop="10dp"
|
|
||||||
android:paddingEnd="10dp"
|
|
||||||
android:paddingBottom="25dp">
|
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
|
||||||
android:layout_width="60dp"
|
|
||||||
android:layout_height="60dp"
|
|
||||||
app:cardCornerRadius="6dp"
|
|
||||||
android:id="@+id/card_view"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
app:cardElevation="0dp">
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/top_im"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:src="@mipmap/im_placeholder" />
|
|
||||||
</androidx.cardview.widget.CardView>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignTop="@id/card_view"
|
|
||||||
android:layout_alignBottom="@id/card_view"
|
|
||||||
android:layout_marginStart="15dp"
|
|
||||||
android:layout_toStartOf="@id/im_play"
|
|
||||||
android:layout_toEndOf="@id/card_view"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingEnd="15dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/top_song_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:textColor="@color/text_color_1"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/top_singer_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:textColor="@color/white_60_color"
|
|
||||||
android:textSize="11sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/im_play"
|
|
||||||
android:layout_width="60dp"
|
|
||||||
android:layout_height="60dp"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_marginEnd="22dp"
|
|
||||||
android:padding="20dp"
|
|
||||||
android:src="@drawable/selector_small_play" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/list_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="-15dp"
|
|
||||||
android:background="@drawable/rec_bg_18">
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@id/tv_title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:textSize="17sp"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:layout_marginStart="15dp"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:text="@string/play_next" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recycler_list"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_below="@id/tv_title" />
|
|
||||||
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
<LinearLayout 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/linearLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/color_transparent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
tools:context=".ui.fragmnt.HomeFragment">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="15dp"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="22sp" />
|
|
||||||
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recycler_song_of_the_day"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingStart="6dp" />
|
|
||||||
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/layout_error"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_error"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginTop="200dp"
|
|
||||||
android:layout_marginStart="15dp"
|
|
||||||
android:layout_marginEnd="15dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/net_error"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_retry"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/tv_error"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
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" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@ -1,94 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/default_play_list_color"
|
|
||||||
tools:context=".ui.fragmnt.SearchFragment">
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/layout_et"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="50dp"
|
|
||||||
android:layout_marginStart="22dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="22dp"
|
|
||||||
android:background="@drawable/bg_search">
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/et_search"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_toStartOf="@id/im_cancel"
|
|
||||||
android:background="@null"
|
|
||||||
android:focusable="true"
|
|
||||||
android:focusableInTouchMode="true"
|
|
||||||
android:hint="@string/search_hint"
|
|
||||||
android:imeOptions="actionSearch"
|
|
||||||
android:inputType="text"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:paddingStart="20dp"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textColorHint="@color/seek_bg_color" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/im_cancel"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:paddingStart="13dp"
|
|
||||||
android:paddingEnd="13dp"
|
|
||||||
android:src="@drawable/icon_cancel" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recycler_suggestion"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/layout_et"
|
|
||||||
android:layout_alignStart="@id/layout_et"
|
|
||||||
android:layout_alignEnd="@id/layout_et" />
|
|
||||||
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recycler_result"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/layout_et"
|
|
||||||
android:layout_alignStart="@id/layout_et"
|
|
||||||
android:layout_alignEnd="@id/layout_et"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/layout_error"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_below="@id/layout_et"
|
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_error"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginStart="15dp"
|
|
||||||
android:layout_marginTop="200dp"
|
|
||||||
android:layout_marginEnd="15dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/no_result"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/pbloading"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/layout_et"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginTop="200dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:indeterminateTint="@color/white" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
@ -18,7 +18,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@mipmap/im_placeholder" />
|
android:src="@mipmap/default_image" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@mipmap/im_placeholder" />
|
android:src="@mipmap/default_image" />
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@mipmap/im_placeholder" />
|
android:src="@mipmap/default_image" />
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:background="@color/black"
|
android:background="@color/black"
|
||||||
android:src="@mipmap/im_placeholder" />
|
android:src="@mipmap/default_image" />
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
|||||||
@ -1,37 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/head_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="15dp"
|
|
||||||
android:textColor="@color/text_color_1"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:paddingTop="10dp"
|
|
||||||
android:textSize="18sp" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recycler_singer"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recycler_category"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:paddingStart="7dp"
|
|
||||||
android:paddingEnd="14dp"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:id="@+id/place"
|
|
||||||
android:layout_height="74dp" />
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RelativeLayout 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="70dp"
|
|
||||||
android:id="@+id/item_layout"
|
|
||||||
android:paddingStart="20dp">
|
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
|
||||||
android:id="@+id/card"
|
|
||||||
android:layout_width="60dp"
|
|
||||||
android:layout_height="60dp"
|
|
||||||
app:cardElevation="0dp"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
app:cardCornerRadius="6dp">
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/im_covert"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:src="@mipmap/im_placeholder" />
|
|
||||||
</androidx.cardview.widget.CardView>
|
|
||||||
|
|
||||||
|
|
||||||
<com.hi.music.player.customerview.AnimaPlayingView
|
|
||||||
android:id="@+id/view_playing"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignStart="@id/card"
|
|
||||||
android:layout_alignTop="@id/card"
|
|
||||||
android:layout_alignEnd="@id/card"
|
|
||||||
android:layout_alignBottom="@id/card"
|
|
||||||
android:layout_marginBottom="10dp" />
|
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
android:paddingEnd="10dp"
|
|
||||||
android:layout_toEndOf="@id/card"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/song_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:textColor="@color/text_color_1"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/artist_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:textColor="@color/white_60_color"
|
|
||||||
android:textSize="11sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginTop="5dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/header"
|
|
||||||
android:layout_width="170dp"
|
|
||||||
android:layout_height="170dp"
|
|
||||||
android:src="@mipmap/im_placeholder" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_title"
|
|
||||||
android:layout_width="169dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:textColor="@color/text_color_1"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_subtitle"
|
|
||||||
android:layout_width="169dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:textColor="@color/text_color_2"
|
|
||||||
android:textSize="12sp" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:id="@+id/view"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_height="100dp"/>
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/header"
|
|
||||||
android:layout_width="66dp"
|
|
||||||
android:layout_height="66dp"
|
|
||||||
android:scaleType="fitXY"
|
|
||||||
android:layout_marginStart="14dp"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:src="@mipmap/im_placeholder" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:paddingEnd="10dp"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_toEndOf="@id/header"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_song_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="99999999999999999999999999999999999"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:maxWidth="200dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:textColor="@color/text_color_1"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_singer_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:maxWidth="200dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:textColor="@color/text_color_2"
|
|
||||||
android:textSize="12sp" />
|
|
||||||
|
|
||||||
<!-- <TextView-->
|
|
||||||
<!-- android:id="@+id/tv_describe"-->
|
|
||||||
<!-- android:layout_width="wrap_content"-->
|
|
||||||
<!-- android:layout_height="wrap_content"-->
|
|
||||||
<!-- android:layout_marginTop="4dp"-->
|
|
||||||
<!-- android:maxLines="1"-->
|
|
||||||
<!-- android:ellipsize="end"-->
|
|
||||||
<!-- android:text="@string/app_name"-->
|
|
||||||
<!-- android:textColor="@color/text_color_1"-->
|
|
||||||
<!-- android:textSize="14sp" />-->
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
@ -1,99 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:id="@+id/layout_panel"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="74dp"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:background="@drawable/panel_bg"
|
|
||||||
android:paddingStart="14dp"
|
|
||||||
android:paddingEnd="14dp">
|
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
|
||||||
android:id="@+id/cardimage"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginStart="2dp"
|
|
||||||
app:cardCornerRadius="200dp"
|
|
||||||
app:cardElevation="0dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/image"
|
|
||||||
android:layout_width="52dp"
|
|
||||||
android:layout_height="52dp"
|
|
||||||
android:src="@mipmap/im_placeholder" />
|
|
||||||
</androidx.cardview.widget.CardView>
|
|
||||||
|
|
||||||
<com.hi.music.player.helper.CircularProgressBar
|
|
||||||
android:id="@+id/circular_pb"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignStart="@id/cardimage"
|
|
||||||
android:layout_alignTop="@id/cardimage"
|
|
||||||
android:layout_alignEnd="@id/cardimage"
|
|
||||||
android:layout_alignBottom="@id/cardimage"
|
|
||||||
android:layout_gravity="center" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginStart="22dp"
|
|
||||||
android:layout_toStartOf="@id/frame_play"
|
|
||||||
android:layout_toEndOf="@id/image"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:textColor="@color/black"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/singer"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:textColor="@color/panel_singer_color"
|
|
||||||
android:textSize="12sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/frame_play"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
android:layout_toStartOf="@id/im_next"
|
|
||||||
android:paddingStart="10dp"
|
|
||||||
android:paddingEnd="10dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/im_play"
|
|
||||||
android:layout_width="34dp"
|
|
||||||
android:layout_height="34dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:src="@drawable/selector_panel_icon_play" />
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/im_next"
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
android:paddingStart="5dp"
|
|
||||||
android:paddingEnd="5dp"
|
|
||||||
android:src="@drawable/icon_next_black"
|
|
||||||
android:visibility="visible" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 270 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 454 KiB |
@ -1,18 +1,10 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">MusicApp</string>
|
<string name="app_name">Offline Music Player</string>
|
||||||
<!-- TODO: Remove or change this placeholder text -->
|
<!-- TODO: Remove or change this placeholder text -->
|
||||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
|
||||||
<string name="song_of_the_day">Song Of The Day</string>
|
|
||||||
<string name="recently_played">Recently Played</string>
|
|
||||||
<string name="top_artists">Top Artists</string>
|
|
||||||
<string name="trending_in_shorts">Trending in Shorts</string>
|
|
||||||
<string name="new_releases">New Releases</string>
|
|
||||||
<string name="musicoo">Musicoo</string>
|
|
||||||
<string name="library">Library</string>
|
|
||||||
<string name="listen_music_anytime">Listen Music Anytime</string>
|
<string name="listen_music_anytime">Listen Music Anytime</string>
|
||||||
<string name="resource_loading">Resource Loading...</string>
|
<string name="resource_loading">Resource Loading...</string>
|
||||||
<string name="ready_to_sleep">Ready to sleep</string>
|
<string name="ready_to_sleep">Sounds of Serenity</string>
|
||||||
<string name="we_ve_carefully_prepared_sounds_for_you">We\'ve carefully prepared sounds for you 🔥</string>
|
<string name="we_ve_carefully_prepared_sounds_for_you">Soothing tunes crafted for deep relaxation and sleep 🌙</string>
|
||||||
<string name="white_noise">White noise</string>
|
<string name="white_noise">White noise</string>
|
||||||
<string name="voice_of_nature">Voice of Nature</string>
|
<string name="voice_of_nature">Voice of Nature</string>
|
||||||
<string name="setting">Setting</string>
|
<string name="setting">Setting</string>
|
||||||
@ -21,24 +13,4 @@
|
|||||||
<string name="share">Share</string>
|
<string name="share">Share</string>
|
||||||
<string name="privacy_policy">Privacy Policy</string>
|
<string name="privacy_policy">Privacy Policy</string>
|
||||||
<string name="terms_of_service">Terms of Service</string>
|
<string name="terms_of_service">Terms of Service</string>
|
||||||
<string name="play_next">Play next</string>
|
|
||||||
<string name="retry">Try again</string>
|
|
||||||
<string name="An_error_occurred">An error occurred</string>
|
|
||||||
<string name="search_hint">Search songs, artists…</string>
|
|
||||||
<string name="play">Play</string>
|
|
||||||
<string name="no_next_song_yet">There is no next song yet</string>
|
|
||||||
<string name="image_loading_failed">Image loading failed</string>
|
|
||||||
<string name="song_loading_failed">Song loading failed</string>
|
|
||||||
<string name="playList_loading_failed">Playlist loading failed</string>
|
|
||||||
<string name="time_format">%d:%02d:%02d</string>
|
|
||||||
<string name="minute_time_format">%d:%02d</string>
|
|
||||||
<string name="like">Like</string>
|
|
||||||
<string name="download">Download</string>
|
|
||||||
<string name="like_song">Songs %d</string>
|
|
||||||
<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>
|
|
||||||
<string name="net_error">An error occurred in the network request. Please try again.</string>
|
|
||||||
<string name="no_result">No results yet</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in New Issue
Block a user