删掉B面代码

This commit is contained in:
litingting 2024-11-08 11:31:32 +08:00
parent f58d8d8bf3
commit 8b8a79f39b
95 changed files with 68 additions and 10090 deletions

View File

@ -70,7 +70,7 @@ dependencies {
implementation("io.reactivex.rxjava2:rxandroid:2.1.1") implementation("io.reactivex.rxjava2:rxandroid:2.1.1")
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0") implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
implementation("androidx.paging:paging-runtime-ktx:3.3.2") // implementation("androidx.paging:paging-runtime-ktx:3.3.2")
implementation("com.github.bumptech.glide:glide:4.16.0") implementation("com.github.bumptech.glide:glide:4.16.0")
// kapt("com.github.bumptech.glide:compiler:4.16.0") // kapt("com.github.bumptech.glide:compiler:4.16.0")
@ -79,17 +79,17 @@ dependencies {
//提取图片主色 //提取图片主色
implementation ("androidx.palette:palette:1.0.0") // implementation ("androidx.palette:palette:1.0.0")
//动画 //动画
implementation ("com.airbnb.android:lottie:6.5.0") // implementation ("com.airbnb.android:lottie:6.5.0")
//----------media3 //----------media3
implementation("androidx.media3:media3-exoplayer:1.4.1") // implementation("androidx.media3:media3-exoplayer:1.4.1")
implementation("androidx.media3:media3-exoplayer-dash:1.4.1") // implementation("androidx.media3:media3-exoplayer-dash:1.4.1")
implementation("androidx.media3:media3-session:1.4.1") // implementation("androidx.media3:media3-session:1.4.1")
implementation("androidx.media3:media3-ui:1.4.1") // implementation("androidx.media3:media3-ui:1.4.1")
implementation ("androidx.media3:media3-database:1.4.1") // implementation ("androidx.media3:media3-database:1.4.1")
//----------media3 //----------media3

View File

@ -23,18 +23,7 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.MusicApp" android:theme="@style/Theme.MusicApp"
tools:targetApi="31"> tools:targetApi="31">
<activity
android:name=".ui.activity.LikeSongActivity"
android:screenOrientation="portrait"
android:exported="false" />
<activity
android:name=".ui.activity.ResultListActivity"
android:screenOrientation="portrait"
android:exported="false" />
<activity
android:name=".ui.activity.CategoryListActivity"
android:screenOrientation="portrait"
android:exported="false" />
<activity <activity
android:name=".ui.activity.A_PlayActivity" android:name=".ui.activity.A_PlayActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
@ -43,20 +32,12 @@
android:name=".ui.activity.A_SettingActivity" android:name=".ui.activity.A_SettingActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:exported="false" /> android:exported="false" />
<activity
android:name=".ui.activity.PlayActivity"
android:exported="false"
android:screenOrientation="portrait" />
<activity <activity
android:name=".ui.activity.A_HomeActivity" android:name=".ui.activity.A_HomeActivity"
android:exported="true" android:exported="true"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name=".ui.activity.HomeActivity"
android:screenOrientation="portrait"
android:exported="false">
</activity>
<activity <activity
android:name=".ui.activity.A_SplashActivity" android:name=".ui.activity.A_SplashActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
@ -68,25 +49,25 @@
</intent-filter> </intent-filter>
</activity> </activity>
<service <!-- <service-->
android:name=".media3.PlaybackService" <!-- android:name=".media3.PlaybackService"-->
android:exported="true" <!-- android:exported="true"-->
android:foregroundServiceType="mediaPlayback"> <!-- android:foregroundServiceType="mediaPlayback">-->
<intent-filter> <!-- <intent-filter>-->
<action android:name="androidx.media3.session.MediaSessionService" /> <!-- <action android:name="androidx.media3.session.MediaSessionService" />-->
</intent-filter> <!-- </intent-filter>-->
</service> <!-- </service>-->
<service <!-- <service-->
android:name=".media3.MyDownloadService" <!-- android:name=".media3.MyDownloadService"-->
android:exported="false" <!-- android:exported="false"-->
android:foregroundServiceType="dataSync" <!-- android:foregroundServiceType="dataSync"-->
tools:ignore="ForegroundServicePermission"> <!-- tools:ignore="ForegroundServicePermission">-->
<intent-filter> <!-- <intent-filter>-->
<action android:name="androidx.media3.exoplayer.downloadService.action.RESTART" /> <!-- <action android:name="androidx.media3.exoplayer.downloadService.action.RESTART" />-->
<category android:name="android.intent.category.DEFAULT" /> <!-- <category android:name="android.intent.category.DEFAULT" />-->
</intent-filter> <!-- </intent-filter>-->
</service> <!-- </service>-->
<service <service
android:name=".service.MusicPlayerForegroundService" android:name=".service.MusicPlayerForegroundService"
android:enabled="true" android:enabled="true"

View File

@ -3,16 +3,6 @@ package com.hi.music.player;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
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.MyMediaControllerManager;
import com.hi.music.player.objectbox.ObjectBoxManager;
public class MusicApplication extends Application { public class MusicApplication extends Application {
public static Context myApplication; public static Context myApplication;
@ -30,20 +20,20 @@ public class MusicApplication extends Application {
return visitorData; return visitorData;
} }
@OptIn(markerClass = UnstableApi.class)
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
myApplication = this; myApplication = this;
Sp.init(this); // Sp.init(this);
RemoteConfigJava.getInstance().init(this); // RemoteConfigJava.getInstance().init(this);
ObjectBoxManager.init(this); // ObjectBoxManager.init(this);
MyMediaControllerManager.getInstance().init(new MediaControllerStatusListener() { // MyMediaControllerManager.getInstance().init(new MediaControllerStatusListener() {
@Override // @Override
public void onMediaControllerComplete(boolean isOk) { // public void onMediaControllerComplete(boolean isOk) {
CommonUtils.LogMsg("=-----mediaController+" + isOk); // CommonUtils.LogMsg("=-----mediaController+" + isOk);
} // }
}); // });
} }

View File

@ -101,7 +101,7 @@ public class A_ImportFragmentAdapter extends RecyclerView.Adapter<A_ImportFragme
time = itemView.findViewById(R.id.time); time = itemView.findViewById(R.id.time);
option.setOnClickListener(v -> { option.setOnClickListener(v -> {
int position = getBindingAdapterPosition(); int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION && onOptionClickListener != null) { if (position != RecyclerView.NO_POSITION && onOptionClickListener != null) {
onOptionClickListener.onOptionClick(position, audioItem.getFile(), option); onOptionClickListener.onOptionClick(position, audioItem.getFile(), option);
} }

View File

@ -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.drawable.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);
}
}
});
}
}
}

View File

@ -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.drawable.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);
}
}
}

View File

@ -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.drawable.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);
}
}
});
}
}

View File

@ -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());
CommonUtils.LogMsg("position="+position+"-----------headTitle-=" + responseHomeChild.getHeaderTitle());
List<ResponseSingle> singleList = responseHomeChild.getSingleList();
List<ResponseCategory> categoryList = responseHomeChild.getCategoryList();
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);
}
}
}
}

View File

@ -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.drawable.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);
}
}
});
}
}

View File

@ -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.drawable.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());
}
});
}
}

View File

@ -1,72 +0,0 @@
package com.hi.music.player.adapter;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.hi.music.player.MusicApplication;
import com.hi.music.player.databinding.ItemResultBinding;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.helper.ItemDecoration;
import com.hi.music.player.helper.MyValue;
import com.hi.music.player.javabean.response.ResponseResultList;
import com.hi.music.player.ui.activity.PlayActivity;
public class AdapterResult extends BaseAdapter<ResponseResultList, ItemResultBinding>{
public AdapterResult(Context mContext) {
super(mContext);
}
@Override
protected ItemResultBinding getViewBinding(ViewGroup parent) {
return ItemResultBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
ResponseResultList resultList = data.get(position);
VHolder<ItemResultBinding> itemHolder = (VHolder<ItemResultBinding>) holder;
ItemResultBinding vb = itemHolder.getVb();
String headerTitle = resultList.getHeaderTitle();
vb.tvHeaderTitle.setText(headerTitle);
CommonUtils.LogMsg("---------headerTitle="+headerTitle);
ItemDecoration itemDecoration ;
if(position == 0){
itemDecoration = new ItemDecoration(10,0,0);
AdapterResultListSong adapterResultListSong = new AdapterResultListSong();
adapterResultListSong.setData(resultList.getChildList());
vb.listChild.setAdapter(adapterResultListSong);
vb.listChild.setLayoutManager(new LinearLayoutManager(mContext));
if(homeItemClickListener!= null)
adapterResultListSong.setHomeItemClickListener(homeItemClickListener);
}else {
itemDecoration = new ItemDecoration(0,10,0);
AdapterResultListAlbum adapterResultListAlbum = new AdapterResultListAlbum();
adapterResultListAlbum.setData(resultList.getChildList());
vb.listChild.setAdapter(adapterResultListAlbum);
vb.listChild.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL,false));
if(homeItemClickListener!= null)
adapterResultListAlbum.setHomeItemClickListener(homeItemClickListener);
}
// vb.listChild.addItemDecoration(itemDecoration);
if(position == data.size() - 1){
vb.place.setVisibility(View.VISIBLE);
}else {
vb.place.setVisibility(View.GONE);
}
}
}

View File

@ -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.drawable.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());
}
}

View File

@ -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.drawable.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());
}
}

View File

@ -1,82 +0,0 @@
package com.hi.music.player.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
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.databinding.ItemSearchBinding;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.response.ResponseSearch;
import com.hi.music.player.javabean.response.child.ResponseSearchChild;
import java.util.List;
public class AdapterSearch extends BaseAdapter<ResponseSearch, ItemSearchBinding> {
@Override
protected ItemSearchBinding getViewBinding(ViewGroup parent) {
return ItemSearchBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
ResponseSearch responseSearch = data.get(position);
VHolder<ItemSearchBinding> itemHolder = (VHolder<ItemSearchBinding>) holder;
ItemSearchBinding vb = itemHolder.getVb();
vb.tvHeaderTitle.setText(responseSearch.getHeaderTitle());
String beastSongTCovert = responseSearch.getBeastSongTCovert();
if (beastSongTCovert != null && !beastSongTCovert.isEmpty()) {
vb.layoutBest.setVisibility(View.VISIBLE);
Glide.with(MusicApplication.myApplication)
.load(beastSongTCovert)
.transform(new CircleCrop())
.into(vb.imBestCovert);
vb.tvBestTitle.setText(responseSearch.getBeastSongTitle());
vb.tvBestSubtitle.setText(responseSearch.getBeastSongDescribe());
vb.layout.setBackground(ContextCompat.getDrawable(MusicApplication.myApplication, R.drawable.bg_best_bg));
vb.layout.setPadding(CommonUtils.dpToPx(6), CommonUtils.dpToPx(10), 0, 0);
vb.tvPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (homeItemClickListener != null) {
homeItemClickListener.onClickSearchResultBest(responseSearch);
}
}
});
} else {
vb.layoutBest.setVisibility(View.GONE);
vb.layout.setBackground(null);
vb.layout.setPadding(0, 0, 0, 0);
}
List<ResponseSearchChild> list = responseSearch.getList();
if(list!= null&&list.size()>0){
AdapterSearchChild adapterSearchChild = new AdapterSearchChild();
adapterSearchChild.setData(list);
vb.list.setAdapter(adapterSearchChild);
if (homeItemClickListener != null)
adapterSearchChild.setHomeItemClickListener(homeItemClickListener);
vb.list.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication));
}
if(position == data.size() - 1){
vb.place.setVisibility(View.VISIBLE);
}else {
vb.place.setVisibility(View.GONE);
}
}
}

View File

@ -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.drawable.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);
}
}
});
}
}

View File

@ -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.drawable.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);
}
}
});
}
}
}

View File

@ -1,46 +0,0 @@
package com.hi.music.player.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.hi.music.player.databinding.ItemSuggestionBinding;
public class AdapterSuggestion extends BaseAdapter<String, ItemSuggestionBinding> {
@Override
protected ItemSuggestionBinding getViewBinding(ViewGroup parent) {
return ItemSuggestionBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
VHolder<ItemSuggestionBinding> itemHolder = (VHolder<ItemSuggestionBinding>) holder;
ItemSuggestionBinding vb = itemHolder.getVb();
String text = data.get(position);
vb.tvSuggestion.setText(text);
vb.relayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(homeItemClickListener!= null){
homeItemClickListener.onClickItemSuggestion(true,text);
}
}
});
vb.imFillIn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(homeItemClickListener!= null){
homeItemClickListener.onClickItemSuggestion(false,text);
}
}
});
}
}

View File

@ -1,127 +0,0 @@
package com.hi.music.player.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
import com.hi.music.player.api.HomeItemClickListener;
import com.hi.music.player.databinding.ItemFooterLoadingBinding;
import com.hi.music.player.javabean.response.child.ResponseCategory;
import com.hi.music.player.javabean.response.child.ResponseSingle;
import java.util.ArrayList;
import java.util.List;
abstract public class BaseAdapter<K, T extends ViewBinding> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
protected List<K> data = new ArrayList<>();
protected Context mContext;
protected static final int TYPE_ITEM = 0;
protected static final int TYPE_FOOTER = 1;
protected boolean isLoadingAdded = false;
public BaseAdapter() {
}
public BaseAdapter(Context mContext) {
this.mContext = mContext;
}
protected HomeItemClickListener homeItemClickListener;
public void setHomeItemClickListener(HomeItemClickListener homeItemClickListener) {
this.homeItemClickListener = homeItemClickListener;
}
public boolean isLoadingAdded() {
return isLoadingAdded;
}
public void addData(List<K> data) {
this.data.addAll(data);
notifyDataSetChanged();
}
public void setData(List<K> data) {
this.data.clear();
this.data.addAll(data);
notifyDataSetChanged();
}
public void addLoadingFooter() {
isLoadingAdded = true;
notifyItemInserted(data.size());
}
// Hide loading footer
public void removeLoadingFooter() {
isLoadingAdded = false;
int position = data.size();
if (position > 0)
notifyItemRemoved(position);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == TYPE_ITEM) {
T viewBinding = getViewBinding(parent);
return new VHolder<>(viewBinding);
} else {
// Inflate footer layout
ItemFooterLoadingBinding inflate = ItemFooterLoadingBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new VHolder<>(inflate);
}
}
protected abstract T getViewBinding(ViewGroup parent);
@Override
public int getItemViewType(int position) {
return (position == data.size() && isLoadingAdded) ? TYPE_FOOTER : TYPE_ITEM;
}
@Override
public int getItemCount() {
return data.size() + (isLoadingAdded ? 1 : 0);
}
public static class VHolder<V extends ViewBinding> extends RecyclerView.ViewHolder {
private V vb;
public V getVb() {
return vb;
}
public VHolder(@NonNull V itemView) {
super(itemView.getRoot());
vb = itemView;
}
}
public static class FooterHolder extends RecyclerView.ViewHolder {
private ItemFooterLoadingBinding vb;
public ItemFooterLoadingBinding getVb() {
return vb;
}
public FooterHolder(@NonNull ItemFooterLoadingBinding itemView) {
super(itemView.getRoot());
vb = itemView;
}
}
}

View File

@ -1,36 +0,0 @@
package com.hi.music.player.adapter;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import com.hi.music.player.ui.fragmnt.HomeFragment;
import com.hi.music.player.ui.fragmnt.ProfileFragment;
import com.hi.music.player.ui.fragmnt.SearchFragment;
import java.util.ArrayList;
import java.util.List;
public class HomeViewPagerAdapter extends FragmentStateAdapter {
private final List<Fragment> fragments = new ArrayList<>();
public HomeViewPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
fragments.add(new HomeFragment());
fragments.add(new SearchFragment());
fragments.add(new ProfileFragment());
}
@NonNull
@Override
public Fragment createFragment(int position) {
return fragments.get(position);
}
@Override
public int getItemCount() {
return fragments.size();
}
}

View File

@ -1,100 +0,0 @@
package com.hi.music.player.api;
import androidx.media3.exoplayer.offline.Download;
import com.hi.music.player.javabean.BoxLikeSong;
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
import com.hi.music.player.javabean.response.ResponseSearch;
import com.hi.music.player.javabean.response.child.ResponseCategory;
import com.hi.music.player.javabean.response.child.ResponseResultListChild;
import com.hi.music.player.javabean.response.child.ResponseSearchChild;
import com.hi.music.player.javabean.response.child.ResponseSingle;
public interface HomeItemClickListener {
//首页点击了单曲
default void onClickItemSinger(ResponseSingle data) {
}
//首页点击了分类合集
default void onClickItemCategory(ResponseCategory data) {
}
//分类合集点击了某一首歌曲
default void onClickItemCategoryList(ResponsePlayListInfo data,int musicIndex) {
}
/**
* 点击了搜索建议
* @param isSearch true 直接搜索 false 输入搜索建议文字
* @param data
*/
default void onClickItemSuggestion(boolean isSearch,String data) {
}
/**
* 点击搜索最佳结果第一个
* @param
*/
default void onClickSearchResultBest(ResponseSearch responseSearch){
}
/**
* 点击搜索结果
* @param
*/
default void onClickSearchResult(ResponseSearchChild responseSearchChild){
}
/**
* 搜索结果详情页面点击单曲
* @param child
* @param index
*/
default void onClickResultSong(ResponseResultListChild child,int index){
}
default void onClickResultAlbum(ResponseResultListChild child,int index){
}
/**
* 点击喜爱歌曲列表的某一首歌曲
* @param boxLikeSong
* @param index
*/
default void onClickLikeSong(BoxLikeSong boxLikeSong, int index){
}
/**
* 开始下载歌曲
* @param boxLikeSong
* @param index
*/
default void onDownloadSong(String videoId, int index){
}
/**
* 点击下载歌曲列表的某一首歌曲
* @param index
*/
default void onClickDownloadSong(Download download, int index){
}
}

View File

@ -1,10 +0,0 @@
package com.hi.music.player.api;
import com.hi.music.player.javabean.BoxLikeSong;
import java.util.List;
public interface LikeSongListener {
void onLikeSongChange(List<BoxLikeSong> data);
}

View File

@ -1,22 +0,0 @@
package com.hi.music.player.api;
import androidx.media3.common.MediaItem;
public interface MediaControllerListener {
void onPlayStatus(int playStatus);
/**
*
* @param videoId
* @param playListIndex 在播放列表中的位置索引
* @param playNow 立即播放
*/
void onRequestNextUri(String videoId,int playListIndex,boolean playNow);
void onChangeMusic(MediaItem mediaItem);
}

View File

@ -1,9 +0,0 @@
package com.hi.music.player.api;
public interface MediaControllerStatusListener {
void onMediaControllerComplete(boolean isOk);
}

View File

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

View File

@ -1,12 +0,0 @@
package com.hi.music.player.api;
import org.json.JSONObject;
import okhttp3.ResponseBody;
public interface RequestListener<T> {
void onFail(String errorMsg);
void onSuccess(JSONObject data) ;
}

View File

@ -1,7 +0,0 @@
package com.hi.music.player.api;
import com.hi.music.player.javabean.CustomerDownload;
public interface onCheckDownload {
void onHasDownload(CustomerDownload customerDownload);
}

View File

@ -1,5 +0,0 @@
package com.hi.music.player.api;
public interface onImageColorListener {
void onImageColor(int color);
}

View File

@ -1,5 +0,0 @@
package com.hi.music.player.api;
public interface onPlayNextListener {
void onPlayNext(boolean hasNext);
}

View File

@ -1,167 +0,0 @@
package com.hi.music.player.customerview;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.hi.music.player.helper.CommonUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class AnimaPlayingView extends View {
private Paint paint;
private int barColor = Color.GREEN; // 音量条的颜色
private int numBars = 5; // 音量条的数量
private float[] barHeights; // 每个音量条的高度
private int maxHeight = CommonUtils.dpToPx(20); // 音量条的最大高度
private int minHeight = CommonUtils.dpToPx(4); // 音量条的最小高度
// 每个柱子的宽度
private int barWidth = CommonUtils.dpToPx(4);
// 柱子之间的间距
private int barSpacing = CommonUtils.dpToPx(2);
private int cornerRadius = CommonUtils.dpToPx(16);
private Random random;
private ValueAnimator animator;
private List<ValueAnimator> valueAnimatorList;
public AnimaPlayingView(Context context) {
super(context);
init();
}
public AnimaPlayingView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public AnimaPlayingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
valueAnimatorList = new ArrayList<>();
paint = new Paint();
paint.setColor(barColor);
paint.setStyle(Paint.Style.FILL);
barHeights = new float[numBars];
random = new Random();
// 初始化音量条高度
for (int i = 0; i < numBars; i++) {
barHeights[i] = 0;
}
initAnimating();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int height = getHeight();
int width = getWidth();
int barCount = barHeights.length;
int totalWidth = barCount * barWidth + (barCount - 1) * barSpacing;
int startX = (width - totalWidth) / 2;
for (int i = 0; i < numBars; i++) {
float left = startX + i * (barWidth + barSpacing);
float top = height - barHeights[i];
float right = left + barWidth;
float bottom = height;
canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius, paint);
}
}
public void startAnimating() {
for (ValueAnimator valueAnimator : valueAnimatorList) {
valueAnimator.start();
}
}
// 启动固定动画使音量条的高度变化
public void initAnimating() {
for (int i = 0; i < numBars; i++) {
animator = ValueAnimator.ofFloat(0, 1);
animator.setDuration(1000); // 每0.5秒更新一次
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.setInterpolator(new LinearInterpolator());
int finalI = i;
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 更新每个音量条的高度使其不断变化
float animatedValue = (Float) animation.getAnimatedValue();
float v = animatedValue * maxHeight;
barHeights[finalI] = v;
invalidate(); // 重绘视图
}
});
valueAnimatorList.add(animator);
animator.setStartDelay(i * 200L);
}
}
public void pauseAnimating() {
for (ValueAnimator valueAnimator : valueAnimatorList) {
valueAnimator.pause();
}
for (int i = 0; i < numBars; i++) {
barHeights[i] = minHeight;
}
invalidate();
}
// 随机生成音量条的高度
private float randomHeight() {
return minHeight + random.nextFloat() * (maxHeight - minHeight);
}
// 设置音量条的颜色
public void setBarColor(int color) {
barColor = color;
paint.setColor(barColor);
invalidate();
}
// 设置音量条的最大高度
public void setMaxHeight(int maxHeight) {
this.maxHeight = maxHeight;
invalidate();
}
// 设置音量条的最小高度
public void setMinHeight(int minHeight) {
this.minHeight = minHeight;
invalidate();
}
// 设置音量条数量
public void setNumBars(int numBars) {
this.numBars = numBars;
barHeights = new float[numBars];
invalidate();
}
}

View File

@ -1,95 +0,0 @@
package com.hi.music.player.dialog;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment;
import androidx.viewbinding.ViewBinding;
import com.hi.music.player.MusicApplication;
import com.hi.music.player.R;
public abstract class BaseDialog<T extends ViewBinding> extends DialogFragment {
protected T vb;
protected abstract T getViewBinding(LayoutInflater inflater, ViewGroup container);
protected abstract void initView();
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
vb = getViewBinding(inflater, container);
init();
initView();
return vb.getRoot();
}
@Override
public void onStart() {
super.onStart();
}
@SuppressLint("ResourceType")
private void init() {
Dialog dialog = getDialog();
setCancelable(true);
if (dialog != null) {
Window window = dialog.getWindow();
if (window != null) {
if (isFullScreen()) {
window.setStatusBarColor(Color.YELLOW); // 设置状态栏为透明或其他颜色
// 设置 dialog 占据全屏并延伸到状态栏
// window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
// 允许内容绘制到状态栏
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
window.setBackgroundDrawableResource(R.color.color_transparent);
window.getDecorView().setPadding(0, 0, 0, 0);
WindowManager.LayoutParams attributes = window.getAttributes();
attributes.gravity = Gravity.BOTTOM;
attributes.width = WindowManager.LayoutParams.MATCH_PARENT;
attributes.height = WindowManager.LayoutParams.MATCH_PARENT;
window.setAttributes(attributes);
} else {
window.setBackgroundDrawableResource(R.color.color_transparent);
window.getDecorView().setPadding(0, 0, 0, 0);
WindowManager.LayoutParams attributes = window.getAttributes();
attributes.gravity = Gravity.BOTTOM;
attributes.width = WindowManager.LayoutParams.MATCH_PARENT;
attributes.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(attributes);
}
}
}
}
public abstract boolean isFullScreen();
public void closeDialog() {
dismiss();
}
}

View File

@ -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.drawable.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);
}
}

View File

@ -1,151 +0,0 @@
package com.hi.music.player.firebase
import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.text.TextUtils
import android.util.Log
import com.google.firebase.remoteconfig.ConfigUpdate
import com.google.firebase.remoteconfig.ConfigUpdateListener
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.FirebaseRemoteConfigException
import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings
import com.google.firebase.remoteconfig.FirebaseRemoteConfigValue
import com.hi.music.player.BuildConfig
import com.hi.music.player.helper.CommonUtils
import java.lang.ref.WeakReference
class RemoteConfig {
private var ctx: Context? = null
private var mFirebaseRemoteConfig: FirebaseRemoteConfig? = null
//配置是否初始化成功
private var isInit = false
//上次获取数据的时间
private var lastFetchTime: Long = 0
private val handler = MHandler(this)
companion object {
const val key_open_type = "TYPE"
//进入A面
const val value_open_type_0 = "0"
//进入B面
const val value_open_type_1 = "1"
const val MSG_REFRESH_CONFIG = 1
val instance: RemoteConfig by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
RemoteConfig()
}
}
fun init(ctx: Application) {
this.ctx = ctx
initConfig()
fetchConfig()
onConfigUpdate()
}
private fun initConfig() {
var intervalTime = (60 * 10).toLong()
//如果是开发状态,则将提取时间缩短
if (BuildConfig.DEBUG) {
intervalTime = (60 * 5).toLong()
}
mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance()
val configSettings =
FirebaseRemoteConfigSettings.Builder() //默认值12小时的最短提取间隔如果在间隔内取值则优先取上次的结果
.setMinimumFetchIntervalInSeconds(intervalTime).build()
mFirebaseRemoteConfig!!.setConfigSettingsAsync(configSettings)
}
private fun onConfigUpdate() {
mFirebaseRemoteConfig!!.addOnConfigUpdateListener(object : ConfigUpdateListener {
override fun onUpdate(configUpdate: ConfigUpdate) {
CommonUtils.LogMsg("Updated keys: " + configUpdate.updatedKeys)
try {
mFirebaseRemoteConfig!!.activate().addOnCompleteListener { task ->
if (task.isSuccessful) {
updateData("onConfigUpdate", mFirebaseRemoteConfig!!.all)
}
}
} catch (ignore: Exception) {
}
}
override fun onError(error: FirebaseRemoteConfigException) {
CommonUtils.LogMsg("Config update error with code: " + error.code)
}
})
}
private fun fetchConfig() {
//这里可能会抛出异常 FirebaseRemoteConfigFetchThrottledException
try {
mFirebaseRemoteConfig!!.fetchAndActivate().addOnCompleteListener { task ->
if (task.isSuccessful) {
isInit = true
lastFetchTime = System.currentTimeMillis()
updateData("fetchAndActivate", mFirebaseRemoteConfig!!.all)
//24小时后重新再去获取
handler.removeMessages(MSG_REFRESH_CONFIG)
handler.sendEmptyMessageDelayed(
MSG_REFRESH_CONFIG, (1000 * 60 * 60 * 24).toLong()
)
} else {
//15分钟后重新再去获取
handler.removeMessages(MSG_REFRESH_CONFIG)
handler.sendEmptyMessageDelayed(MSG_REFRESH_CONFIG, (1000 * 60 * 15).toLong())
}
}
} catch (ignore: Exception) {
}
}
private fun updateData(from: String, all: Map<String, FirebaseRemoteConfigValue>) {
for ((key, value) in all) {
try {
CommonUtils.LogMsg( "from = " + from + "Key = " + key + " Value = " + value.asString()
)
if (TextUtils.equals(key_open_type, key)) {
Sp.getInstance()
.putStringValue(key_open_type, value.asString()).commit()
}
} catch (ignore: Exception) {
}
}
}
private class MHandler(remoteConfig: RemoteConfig) : Handler(Looper.getMainLooper()) {
private val weakReference: WeakReference<RemoteConfig>
init {
weakReference = WeakReference(remoteConfig)
}
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
val remoteConfig = weakReference.get()
if (remoteConfig?.ctx != null) {
if (msg.what == MSG_REFRESH_CONFIG) {
remoteConfig.fetchConfig()
}
}
}
}
}

View File

@ -1,167 +0,0 @@
package com.hi.music.player.firebase;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.BuildConfig;
import com.google.firebase.remoteconfig.ConfigUpdate;
import com.google.firebase.remoteconfig.ConfigUpdateListener;
import com.google.firebase.remoteconfig.FirebaseRemoteConfig;
import com.google.firebase.remoteconfig.FirebaseRemoteConfigException;
import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings;
import com.google.firebase.remoteconfig.FirebaseRemoteConfigValue;
import com.hi.music.player.helper.CommonUtils;
import java.lang.ref.WeakReference;
import java.util.Map;
public class RemoteConfigJava {
private static RemoteConfigJava remoteConfigJava;
public static String key_open_type = "TYPE";
//进入A面
public static String value_open_type_0 = "0";
//进入B面
public static String value_open_type_1 = "1";
private static int MSG_REFRESH_CONFIG = 1;
private Context ctx;
private FirebaseRemoteConfig mFirebaseRemoteConfig;
//配置是否初始化成功
private boolean isInit = false;
//上次获取数据的时间
private long lastFetchTime = 0;
private MHandler handler = new MHandler(this);
private Context getCtx() {
return ctx;
}
public static RemoteConfigJava getInstance(){
if(remoteConfigJava == null){
remoteConfigJava = new RemoteConfigJava();
}
return remoteConfigJava;
}
private static class MHandler extends Handler {
private WeakReference<RemoteConfigJava> weakReference;
public MHandler(RemoteConfigJava remoteConfig) {
super(Looper.getMainLooper());
weakReference = new WeakReference<>(remoteConfig);
}
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
RemoteConfigJava remoteConfig1 = weakReference.get();
if (remoteConfig1.getCtx() != null) {
if (msg.what == MSG_REFRESH_CONFIG) {
remoteConfig1.fetchConfig();
}
}
}
}
public void init(Context context) {
this.ctx = context;
initConfig();
fetchConfig();
onConfigUpdate();
}
private void initConfig() {
long intervalTime = 60L * 10L;
//如果是开发状态则将提取时间缩短
if (BuildConfig.DEBUG) {
intervalTime = 60L * 5L;
}
mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder() //默认值12小时的最短提取间隔如果在间隔内取值则优先取上次的结果
.setMinimumFetchIntervalInSeconds(intervalTime).build();
mFirebaseRemoteConfig.setConfigSettingsAsync(configSettings);
}
private void onConfigUpdate() {
mFirebaseRemoteConfig.addOnConfigUpdateListener(new ConfigUpdateListener() {
@Override
public void onUpdate(@NonNull ConfigUpdate configUpdate) {
CommonUtils.LogMsg("Updated keys: " + configUpdate.getUpdatedKeys());
try {
mFirebaseRemoteConfig.activate().addOnCompleteListener(new OnCompleteListener<Boolean>() {
@Override
public void onComplete(@NonNull Task<Boolean> task) {
if (task.isSuccessful()) {
updateData("onConfigUpdate", mFirebaseRemoteConfig.getAll());
}
}
});
} catch (Exception ignore) {
CommonUtils.LogErrorMsg("onConfigUpdate Exception " + ignore.getMessage());
}
}
@Override
public void onError(@NonNull FirebaseRemoteConfigException error) {
CommonUtils.LogErrorMsg("onConfigUpdate onError " + error.getMessage());
}
});
}
private void fetchConfig() {
//这里可能会抛出异常 FirebaseRemoteConfigFetchThrottledException
try {
mFirebaseRemoteConfig.fetchAndActivate().addOnCompleteListener(new OnCompleteListener<Boolean>() {
@Override
public void onComplete(@NonNull Task<Boolean> task) {
if (task.isSuccessful()) {
isInit = true;
lastFetchTime = System.currentTimeMillis();
updateData("fetchAndActivate", mFirebaseRemoteConfig.getAll());
//24小时后重新再去获取
handler.removeMessages(MSG_REFRESH_CONFIG);
handler.sendEmptyMessageDelayed(
MSG_REFRESH_CONFIG, 1000 * 60 * 60 * 24L);
} else {
//15分钟后重新再去获取
handler.removeMessages(MSG_REFRESH_CONFIG);
handler.sendEmptyMessageDelayed(MSG_REFRESH_CONFIG, 1000 * 60 * 15L);
}
}
});
} catch (Exception exception) {
CommonUtils.LogErrorMsg(" exception = " + exception.getMessage());
}
}
private void updateData(String from, Map<String, FirebaseRemoteConfigValue> all) {
for (Map.Entry<String, FirebaseRemoteConfigValue> entry : all.entrySet()) {
FirebaseRemoteConfigValue value = entry.getValue();
String key = entry.getKey();
CommonUtils.LogMsg("from = " + from + "Key = " + key + " Value = " + value.asString());
if (TextUtils.equals(key_open_type, key)) {
Sp.getInstance()
.putStringValue(key_open_type, value.asString()).commit();
}
}
}
}

View File

@ -1,44 +0,0 @@
package com.hi.music.player.firebase;
import android.content.Context;
import android.content.SharedPreferences;
public class Sp {
private static String spName = "AD_SHOW";
private static Sp instance;
private SharedPreferences.Editor editor;
private SharedPreferences preferences;
private Sp(Context context) {
preferences = context.getSharedPreferences(spName, Context.MODE_PRIVATE);
editor = preferences.edit();
}
public static void init(Context context){
instance = new Sp(context);
}
public static Sp getInstance() {
return instance;
}
public Sp putStringValue(String key, String value) {
editor.putString(key, value);
return this;
}
public boolean commit() {
return editor.commit();
}
public String getStringValue(String key) {
return preferences.getString(key, RemoteConfigJava.value_open_type_1);
}
}

View File

@ -1,24 +0,0 @@
package com.hi.music.player.helper;
import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModelStore;
import androidx.lifecycle.ViewModelStoreOwner;
public class BaseViewModelStoreOwner implements ViewModelStoreOwner {
private final static BaseViewModelStoreOwner sInstance = new BaseViewModelStoreOwner();
private ViewModelStore mAppViewModelStore;
private BaseViewModelStoreOwner() {
}
public static BaseViewModelStoreOwner getInstance() {
return sInstance;
}
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (mAppViewModelStore == null) mAppViewModelStore = new ViewModelStore();
return mAppViewModelStore;
}
}

View File

@ -1,324 +0,0 @@
package com.hi.music.player.helper;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import androidx.annotation.OptIn;
import androidx.media3.common.MediaItem;
import androidx.media3.common.MediaMetadata;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.datasource.cache.Cache;
import androidx.media3.datasource.cache.CacheEvictor;
import androidx.media3.datasource.cache.CacheSpan;
import androidx.media3.datasource.cache.SimpleCache;
import androidx.media3.exoplayer.offline.Download;
import androidx.palette.graphics.Palette;
import com.google.gson.Gson;
import com.hi.music.player.MusicApplication;
import com.hi.music.player.R;
import com.hi.music.player.api.onImageColorListener;
import com.hi.music.player.javabean.BoxDownloadSong;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.NavigableSet;
import java.util.TreeSet;
import okhttp3.ResponseBody;
public class CommonUtils {
private static String TAG = "----MUSIC---------";
private static String TAG_ERROR = "----MUSIC---------ERROR--";
public static void LogMsg(String msg) {
Log.d(TAG, msg);
}
public static void LogErrorMsg(String msg) {
Log.e(TAG_ERROR, msg);
}
public static JSONObject toJsonObject(ResponseBody body) {
try {
String string = body.string();
return new JSONObject(string);
} catch (IOException | JSONException exception) {
return null;
}
}
public static int dpToPx(int dp) {
return Math.round(dp * (MusicApplication.myApplication.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
public static int pxToDp(int px) {
return Math.round(px / (MusicApplication.myApplication.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
// 获取导航栏高度的方法
public int getNavigationBarHeight(Context context) {
int navigationBarHeight = 0;
int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
navigationBarHeight = context.getResources().getDimensionPixelSize(resourceId);
}
return navigationBarHeight;
}
public static int getStatusBarHeight(Context context) {
int statusBarHeight = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
}
return statusBarHeight;
}
//time 3:45 转换成毫秒
public static long convertToMilliseconds(String time) {
String[] parts = time.split(":");
if (parts.length == 2) {
//3:45
int minutes = Integer.parseInt(parts[0]);
int seconds = Integer.parseInt(parts[1]);
return (minutes * 60L + seconds) * 1000 - 1000;
} else {
//3:4507
int hours = Integer.parseInt(parts[0]);
int minutes = Integer.parseInt(parts[1]);
int seconds = Integer.parseInt(parts[2]);
return (hours * 60L * 60L + minutes * 60L + seconds) * 1000 - 1000;
}
}
public static String convertMillisToTime(long millis) {
long seconds = millis / 1000;
long hours = seconds / 3600;
long minutes = (seconds % 3600) / 60;
long remainingSeconds = seconds % 60;
// long seconds = (millis / 1000) % 60;
// long minutes = (millis / (1000 * 60)) % 60;
if (hours > 0) {
return String.format(MusicApplication.myApplication.getString(R.string.time_format), hours, minutes, remainingSeconds); // 格式化为 mm:ss
} else {
return String.format(MusicApplication.myApplication.getString(R.string.minute_time_format), minutes, remainingSeconds); // 格式化为 mm:ss
}
}
public static int getMyColor(int resId) {
return MusicApplication.myApplication.getColor(resId);
}
// 使用 Palette 提取深色主色调
public static void getDominantDarkColor1(Drawable imDraw, onImageColorListener listener) {
// 异步生成 Palette
BitmapDrawable drawable = (BitmapDrawable) imDraw;
if (drawable != null) {
Bitmap bitmap = drawable.getBitmap();
Palette.from(bitmap)
.generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
// 首先尝试获取深色活力色
Palette.Swatch darkVibrantSwatch = palette.getDarkVibrantSwatch();
// 如果没有深色活力色尝试获取深色柔和色
if (darkVibrantSwatch == null) {
darkVibrantSwatch = palette.getDarkMutedSwatch();
}
// 如果存在深色样本则获取其 RGB 颜色值
if (darkVibrantSwatch != null) {
int dominantDarkColor = darkVibrantSwatch.getRgb();
listener.onImageColor(dominantDarkColor);
String dominantColorHex = String.format("#%06X", (0xFFFFFF & dominantDarkColor));
Log.d("Dominant Dark Color", "主色调: " + dominantColorHex); // 打印主色调
} else {
Log.d("Dominant Dark Color", "未找到深色主色调");
listener.onImageColor(-1);
}
}
});
} else {
listener.onImageColor(-1);
}
}
// 调整颜色的亮度factor > 1 表示变亮factor < 1 表示变暗
public static int adjustBrightness(int color, float factor) {
// RGB 颜色转换为 HSV
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
// 调整亮度V
hsv[2] = Math.min(1.0f, hsv[2] * factor); // 亮度值最多是 1.0
// 返回调整后的颜色HSV 转回 RGB
return Color.HSVToColor(hsv);
}
public static void getMainColor(Drawable imDraw, onImageColorListener listener) {
BitmapDrawable drawable = (BitmapDrawable) imDraw;
// 使用 Palette 提取颜色
if (drawable != null) {
Bitmap bitmap = drawable.getBitmap();
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
// 获取占比最大的颜色
Palette.Swatch dominantSwatch = palette.getDominantSwatch();
if (dominantSwatch != null) {
int dominantColor = dominantSwatch.getRgb(); // 获取 RGB 颜色
listener.onImageColor(dominantColor);
} else {
listener.onImageColor(-1);
}
}
});
}
}
public static Drawable getNewDrawable(int color, float RadiusTopLeft, float RadiusTopRight, float RadiusBottomRight, float RadiusBottomLeft) {
// 创建 GradientDrawable
GradientDrawable drawable = new GradientDrawable();
// 设置形状为矩形
drawable.setShape(GradientDrawable.RECTANGLE);
// 设置背景颜色
drawable.setColor(color);
// 设置顶部圆角 (top-left and top-right)
float[] radii = new float[]{
RadiusTopLeft, RadiusTopLeft, // top-left radius
RadiusTopRight, RadiusTopRight, // top-right radius
RadiusBottomRight, RadiusBottomRight, // bottom-right radius
RadiusBottomLeft, RadiusBottomLeft // bottom-left radius
};
drawable.setCornerRadii(radii);
return drawable;
}
public static void extractColorsFromImage(Drawable drawable, View view) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
Palette.from(bitmap).generate(palette -> {
if (palette != null) {
// 获取主色
int vibrantColor = palette.getVibrantColor(0);
int mutedColor = palette.getMutedColor(0);
// 创建左右渐变色
createGradientBackground(vibrantColor, mutedColor, view);
}
});
}
public static void createGradientBackground(int leftColor, int rightColor, View view) {
GradientDrawable gradientDrawable = new android.graphics.drawable.GradientDrawable(
android.graphics.drawable.GradientDrawable.Orientation.LEFT_RIGHT,
new int[]{leftColor, rightColor}
);
view.setBackground(gradientDrawable);
}
/**
* 当前媒体项是否有有效的播放地址
*
* @param mediaItem
* @return
*/
public static boolean hasValidUri(MediaItem mediaItem) {
MediaItem.LocalConfiguration localConfiguration = mediaItem.localConfiguration;
if (localConfiguration != null) {
if (CommonUtils.isUriFormat(localConfiguration.uri)) {
return true;
}
}
return false;
}
private static boolean isUriFormat(Uri parsedUri) {
// 3. 检查 URI 是否具有正确的格式
try {
if (parsedUri.getScheme() == null) {
return false;
}
} catch (Exception e) {
LogMsg("URI parsing failed: " + e.getMessage());
return false;
}
return true;
}
public static BoxDownloadSong downloadToBean(Download download) {
@OptIn(markerClass = UnstableApi.class) byte[] data = download.request.data;
String additionalData = new String(data, StandardCharsets.UTF_8);
Gson gson = new Gson();
return gson.fromJson(additionalData, BoxDownloadSong.class);
}
@OptIn(markerClass = UnstableApi.class)
public static MediaItem downloadToMediaItem(Download data){
MediaItem mediaItem = data.request.toMediaItem();
BoxDownloadSong boxDownloadSong = CommonUtils.downloadToBean(data);
MediaItem.Builder builder = mediaItem.buildUpon();
MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder();
metadataBuilder.setArtist(boxDownloadSong.getSingerName());
metadataBuilder.setDescription(boxDownloadSong.getDuration());
metadataBuilder.setDurationMs(boxDownloadSong.getDurationMs());
metadataBuilder.setArtworkUri(Uri.parse(boxDownloadSong.getCovert()));
metadataBuilder.setTitle(boxDownloadSong.getSongName());
builder.setMediaMetadata(metadataBuilder.build());
return builder.build();
}
// @OptIn(markerClass = UnstableApi.class)
// public static boolean isSongCached(SimpleCache cache, String id) {
//
// return cachedFile.exists();
//
// }
}

View File

@ -1,130 +0,0 @@
package com.hi.music.player.helper;
public class MyValue {
// 现场表演
public static final String PAGE_TYPE_MV_LIST="MUSIC_PAGE_TYPE_USER_CHANNEL";
//个人live
public static final String PAGE_TYPE_MV="MUSIC_PAGE_TYPE_ARTIST";
//风格音乐合集乡村音乐
public static final String PAGE_TYPE_LIST="MUSIC_PAGE_TYPE_PLAYLIST";
//专辑
public static final String PAGE_TYPE_ALBUM="MUSIC_PAGE_TYPE_ALBUM";
//-----------------------------PlayActivity
/**
* 歌手单曲进入的数据key
*/
public static String KEY_PLAY_ACTIVITY_SINGER = "click_singer";
/**
* 音乐列表进入的数据key和点击的列表位置key
*/
public static String KEY_PLAY_ACTIVITY_CATEGORY_LIST = "click_category_list";
public static String KEY_PLAY_ACTIVITY_CATEGORY_LIST_INDEX = "click_category_list_index";
/**
* MV进入的数据key
*/
public static String KEY_PLAY_ACTIVITY_MV = "click_mv";
/**
* 进入PlayActivity传递的即将播放的歌曲videoId
*/
public static String KEY_PLAY_VIDEO_ID = "video_id";
/**
* 进入PlayActivity传递的即将播放的歌曲index(针对在进入PlayActivity之前已经调用vmApplication.reSetPlayList
* 重置了播放列表的情况)
*/
public static String KEY_PLAY_INDEX = "play_index";
//播放错误
public final static int PLAY_STATUS_CODE_ERROR = -1;
//正在播放
public final static int PLAY_STATUS_CODE_PLAYING = -2;
//暂停或者停止
public final static int PLAY_STATUS_CODE_PAUSE = -3;
//切歌
public final static int PLAY_STATUS_CHANGE_MUSIC= -4;
/**
* 进入播放页面的来源
* 0--首页单曲进入 1--首页音乐分类合集列表进入 2--首页单个视频mv进入
* 3--控制面板进入
*/
public static String KEY_ENTER_SOURCE = "ENTER_SOURCE";
public final static int TYPE_ENTER_SOURCE_SINGLE = 0;
public final static int TYPE_ENTER_SOURCE_CATEGORY = 1;
public final static int TYPE_ENTER_SOURCE_MV = 2;
public final static int TYPE_ENTER_PANEL = 3;
//从喜爱歌曲进入
public final static int TYPE_ENTER_LIKE= 4;
//从下载歌曲进入
public final static int TYPE_ENTER_DOWNLOAD= 5;
//-----------------------------CategoryListActivity
public static String KEY_PLAY_ACTIVITY_CATEGORY= "click_category";
public static String KEY_CATEGORY_LIST_TYPE= "page_type";
public static String KEY_CATEGORY_LIST_SINGER_NAME= "singer_name";
public static String KEY_CATEGORY_LIST_BROWSER_ID= "browser_id";
//------------------------ResultListActivity
public static String KEY_SEARCH_RESULT_BROWSER_ID= "search_result_browser_id";
//---------------------LikeSongActivity
public static String KEY_ENTER_LIKE_ACTIVITY_TYPE = "song_type";
public final static int KEY_ENTER_LIKE_ACTIVITY_TYPE_LIKE = 0;
public final static int KEY_ENTER_LIKE_ACTIVITY_TYPE_DOWNLOAD = 1;
}

View File

@ -1,31 +0,0 @@
package com.hi.music.player.helper;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import com.hi.music.player.MusicApplication;
public class ViewModelScope {
private ViewModelProvider mFragmentProvider;
private ViewModelProvider mActivityProvider;
private ViewModelProvider mApplicationProvider;
public <T extends ViewModel> T getFragmentScopeViewModel(@NonNull Fragment fragment, @NonNull Class<T> modelClass) {
if (mFragmentProvider == null) mFragmentProvider = new ViewModelProvider(fragment);
return mFragmentProvider.get(modelClass);
}
public <T extends ViewModel> T getActivityScopeViewModel(@NonNull AppCompatActivity activity, @NonNull Class<T> modelClass) {
if (mActivityProvider == null) mActivityProvider = new ViewModelProvider(activity);
return mActivityProvider.get(modelClass);
}
public <T extends ViewModel> T getApplicationScopeViewModel(@NonNull Class<T> modelClass) {
if (mApplicationProvider == null)
mApplicationProvider = new ViewModelProvider(BaseViewModelStoreOwner.getInstance());
return mApplicationProvider.get(modelClass);
}
}

View File

@ -1,88 +0,0 @@
package com.hi.music.player.javabean;
import io.objectbox.annotation.Entity;
import io.objectbox.annotation.Id;
@Entity
public class BoxDownloadSong {
@Id
public long id;
private String songName;
private String singerName;
private String videoId;
private String covert;
private long durationMs;
private String duration ;
// 音视频文件uri
private String videoUrl ;
public BoxDownloadSong( ) {
}
public BoxDownloadSong(String songName, String singerName, String videoId, String covert, long durationMs, String duration) {
this.songName = songName;
this.singerName = singerName;
this.videoId = videoId;
this.covert = covert;
this.durationMs = durationMs;
this.duration = duration;
}
public String getVideoUrl() {
return videoUrl;
}
public void setVideoUrl(String videoUrl) {
this.videoUrl = videoUrl;
}
public long getDurationMs() {
return durationMs;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public void setDurationMs(long durationMs) {
this.durationMs = durationMs;
}
public String getSingerName() {
return singerName;
}
public void setSingerName(String singerName) {
this.singerName = singerName;
}
public String getVideoId() {
return videoId;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public String getCovert() {
return covert;
}
public void setCovert(String covert) {
this.covert = covert;
}
public String getSongName() {
return songName;
}
public void setSongName(String songName) {
this.songName = songName;
}
}

View File

@ -1,80 +0,0 @@
package com.hi.music.player.javabean;
import io.objectbox.annotation.Entity;
import io.objectbox.annotation.Id;
@Entity
public class BoxLikeSong {
@Id
public long id;
private String songName;
private String singerName;
private String videoId;
private String covert;
private long durationMs;
private String duration ;
public BoxLikeSong( ) {
}
public BoxLikeSong(String songName, String singerName, String videoId, String covert,long durationMs,String duration) {
this.songName = songName;
this.singerName = singerName;
this.videoId = videoId;
this.covert = covert;
this.durationMs = durationMs;
this.duration = duration;
}
public long getDurationMs() {
return durationMs;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public void setDurationMs(long durationMs) {
this.durationMs = durationMs;
}
public String getSingerName() {
return singerName;
}
public void setSingerName(String singerName) {
this.singerName = singerName;
}
public String getVideoId() {
return videoId;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public String getCovert() {
return covert;
}
public void setCovert(String covert) {
this.covert = covert;
}
public String getSongName() {
return songName;
}
public void setSongName(String songName) {
this.songName = songName;
}
}

View File

@ -1,24 +0,0 @@
package com.hi.music.player.javabean;
import androidx.media3.exoplayer.offline.Download;
public class CustomerDownload {
private Download download;
private boolean isDownload;
public CustomerDownload(Download download, boolean isDownload) {
this.download = download;
this.isDownload = isDownload;
}
public Download getDownloadData() {
return download;
}
public boolean isDownload() {
return isDownload;
}
}

View File

@ -1,44 +0,0 @@
package com.hi.music.player.javabean;
import com.hi.music.player.javabean.response.ResponsePlayUrl;
public class CustomerUrlInfo {
private ResponsePlayUrl playUrl;
private int playMusicIndex;
private boolean needPlayNow;
private String videoId;
public String getVideoId() {
return videoId;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public ResponsePlayUrl getPlayUrl() {
return playUrl;
}
public void setPlayUrl(ResponsePlayUrl playUrl) {
this.playUrl = playUrl;
}
public int getPlayMusicIndex() {
return playMusicIndex;
}
public void setPlayMusicIndex(int playMusicIndex) {
this.playMusicIndex = playMusicIndex;
}
public boolean isNeedPlayNow() {
return needPlayNow;
}
public void setNeedPlayNow(boolean needPlayNow) {
this.needPlayNow = needPlayNow;
}
}

View File

@ -1,37 +0,0 @@
package com.hi.music.player.javabean.requestbody;
import com.hi.music.player.javabean.requestbody.child.ContextBody;
import java.io.Serializable;
/**
* 首页接口请求体
*/
public class BodyHome implements Serializable {
private String browseId = "FEmusic_home";
public String getBrowseId() {
return browseId;
}
public void setBrowseId(String browseId) {
this.browseId = browseId;
}
private ContextBody context = new ContextBody();
public ContextBody getContext() {
return context;
}
public void setContext(ContextBody context) {
this.context = context;
}
}

View File

@ -1,78 +0,0 @@
package com.hi.music.player.javabean.requestbody;
import com.hi.music.player.javabean.requestbody.child.ContextBody;
import java.io.Serializable;
/**
* 播放页面接口请求体
*/
public class BodyPlay implements Serializable {
private ContextBody context = new ContextBody();
private String tunerSettingValue = "AUTOMIX_SETTING_NORMAL";
private boolean isAudioOnly = true;
private Configs watchEndpointMusicSupportedConfigs = new Configs();
private int index;
private String playlistId;
private String videoId;
private String params;
private String playlistSetVideoId;
public static class Configs {
private String musicVideoType = "MUSIC_VIDEO_TYPE_ATV";
public String getMusicVideoType() {
return musicVideoType;
}
public void setMusicVideoType(String musicVideoType) {
this.musicVideoType = musicVideoType;
}
}
public ContextBody getContext() {
return context;
}
public void setContext(ContextBody context) {
this.context = context;
}
public void setTunerSettingValue(String tunerSettingValue) {
this.tunerSettingValue = tunerSettingValue;
}
public void setIndex(int index) {
this.index = index;
}
public void setPlaylistId(String playlistId) {
this.playlistId = playlistId;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public void setParams(String params) {
this.params = params;
}
public void setPlaylistSetVideoId(String playlistSetVideoId) {
this.playlistSetVideoId = playlistSetVideoId;
}
public Configs getWatchEndpointMusicSupportedConfigs() {
return watchEndpointMusicSupportedConfigs;
}
}

View File

@ -1,40 +0,0 @@
package com.hi.music.player.javabean.requestbody;
import com.hi.music.player.javabean.requestbody.child.ContextBody;
import java.io.Serializable;
/**
* 首页接口请求体
*/
public class BodyPlayUrl implements Serializable {
private String videoId ;
private ContextBody context = new ContextBody();
// private String key = "AIzaSyC9XL3ZjwddXya6X74dJOCTL-WEYFDNX30" ;
private String params ="CgIQBg";
public String getVideoId() {
return videoId;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public ContextBody getContext() {
return context;
}
public void setContext(ContextBody context) {
this.context = context;
}
}

View File

@ -1,34 +0,0 @@
package com.hi.music.player.javabean.requestbody;
import com.hi.music.player.javabean.requestbody.child.Client;
import com.hi.music.player.javabean.requestbody.child.ContextBody;
import java.io.Serializable;
/**
* 搜索建议接口
*/
public class BodySearch implements Serializable {
private String query = "";
private ContextBody context = new ContextBody();
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
public ContextBody getContext() {
return context;
}
public void setContext(ContextBody context) {
this.context = context;
}
}

View File

@ -1,34 +0,0 @@
package com.hi.music.player.javabean.requestbody;
import com.hi.music.player.javabean.requestbody.child.Client;
import com.hi.music.player.javabean.requestbody.child.ContextBody;
import java.io.Serializable;
/**
* 搜索建议接口
*/
public class BodySearchSuggestion implements Serializable {
private String input = "";
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
private ContextBody context = new ContextBody();
public ContextBody getContext() {
return context;
}
public void setContext(ContextBody context) {
this.context = context;
}
}

View File

@ -1,55 +0,0 @@
package com.hi.music.player.javabean.requestbody.child;
import java.io.Serializable;
import java.util.Locale;
public class Client implements Serializable {
private String clientName = "WEB_REMIX";
//1.20240506.01.00
private String clientVersion = "1.20220918";
private String hl = Locale.getDefault().getLanguage();
private String gl = "US";
private String platform = "DESKTOP";
private String visitorData;
public String getVisitorData() {
return visitorData;
}
public void setVisitorData(String visitorData) {
this.visitorData = visitorData;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public void setClientVersion(String clientVersion) {
this.clientVersion = clientVersion;
}
public void setPlatform(String platform) {
this.platform = platform;
}
public String getGl() {
return gl;
}
public void setGl(String gl) {
this.gl = gl;
}
public String getHl() {
return hl;
}
public void setHl(String hl) {
this.hl = hl;
}
}

View File

@ -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;
}
}
}

View File

@ -1,67 +0,0 @@
package com.hi.music.player.javabean.response;
import com.hi.music.player.javabean.response.child.ResponseCategoryListChild;
import java.io.Serializable;
import java.util.List;
public class ResponseCategoryList implements Serializable {
private String covert;
private String title;
private String description;
private String secondSubtitle;
private String singName;
private List<ResponsePlayListInfo> list;
public String getSingName() {
return singName;
}
public void setSingName(String singName) {
this.singName = singName;
}
public String getCovert() {
return covert;
}
public void setCovert(String covert) {
this.covert = covert;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getSecondSubtitle() {
return secondSubtitle;
}
public void setSecondSubtitle(String secondSubtitle) {
this.secondSubtitle = secondSubtitle;
}
public List<ResponsePlayListInfo> getList() {
return list;
}
public void setList(List<ResponsePlayListInfo> list) {
this.list = list;
}
}

View File

@ -1,68 +0,0 @@
package com.hi.music.player.javabean.response;
import androidx.annotation.Nullable;
import com.hi.music.player.javabean.response.child.ResponseHomeChild;
import java.util.List;
public class ResponseHome {
//用于更多数据请求的cit
private String clickTrackingParams;
//用于更多数据请求的ctoken
private String continuation;
@Nullable
//用于更多数据请求的visitorData(只有第一个接口会返回该值,youtubei/v1/browse?prettyPrint=false)
private String visitorData;
@Nullable
private String backgroundUrl;
private List<ResponseHomeChild> childList;
public List<ResponseHomeChild> getChildList() {
return childList;
}
public void setChildList(List<ResponseHomeChild> childList) {
this.childList = childList;
}
public String getClickTrackingParams() {
return clickTrackingParams;
}
public void setClickTrackingParams(String clickTrackingParams) {
this.clickTrackingParams = clickTrackingParams;
}
public String getContinuation() {
return continuation;
}
public void setContinuation(String continuation) {
this.continuation = continuation;
}
public String getVisitorData() {
return visitorData;
}
public void setVisitorData(String visitorData) {
this.visitorData = visitorData;
}
public String getBackgroundUrl() {
return backgroundUrl;
}
public void setBackgroundUrl(String backgroundUrl) {
this.backgroundUrl = backgroundUrl;
}
}

View File

@ -1,179 +0,0 @@
package com.hi.music.player.javabean.response;
import com.hi.music.player.helper.MyValue;
import java.io.Serializable;
/**
* 播放列表
*/
public class ResponsePlayListInfo implements Serializable {
//封面
private String covert;
//小尺寸封面
private String smallCovert;
//歌曲名字
private String SongTitle;
//歌手名字
private String SingerName;
//专辑名称
private String AlbumTitle;
//发行年份
private String Year;
//歌曲时长
private String Duration;
//歌曲时长 毫秒
private long DurationMs;
private String describe;
private String videoId;
private String playlistId;
private String params;
private String musicVideoType;
public ResponsePlayListInfo() {
}
public ResponsePlayListInfo(String covert, String songTitle, String singerName, long durationMs, String videoId,String duration) {
this.covert = covert;
SongTitle = songTitle;
SingerName = singerName;
DurationMs = durationMs;
this.Duration = duration;
this.videoId = videoId;
}
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
}
public String getSmallCovert() {
return smallCovert;
}
public void setSmallCovert(String smallCovert) {
this.smallCovert = smallCovert;
}
public long getDurationMs() {
return DurationMs;
}
public void setDurationMs(long durationMs) {
DurationMs = durationMs;
}
public String getDuration() {
return Duration;
}
public void setDuration(String duration) {
Duration = duration;
}
public String getCovert() {
return covert;
}
public void setCovert(String covert) {
this.covert = covert;
}
public String getSongTitle() {
return SongTitle;
}
public void setSongTitle(String songTitle) {
SongTitle = songTitle;
}
public String getSingerName() {
return SingerName;
}
public void setSingerName(String singerName) {
SingerName = singerName;
}
public String getAlbumTitle() {
return AlbumTitle;
}
public void setAlbumTitle(String albumTitle) {
AlbumTitle = albumTitle;
}
public String getYear() {
return Year;
}
public void setYear(String year) {
Year = year;
}
public String getVideoId() {
return videoId;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public String getPlaylistId() {
return playlistId;
}
public void setPlaylistId(String playlistId) {
this.playlistId = playlistId;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public String getMusicVideoType() {
return musicVideoType;
}
public void setMusicVideoType(String musicVideoType) {
this.musicVideoType = musicVideoType;
}
// public String getAudioUrlLow() {
// return audioUrlLow;
// }
//
// public void setAudioUrlLow(String audioUrlLow) {
// this.audioUrlLow = audioUrlLow;
// }
//
// public String getAudioUrlMedium() {
// return audioUrlMedium;
// }
//
// public void setAudioUrlMedium(String audioUrlMedium) {
// this.audioUrlMedium = audioUrlMedium;
// }
}

View File

@ -1,79 +0,0 @@
package com.hi.music.player.javabean.response;
/**
* 音频源地址
*/
public class ResponsePlayUrl {
private String status;
private String audioUrlLow;
private String audioUrlMedium;
private String videoId;
private String BigCovert;
private String videoUrlMedium;
public String getVideoUrlMedium() {
return videoUrlMedium;
}
public void setVideoUrlMedium(String videoUrlMedium) {
this.videoUrlMedium = videoUrlMedium;
}
public String getBigCovert() {
return BigCovert;
}
public void setBigCovert(String bigCovert) {
BigCovert = bigCovert;
}
public String getAudioUrlMedium() {
return audioUrlMedium;
}
public void setAudioUrlMedium(String audioUrlMedium) {
this.audioUrlMedium = audioUrlMedium;
}
///AUDIO_QUALITY_MEDIUMAUDIO_QUALITY_LOW
// private String audioQuality;
//
//
// public String getAudioQuality() {
// return audioQuality;
// }
//
// public void setAudioQuality(String audioQuality) {
// this.audioQuality = audioQuality;
// }
public String getVideoId() {
return videoId;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getAudioUrlLow() {
return audioUrlLow;
}
public void setAudioUrlLow(String audioUrlLow) {
this.audioUrlLow = audioUrlLow;
}
}

View File

@ -1,36 +0,0 @@
package com.hi.music.player.javabean.response;
import java.util.List;
public class ResponseResult {
private String mainTitle;
private String mainCovert;
private List<ResponseResultList> list;
public String getMainTitle() {
return mainTitle;
}
public void setMainTitle(String mainTitle) {
this.mainTitle = mainTitle;
}
public String getMainCovert() {
return mainCovert;
}
public void setMainCovert(String mainCovert) {
this.mainCovert = mainCovert;
}
public List<ResponseResultList> getList() {
return list;
}
public void setList(List<ResponseResultList> list) {
this.list = list;
}
}

View File

@ -1,29 +0,0 @@
package com.hi.music.player.javabean.response;
import com.hi.music.player.javabean.response.child.ResponseResultListChild;
import java.util.List;
public class ResponseResultList {
private String headerTitle;
private List<ResponseResultListChild> childList;
public String getHeaderTitle() {
return headerTitle;
}
public void setHeaderTitle(String headerTitle) {
this.headerTitle = headerTitle;
}
public List<ResponseResultListChild> getChildList() {
return childList;
}
public void setChildList(List<ResponseResultListChild> childList) {
this.childList = childList;
}
}

View File

@ -1,90 +0,0 @@
package com.hi.music.player.javabean.response;
import com.hi.music.player.javabean.response.child.ResponseSearchChild;
import java.util.List;
public class ResponseSearch {
private String headerTitle;
private String beastSongTitle;
private String beastSongTCovert;
private String beastSongDescribe;
private String beastBrowserId;
private String beastVideoId;
private String pageType;
private List<ResponseSearchChild> list;
public String getBeastVideoId() {
return beastVideoId;
}
public void setBeastVideoId(String beastVideoId) {
this.beastVideoId = beastVideoId;
}
public String getHeaderTitle() {
return headerTitle;
}
public void setHeaderTitle(String headerTitle) {
this.headerTitle = headerTitle;
}
public List<ResponseSearchChild> getList() {
return list;
}
public void setList(List<ResponseSearchChild> list) {
this.list = list;
}
public String getBeastSongTitle() {
return beastSongTitle;
}
public void setBeastSongTitle(String beastSongTitle) {
this.beastSongTitle = beastSongTitle;
}
public String getBeastSongTCovert() {
return beastSongTCovert;
}
public void setBeastSongTCovert(String beastSongTCovert) {
this.beastSongTCovert = beastSongTCovert;
}
public String getBeastSongDescribe() {
return beastSongDescribe;
}
public void setBeastSongDescribe(String beastSongDescribe) {
this.beastSongDescribe = beastSongDescribe;
}
public String getBeastBrowserId() {
return beastBrowserId;
}
public void setBeastBrowserId(String beastBrowserId) {
this.beastBrowserId = beastBrowserId;
}
public String getPageType() {
return pageType;
}
public void setPageType(String pageType) {
this.pageType = pageType;
}
}

View File

@ -1,117 +0,0 @@
package com.hi.music.player.javabean.response.child;
import java.io.Serializable;
public class ResponseCategory implements Serializable {
//类别封面
private String covert;
//类别标题
private String twoTitle;
//类别描述
/**
* PAGE_TYPE_ALBUM : 专辑.歌手名字
* PAGE_TYPE_LIST 多个歌手名字
*/
private String twoSubtitle;
private String browseId;
private String videoId;
private String playListId;
private String params;
private String musicVideoType;
/**
* 视频Mv合集
*MUSIC_PAGE_TYPE_USER_CHANNEL
*
* 视频Mv单个
* MUSIC_PAGE_TYPE_USER_CHANNEL
*
* 音乐合集列表
* MUSIC_PAGE_TYPE_PLAYLIST
*
* 专辑
*MUSIC_PAGE_TYPE_ALBUM
*/
private String pageType;
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public String getMusicVideoType() {
return musicVideoType;
}
public void setMusicVideoType(String musicVideoType) {
this.musicVideoType = musicVideoType;
}
public String getPlayListId() {
return playListId;
}
public void setPlayListId(String playListId) {
this.playListId = playListId;
}
public String getVideoId() {
return videoId;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public String getPageType() {
return pageType;
}
public void setPageType(String pageType) {
this.pageType = pageType;
}
public String getBrowseId() {
return browseId;
}
public void setBrowseId(String browseId) {
this.browseId = browseId;
}
public String getCovert() {
return covert;
}
public void setCovert(String covert) {
this.covert = covert;
}
public String getTwoTitle() {
return twoTitle;
}
public void setTwoTitle(String twoTitle) {
this.twoTitle = twoTitle;
}
public String getTwoSubtitle() {
return twoSubtitle;
}
public void setTwoSubtitle(String twoSubtitle) {
this.twoSubtitle = twoSubtitle;
}
}

View File

@ -1,44 +0,0 @@
package com.hi.music.player.javabean.response.child;
public class ResponseCategoryListChild {
private String SongTitle;
private String SingerName;
private String SongCovert;
private String SongDuration;
public String getSongCovert() {
return SongCovert;
}
public void setSongCovert(String songCovert) {
SongCovert = songCovert;
}
public String getSongDuration() {
return SongDuration;
}
public void setSongDuration(String songDuration) {
SongDuration = songDuration;
}
public String getSongTitle() {
return SongTitle;
}
public void setSongTitle(String songTitle) {
SongTitle = songTitle;
}
public String getSingerName() {
return SingerName;
}
public void setSingerName(String singerName) {
SingerName = singerName;
}
}

View File

@ -1,36 +0,0 @@
package com.hi.music.player.javabean.response.child;
import java.util.List;
public class ResponseHomeChild {
private String HeaderTitle;
private List<ResponseSingle> singleList;
private List<ResponseCategory> categoryList;
public String getHeaderTitle() {
return HeaderTitle;
}
public void setHeaderTitle(String headerTitle) {
HeaderTitle = headerTitle;
}
public List<ResponseSingle> getSingleList() {
return singleList;
}
public void setSingleList(List<ResponseSingle> singleList) {
this.singleList = singleList;
}
public List<ResponseCategory> getCategoryList() {
return categoryList;
}
public void setCategoryList(List<ResponseCategory> categoryList) {
this.categoryList = categoryList;
}
}

View File

@ -1,85 +0,0 @@
package com.hi.music.player.javabean.response.child;
public class ResponseResultListChild {
private String thumbnail;
private String songName;
private String subTitle;
private String playCount;
private String videoId;
private String playListId;
private String browserId;
private String pageType;
public String getThumbnail() {
return thumbnail;
}
public void setThumbnail(String thumbnail) {
this.thumbnail = thumbnail;
}
public String getSongName() {
return songName;
}
public void setSongName(String songName) {
this.songName = songName;
}
public String getSubTitle() {
return subTitle;
}
public void setSubTitle(String subTitle) {
this.subTitle = subTitle;
}
public String getBrowserId() {
return browserId;
}
public void setBrowserId(String browserId) {
this.browserId = browserId;
}
public String getPageType() {
return pageType;
}
public void setPageType(String pageType) {
this.pageType = pageType;
}
public String getPlayCount() {
return playCount;
}
public void setPlayCount(String playCount) {
this.playCount = playCount;
}
public String getVideoId() {
return videoId;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public String getPlayListId() {
return playListId;
}
public void setPlayListId(String playListId) {
this.playListId = playListId;
}
}

View File

@ -1,75 +0,0 @@
package com.hi.music.player.javabean.response.child;
public class ResponseSearchChild {
private String songTitle;
private String songCovert;
private String songDescribe;
private String songPlayCount;
private String songVideoId;
private String browserId;
private String pageType;
public String getBrowserId() {
return browserId;
}
public void setBrowserId(String browserId) {
this.browserId = browserId;
}
public String getPageType() {
return pageType;
}
public void setPageType(String pageType) {
this.pageType = pageType;
}
public String getSongTitle() {
return songTitle;
}
public void setSongTitle(String songTitle) {
this.songTitle = songTitle;
}
public String getSongCovert() {
return songCovert;
}
public void setSongCovert(String songCovert) {
this.songCovert = songCovert;
}
public String getSongDescribe() {
return songDescribe;
}
public void setSongDescribe(String songDescribe) {
this.songDescribe = songDescribe;
}
public String getSongPlayCount() {
return songPlayCount;
}
public void setSongPlayCount(String songPlayCount) {
this.songPlayCount = songPlayCount;
}
public String getSongVideoId() {
return songVideoId;
}
public void setSongVideoId(String songVideoId) {
this.songVideoId = songVideoId;
}
}

View File

@ -1,91 +0,0 @@
package com.hi.music.player.javabean.response.child;
import java.io.Serializable;
public class ResponseSingle implements Serializable {
//歌手头像
private String SingerHead;
//歌曲名字
private String SongTitle;
//歌手名字
private String SingerName;
//描述
private String Description;
private String videoId;
private String playlistId;
private String params;
private String musicVideoType;
public String getSingerHead() {
return SingerHead;
}
public void setSingerHead(String singerHead) {
SingerHead = singerHead;
}
public String getSongTitle() {
return SongTitle;
}
public void setSongTitle(String songTitle) {
SongTitle = songTitle;
}
public String getSingerName() {
return SingerName;
}
public void setSingerName(String singerName) {
SingerName = singerName;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public void setPlaylistId(String playlistId) {
this.playlistId = playlistId;
}
public void setParams(String params) {
this.params = params;
}
public void setMusicVideoType(String musicVideoType) {
this.musicVideoType = musicVideoType;
}
public String getVideoId() {
return videoId;
}
public String getPlaylistId() {
return playlistId;
}
public String getParams() {
return params;
}
public String getMusicVideoType() {
return musicVideoType;
}
}

View File

@ -1,154 +0,0 @@
package com.hi.music.player.media3;
import android.net.Uri;
import androidx.media3.common.MediaItem;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.datasource.DataSource;
import androidx.media3.datasource.DataSpec;
import androidx.media3.datasource.DefaultDataSource;
import androidx.media3.datasource.DefaultDataSourceFactory;
import androidx.media3.datasource.DefaultHttpDataSource;
import androidx.media3.datasource.ResolvingDataSource;
import androidx.media3.datasource.cache.CacheDataSource;
import androidx.media3.datasource.cache.SimpleCache;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.drm.DrmSessionManagerProvider;
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.source.MediaSourceFactory;
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
import com.hi.music.player.MusicApplication;
import com.hi.music.player.api.RequestListener;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.response.ResponsePlayUrl;
import com.hi.music.player.network.JsonHelper;
import com.hi.music.player.network.RetrofitManager;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.ResponseBody;
public class DynamicMediaSourceFactory implements MediaSource.Factory {
private DataSource.Factory mediaSourceFactory;
private SimpleCache simpleCache;
public DynamicMediaSourceFactory(DataSource.Factory factory) {
this.mediaSourceFactory = factory;
}
@UnstableApi
@Override
public MediaSource.Factory setDrmSessionManagerProvider(DrmSessionManagerProvider drmSessionManagerProvider) {
return null;
}
@UnstableApi
@Override
public MediaSource.Factory setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
return null;
}
@UnstableApi
@Override
public int[] getSupportedTypes() {
return new int[0];
}
@UnstableApi
@Override
public MediaSource createMediaSource(MediaItem mediaItem) {
CommonUtils.LogMsg("------createMediaSource----------=" + mediaItem.mediaId + "---------" + mediaItem.mediaMetadata.title);
// DefaultHttpDataSource.Factory httpDataSourceFactory = new DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true);
// 这里的DefaultDataSource同时支持本地和HTTP请求的资源自动实现检测 The DefaultDataSource supports both local and Http sources. It automatically detects which one to use.
//实现缓存
// CacheDataSource.Factory cacheDataSourceFactory = new CacheDataSource.Factory()
// .setCache(simpleCache)
// .setUpstreamDataSourceFactory(mediaSourceFactory)
// .setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
MediaSource mediaSource = new ProgressiveMediaSource.Factory(mediaSourceFactory)
.createMediaSource(mediaItem);
return mediaSource;
// return new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
// .createMediaSource(MediaItem.fromUri(responsePlayUrl.getAudioUrlMedium()));
// 可以在这里根据 mediaItem ID 动态生成新的 URI
// String updatedUri = "https://rr1---sn-tt1e7nlz.googlevideo.com/videoplayback?expire=1727628605&ei=3TD5ZuWFEe-yzN0P27WuqQ4&ip=146.19.167.8&id=o-ANGM0PjEvsfYH7TmYV_DFuD-65tipJeeLe2URDOk90sL&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=xj&mm=31%2C29&mn=sn-tt1e7nlz%2Csn-vgqsknsk&ms=au%2Crdu&mv=m&mvi=1&pl=24&pcm2=no&gcr=us&initcwndbps=7610000&vprv=1&svpuc=1&mime=audio%2Fmp4&rqh=1&gir=yes&clen=5440168&dur=335.973&lmt=1709326903801285&mt=1727606690&fvip=5&keepalive=yes&fexp=51299152&c=ANDROID_MUSIC&txp=2318224&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cpcm2%2Cgcr%2Cvprv%2Csvpuc%2Cmime%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhALmM_S8Cmagr60muB3wDOby0OdcjF-x6f7TcEenixH0KAiAnR0-hmA03MeVzSg2wi5ncJ4Ve5FFlpZnlSoRNGWgGhQ%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=ABPmVW0wRQIhAPv5slfEnf8_E7o6yjEkussQ6JIFFaSY6QtP9HXncTTcAiAjlhMa71t76Wu1R1rcmsHoO6pyxjhGYouio4D0deJqEA%3D%3D";
// Uri updateUri = null;
//
// MediaItem.Builder builder = mediaItem.buildUpon();
// if (mediaItem.localConfiguration != null) {
// updateUri = mediaItem.localConfiguration.uri;
// builder.setUri(updateUri);
// CommonUtils.LogErrorMsg("----updateUri=成功 builder="+mediaItem.mediaId+"--updateUri="+updateUri);
// }else {
// CommonUtils.LogErrorMsg("----updateUri=null builder="+mediaItem.mediaId);
// }
// return mediaSourceFactory.createMediaSource(builder.build());
}
// @UnstableApi
// @Override
// public DataSource createDataSource() {
//
//
//
//
//// RetrofitManager.getInstance().getPlayUrl(mediaItem.mediaId, new RequestListener<ResponseBody>() {
////
//// @Override
//// public void onFail(String errorMsg) {
////
//// }
////
//// @Override
//// public void onSuccess(ResponseBody data) {
//// JSONObject jsonObject = CommonUtils.toJsonObject(data);
//// if (jsonObject != null) {
//// ResponsePlayUrl responsePlayUrl = JsonHelper.ResolvePlayUrlJson(jsonObject);
//// if (responsePlayUrl == null) {
//// // TODO: 2024/9/27
//// return;
//// }
//// String uri = "";
//// if (responsePlayUrl.getAudioUrlMedium() != null) {
//// uri = responsePlayUrl.getAudioUrlMedium();
//// } else {
//// uri = responsePlayUrl.getAudioUrlLow();
//// }
//// CommonUtils.LogMsg("------createMediaSource----------="+mediaItem.mediaId+"---------"+uri);
//// ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
//// .createMediaSource(MediaItem.fromUri(uri));
//// player.setMediaSource(mediaSource);
//// player.prepare();
////
//// }
////
////
//// }
//// });
// return null;
// }
}

View File

@ -1,13 +0,0 @@
package com.hi.music.player.media3;
import android.content.Context;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.ui.PlayerControlView;
@UnstableApi
public class MyControllerView extends PlayerControlView{
public MyControllerView(Context context) {
super(context);
}
}

View File

@ -1,35 +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.NoOpCacheEvictor;
import androidx.media3.datasource.cache.SimpleCache;
import com.hi.music.player.MusicApplication;
import java.io.File;
/**
* 下载缓存
*/
public class MyDownloadCacheManager {
private static SimpleCache downloadCache;
@OptIn(markerClass = UnstableApi.class)
public static SimpleCache getMyCache(StandaloneDatabaseProvider databaseProvider){
if(downloadCache == null){
Context myApplication = MusicApplication.myApplication;
File musicApp = new File(myApplication.getCacheDir(), "Music_App");
downloadCache = new SimpleCache(musicApp, new NoOpCacheEvictor(), databaseProvider);
}
return downloadCache;
}
}

View File

@ -1,193 +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;
public MyDownloadService() {
super(FOREGROUND_NOTIFICATION_ID,
DEFAULT_FOREGROUND_NOTIFICATION_UPDATE_INTERVAL,
CHANNEL_ID, // 通知渠道 ID
R.string.app_name, // 通知渠道名称
0
);
}
public static void init(Context context, StandaloneDatabaseProvider databaseProvider) {
if (mDownloadManager == null) {
SimpleCache 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);
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -1,119 +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.ResolvingDataSource;
import androidx.media3.datasource.TransferListener;
import androidx.media3.datasource.cache.CacheDataSource;
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;
public class PlaybackService extends MediaSessionService {
private MediaSession mediaSession = null;
private ExoPlayer player;
@OptIn(markerClass = UnstableApi.class)
@Override
public void onCreate() {
super.onCreate();
DynamicMediaSourceFactory customMediaSourceFactory = new DynamicMediaSourceFactory(getCacheDataSourceFactory(this));
DefaultMediaSourceFactory defaultMediaSourceFactory1 = new DefaultMediaSourceFactory(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(mediaSourceFactory)
.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);
return new CacheDataSource.Factory()
.setCache(MyPlayCacheManager.getInitPlayCache(context))
.setUpstreamDataSourceFactory(factory)
.setFlags(CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
// .setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
}
@OptIn(markerClass = UnstableApi.class)
private DataSource.Factory getUrlFactory() {
CommonUtils.LogMsg("--------getUrlFactory");
return new ResolvingDataSource.Factory(getCacheDataSourceFactory(this), new ResolvingDataSource.Resolver() {
@Override
public DataSpec resolveDataSpec(DataSpec dataSpec) {
CommonUtils.LogMsg("--------resolveDataSpec=" + dataSpec.key);
String string = "https://rr5---sn-ab5sznzy.googlevideo.com//videoplayback?expire=1730814877&ei=PM8pZ_37PL6b2_gP1LeTsQY&ip=146.19.167.8&id=o-AOdAohYUdM95I2jXmxqV5-JBeVgnMYAS3AKn2fsaiz72&itag=18&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&met=1730793277%2C&mh=Od&mm=31%2C29&mn=sn-ab5sznzy%2Csn-tt1e7nls&ms=au%2Crdu&mv=m&mvi=5&pl=24&rms=au%2Cau&gcr=us&initcwndbps=7066250&vprv=1&svpuc=1&xtags=heaudio%3Dtrue&mime=video%2Fmp4&rqh=1&cnr=14&ratebypass=yes&dur=181.394&lmt=1711913129189608&mt=1730792707&fvip=2&fexp=51312688%2C51326932&c=ANDROID&txp=4538434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cgcr%2Cvprv%2Csvpuc%2Cxtags%2Cmime%2Crqh%2Ccnr%2Cratebypass%2Cdur%2Clmt&sig=AJfQdSswRgIhAMmdioipTMb9rGt1ZIzbhTPL0yWZGnuorRv7jOS9THllAiEAnkSJJhOkXt3SdMYmeNuRMEosaJl2H00SQxORzbbGRP4%3D&lsparams=met%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Crms%2Cinitcwndbps&lsig=ACJ0pHgwRQIhANId6hdBj5z2g7IWnbCdzQ6MyYO_wit31Zaxh3VWahe7AiAIlubSJiPZP4deLNaBQ8eyT12Zf7nPkJ_ZZYBHeFf9XA%3D%3D";
return dataSpec.withUri(Uri.parse(dataSpec.key));
}
});
}
@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();
}
}

View File

@ -1,73 +0,0 @@
package com.hi.music.player.media3;
import androidx.media3.common.MediaItem;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.datasource.DataSource;
import androidx.media3.exoplayer.drm.DrmSessionManagerProvider;
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
import com.hi.music.player.helper.CommonUtils;
public class testSourceFactory implements DataSource.Factory {
// private final CacheDataSource.Factory cacheDataSourceFactory;
// private final ExoPlayer player;
private DefaultMediaSourceFactory mediaSourceFactory;
// public DynamicMediaSourceFactory(DefaultMediaSourceFactory factory,CacheDataSource.Factory cacheDataSourceFactory, ExoPlayer exoPlayer) {
// this.cacheDataSourceFactory = cacheDataSourceFactory;
// this.player = exoPlayer;
// this.mediaSourceFactory = factory;
// }
public testSourceFactory(DefaultMediaSourceFactory factory) {
this.mediaSourceFactory = factory;
}
@UnstableApi
@Override
public DataSource createDataSource() {
// RetrofitManager.getInstance().getPlayUrl(mediaItem.mediaId, new RequestListener<ResponseBody>() {
//
// @Override
// public void onFail(String errorMsg) {
//
// }
//
// @Override
// public void onSuccess(ResponseBody data) {
// JSONObject jsonObject = CommonUtils.toJsonObject(data);
// if (jsonObject != null) {
// ResponsePlayUrl responsePlayUrl = JsonHelper.ResolvePlayUrlJson(jsonObject);
// if (responsePlayUrl == null) {
// // TODO: 2024/9/27
// return;
// }
// String uri = "";
// if (responsePlayUrl.getAudioUrlMedium() != null) {
// uri = responsePlayUrl.getAudioUrlMedium();
// } else {
// uri = responsePlayUrl.getAudioUrlLow();
// }
// CommonUtils.LogMsg("------createMediaSource----------="+mediaItem.mediaId+"---------"+uri);
// ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
// .createMediaSource(MediaItem.fromUri(uri));
// player.setMediaSource(mediaSource);
// player.prepare();
//
// }
//
//
// }
// });
return null;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +0,0 @@
package com.hi.music.player.network;
import io.reactivex.Observable;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.POST;
import retrofit2.http.Query;
public interface MusicApi {
//首页数据
@POST("youtubei/v1/browse?prettyPrint=false")
@Headers("X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8")
Observable<ResponseBody> getHomeData(@Body RequestBody requestBody);
//首页更多数据
@POST("youtubei/v1/browse")
@Headers("X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8")
Observable<ResponseBody> getHomeMoreData(@Query("ctoken") String token,
@Query("continuation") String continuation,
@Query("type") String type,
@Query("itct") String itct,
@Query("prettyPrint") boolean prettyPrint,@Body RequestBody requestBody);
// X-Goog-FieldMask: contents.singleColumnMusicWatchNextResultsRenderer.tabbedRenderer.watchNextTabbedResultsRenderer.tabs.tabRenderer.content.musicQueueRenderer.content.playlistPanelRenderer(continuations,contents(automixPreviewVideoRenderer,playlistPanelVideoRenderer(title,navigationEndpoint,longBylineText,shortBylineText,thumbnail,lengthText)))
//获取播放列表(返回的是每首歌曲详情列表)
@POST("youtubei/v1/next?prettyPrint=false")
@Headers("X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8")
Observable<ResponseBody> getMusicPlayPage(@Header("X-Goog-FieldMask") String customHeader, @Body RequestBody requestBody);
// "X-Goog-FieldMask:playabilityStatus.status,playerConfig.audioConfig,streamingData.adaptiveFormats,videoDetails.videoId,videoDetails.thumbnail"
//获取播放音频资源url "X-Goog-Api-Key:AIzaSyC9XL3ZjwddXya6X74dJOCTL-WEYFDNX30"
@POST("youtubei/v1/player?prettyPrint=false")
@Headers({"X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"})
Observable<ResponseBody> getMusicPlayUrl(@Body RequestBody requestBody);
//首页分类项下的播放列表子页面 (类型1单曲合集2专辑3音乐视频合集 不同类型返回数据结构有区别)
@POST("youtubei/v1/browse?prettyPrint=false")
@Headers({"X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"})
Observable<ResponseBody> getCategoryList(@Body RequestBody requestBody);
@POST("youtubei/v1/music/get_search_suggestions?prettyPrint=false")
@Headers({"X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8",
"X-Goog-FieldMask:contents.searchSuggestionsSectionRenderer.contents.searchSuggestionRenderer.navigationEndpoint.searchEndpoint.query"})
Observable<ResponseBody> getSearchSuggestion(@Body RequestBody requestBody);
// "X-Goog-FieldMask:contents.tabbedSearchResultsRenderer.tabs.tabRenderer.content.sectionListRenderer.contents.musicShelfRenderer(continuations,contents.musicResponsiveListItemRenderer(flexColumns,fixedColumns,thumbnail,navigationEndpoint))"
@POST("youtubei/v1/search?prettyPrint=false")
@Headers({"X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"})
Observable<ResponseBody> getSearch(@Body RequestBody requestBody);
}

View File

@ -1,60 +0,0 @@
package com.hi.music.player.network;
import com.hi.music.player.api.RequestListener;
import com.hi.music.player.helper.CommonUtils;
import org.json.JSONException;
import org.json.JSONObject;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import okhttp3.ResponseBody;
public class ObserverWrapper<T> implements Observer<T> {
private RequestListener<T> requestListener;
public ObserverWrapper(RequestListener<T> requestListener) {
this.requestListener = requestListener;
}
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(T t) {
ResponseBody responseBody = (ResponseBody) t;
JSONObject jsonObject = CommonUtils.toJsonObject(responseBody);
try {
if (jsonObject != null) {
if (jsonObject.has("playabilityStatus")) {
String status = jsonObject.getJSONObject("playabilityStatus").getString("status");
if (!status.equals("OK")) {
requestListener.onFail("");
return;
}
}
requestListener.onSuccess(jsonObject);
}
} catch (JSONException e) {
requestListener.onFail(e.getMessage());
}
}
@Override
public void onError(Throwable e) {
CommonUtils.LogMsg("----------onError---" + e.getMessage());
requestListener.onFail(e.getMessage());
}
@Override
public void onComplete() {
}
}

View File

@ -1,212 +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);
}
// public <T> T getService(Class<T> cls){
// return getRetrofit().create(cls);
// }
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));
}
}

View File

@ -1,109 +0,0 @@
package com.hi.music.player.objectbox;
import android.content.Context;
import androidx.annotation.NonNull;
import com.hi.music.player.api.LikeSongListener;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.BoxLikeSong;
import com.hi.music.player.javabean.BoxLikeSong_;
import com.hi.music.player.javabean.MyObjectBox;
import java.util.List;
import io.objectbox.Box;
import io.objectbox.BoxStore;
import io.objectbox.android.AndroidScheduler;
import io.objectbox.query.Query;
import io.objectbox.query.QueryBuilder;
import io.objectbox.reactive.DataObserver;
import io.objectbox.reactive.DataSubscription;
import io.objectbox.reactive.DataSubscriptionList;
public class ObjectBoxManager {
private static BoxStore boxStore;
private static Box<BoxLikeSong> boxLikeSongBox;
private static DataSubscription observer;
public static void init(Context context) {
boxStore = MyObjectBox.builder().androidContext(context).build();
}
public static Box<BoxLikeSong> getObjectBoxLike() {
if (boxLikeSongBox == null) {
return boxStore.boxFor(BoxLikeSong.class);
}
return boxLikeSongBox;
}
public static DataSubscription setLikeDataListener(LikeSongListener listener) {
Query<BoxLikeSong> build = getObjectBoxLike().query().build();
return build.subscribe(new DataSubscriptionList())
.on(AndroidScheduler.mainThread())
.observer(new DataObserver<List<BoxLikeSong>>() {
@Override
public void onData(@NonNull List<BoxLikeSong> data) {
CommonUtils.LogMsg("------ProfileFragment 11data=" + data.size());
listener.onLikeSongChange(data);
}
});
}
public static void insertOrUpdateLike(BoxLikeSong boxLikeSong) {
Box<BoxLikeSong> objectBoxLike = getObjectBoxLike();
String videoId = boxLikeSong.getVideoId();
BoxLikeSong first = objectBoxLike.query()
.equal(BoxLikeSong_.videoId, videoId, QueryBuilder.StringOrder.CASE_SENSITIVE)
.build()
.findFirst();
if (first == null) {
CommonUtils.LogErrorMsg("-----------添加 song=" + boxLikeSong.getSongName() + "---videoId=" + videoId);
objectBoxLike.put(boxLikeSong);
} else {
CommonUtils.LogErrorMsg("-----------已经存在 song=" + boxLikeSong.getSongName() + "---videoId=" + videoId);
}
}
public static void deleteLike(BoxLikeSong boxLikeSong) {
Box<BoxLikeSong> objectBoxLike = getObjectBoxLike();
String videoId = boxLikeSong.getVideoId();
List<BoxLikeSong> boxLikeSongs = objectBoxLike.query()
.equal(BoxLikeSong_.videoId, videoId, QueryBuilder.StringOrder.CASE_SENSITIVE)
.build()
.find();
for (BoxLikeSong song : boxLikeSongs) {
objectBoxLike.remove(song);
CommonUtils.LogErrorMsg("-------onLikeSongChange-deleteLike song=" + song.getSongName());
}
}
public static List<BoxLikeSong> queryAllLike() {
return getObjectBoxLike().query()
.build()
.find();
}
public static boolean queryIsLike(String videoId) {
Box<BoxLikeSong> objectBoxLike = getObjectBoxLike();
BoxLikeSong first = objectBoxLike.query()
.equal(BoxLikeSong_.videoId, videoId, QueryBuilder.StringOrder.CASE_SENSITIVE)
.build()
.findFirst();
if (first == null) {
return false;
} else {
return true;
}
}
}

View File

@ -5,8 +5,6 @@ import android.os.CountDownTimer;
import android.view.View; import android.view.View;
import com.hi.music.player.databinding.ActivityAsplashBinding; import com.hi.music.player.databinding.ActivityAsplashBinding;
import com.hi.music.player.firebase.RemoteConfigJava;
import com.hi.music.player.firebase.Sp;
public class A_SplashActivity extends BaseActivity<ActivityAsplashBinding> { public class A_SplashActivity extends BaseActivity<ActivityAsplashBinding> {
@ -76,13 +74,7 @@ public class A_SplashActivity extends BaseActivity<ActivityAsplashBinding> {
} }
private void enterHome() { private void enterHome() {
String stringValue = Sp.getInstance().getStringValue(RemoteConfigJava.key_open_type); Intent intent = new Intent(A_SplashActivity.this, A_HomeActivity.class);
Intent intent;
if(stringValue.equals(RemoteConfigJava.value_open_type_0)){
intent = new Intent(A_SplashActivity.this, A_HomeActivity.class);
}else {
intent = new Intent(A_SplashActivity.this, HomeActivity.class);
}
startActivity(intent); startActivity(intent);
finish(); finish();

View File

@ -1,44 +1,23 @@
package com.hi.music.player.ui.activity; package com.hi.music.player.ui.activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.view.Gravity;
import android.view.View; import android.view.View;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.OptIn;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.WindowCompat; import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsControllerCompat; import androidx.core.view.WindowInsetsControllerCompat;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel; 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 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.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 { public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActivity implements View.OnClickListener {
private final ViewModelScope mViewModelScope = new ViewModelScope(); // private final ViewModelScope mViewModelScope = new ViewModelScope();
protected T vb; protected T vb;
@ -47,8 +26,8 @@ public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActiv
protected View mView; protected View mView;
private ActivityBaseBinding rootVb; private ActivityBaseBinding rootVb;
protected VMApplication vmApplication; // protected VMApplication vmApplication;
protected MyMediaControllerManager mediaControllerManager; // protected MyMediaControllerManager mediaControllerManager;
private Handler mHandler; private Handler mHandler;
private Runnable mRunnable; private Runnable mRunnable;
@ -64,11 +43,10 @@ public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActiv
window = getWindow(); window = getWindow();
decorView = window.getDecorView(); decorView = window.getDecorView();
mView = decorView.getRootView(); mView = decorView.getRootView();
vmApplication = getApplicationScopeViewModel(VMApplication.class); // vmApplication = getApplicationScopeViewModel(VMApplication.class);
mediaControllerManager = MyMediaControllerManager.getInstance(); // mediaControllerManager = MyMediaControllerManager.getInstance();
if (showPanel())
initPanel();
setStatusBar(); setStatusBar();
if (isFullScreen()) { if (isFullScreen()) {
// ImmersionBar.with(this).init();//设置沉浸式效果 // ImmersionBar.with(this).init();//设置沉浸式效果
@ -94,133 +72,11 @@ public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActiv
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())
.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() { private void setStatusBar() {
//深色模式 //深色模式
WindowInsetsControllerCompat insetsController = WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView()); WindowInsetsControllerCompat insetsController = WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView());
@ -234,13 +90,13 @@ public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActiv
mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} }
protected <K extends ViewModel> K getActivityScopeViewModel(@NonNull Class<K> modelClass) { // protected <K extends ViewModel> K getActivityScopeViewModel(@NonNull Class<K> modelClass) {
return mViewModelScope.getActivityScopeViewModel(this, modelClass); // return mViewModelScope.getActivityScopeViewModel(this, modelClass);
} // }
//
protected <K extends ViewModel> K getApplicationScopeViewModel(@NonNull Class<K> modelClass) { // protected <K extends ViewModel> K getApplicationScopeViewModel(@NonNull Class<K> modelClass) {
return mViewModelScope.getApplicationScopeViewModel(modelClass); // return mViewModelScope.getApplicationScopeViewModel(modelClass);
} // }
@Override @Override
protected void onDestroy() { protected void onDestroy() {

View File

@ -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.drawable.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();
}
}

View File

@ -1,131 +0,0 @@
package com.hi.music.player.ui.activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import androidx.core.content.ContextCompat;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.hi.music.player.MusicApplication;
import com.hi.music.player.R;
import com.hi.music.player.adapter.HomeViewPagerAdapter;
import com.hi.music.player.databinding.ActivityHomeBinding;
import com.hi.music.player.databinding.HomeTabCustomBinding;
import com.hi.music.player.helper.CommonUtils;
public class HomeActivity extends BaseActivity<ActivityHomeBinding> {
// 图标数组定义为类成员避免重复
private final int[] defaultIcons = {
R.drawable.home_unselect,
R.drawable.search_unselect,
R.drawable.profile_unselect
};
private final int[] selectedIcons = {
R.drawable.home_select,
R.drawable.search_select,
R.drawable.profile_select
};
@Override
protected ActivityHomeBinding getViewBinding() {
return ActivityHomeBinding.inflate(getLayoutInflater());
}
@Override
protected void onCreateInit() {
initView(); // 可以在这里初始化视图
}
@Override
protected void onInitClick() {
}
@Override
public boolean isFullScreen() {
return true;
}
@Override
public boolean statusBarLight() {
return false;
}
@Override
public boolean showPanel() {
return true;
}
public void initView() {
int statusBarHeight = CommonUtils.getStatusBarHeight(MusicApplication.myApplication);
View root = vb.getRoot();
root.setPadding(0,statusBarHeight,0,0);
HomeViewPagerAdapter adapter = new HomeViewPagerAdapter(this);
vb.homeViewPager.setAdapter(adapter);
vb.homeViewPager.setUserInputEnabled(false);
// 设置TabLayout的图标
new TabLayoutMediator(vb.homeTabLayout, vb.homeViewPager, (tab, position) -> {
HomeTabCustomBinding tabBinding = HomeTabCustomBinding.inflate(LayoutInflater.from(this));
tab.setCustomView(tabBinding.getRoot());
tabBinding.homeIcon.setImageResource(defaultIcons[position]); // 默认图标
}).attach();
// 添加Tab选中与未选中事件监听器
vb.homeTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
updateTabIcon(tab, true); // 更新选中的图标
int position = tab.getPosition();
switch (position){
case 0:
vb.view.setVisibility(View.VISIBLE);
vb.homeLayout.setBackgroundColor(ContextCompat.getColor(HomeActivity.this,R.color.black));
break;
case 1:
vb.view.setVisibility(View.GONE);
vb.homeLayout.setBackgroundColor(ContextCompat.getColor(HomeActivity.this,R.color.default_play_list_color));
break;
case 2:
vb.view.setVisibility(View.GONE);
vb.homeLayout.setBackground(ContextCompat.getDrawable(HomeActivity.this,R.mipmap.bg_library));
break;
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
updateTabIcon(tab, false); // 恢复未选中图标
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
// 可选重复选择Tab时的操作
}
});
// 设置默认选中第一个
TabLayout.Tab firstTab = vb.homeTabLayout.getTabAt(0);
if (firstTab != null) {
firstTab.select();
updateTabIcon(firstTab, true); // 设置选中的图标
}
}
private void updateTabIcon(TabLayout.Tab tab, boolean isSelected) {
HomeTabCustomBinding tabBinding = HomeTabCustomBinding.bind(tab.getCustomView());
int position = tab.getPosition();
tabBinding.homeIcon.setImageResource(isSelected ? selectedIcons[position] : defaultIcons[position]);
}
@Override
public void onClick(View v) {
}
}

View File

@ -1,171 +0,0 @@
package com.hi.music.player.ui.activity;
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 androidx.media3.exoplayer.offline.DownloadManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.hi.music.player.R;
import com.hi.music.player.adapter.AdapterDownloadSong;
import com.hi.music.player.adapter.AdapterLikeSong;
import com.hi.music.player.api.HomeItemClickListener;
import com.hi.music.player.databinding.ActivityLikeSongBinding;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.helper.MyValue;
import com.hi.music.player.javabean.BoxLikeSong;
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
import com.hi.music.player.media3.MyDownloadService;
import com.hi.music.player.objectbox.ObjectBoxManager;
import java.util.ArrayList;
import java.util.List;
public class LikeSongActivity extends BaseActivity<ActivityLikeSongBinding> implements HomeItemClickListener {
private List<BoxLikeSong> boxLikeSongs;
private int mType;
private List<Pair<Integer, String>> downloadList = new ArrayList<>();
@Override
protected ActivityLikeSongBinding getViewBinding() {
return ActivityLikeSongBinding.inflate(getLayoutInflater());
}
@OptIn(markerClass = UnstableApi.class)
@Override
protected void onCreateInit() {
Intent intent = getIntent();
mType = intent.getIntExtra(MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE, MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE_LIKE);
switch (mType) {
case MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE_LIKE:
vb.tvTitle.setText(getString(R.string.text_like_song));
boxLikeSongs = ObjectBoxManager.queryAllLike();
AdapterLikeSong adapterLikeSong = new AdapterLikeSong(this, vmApplication);
adapterLikeSong.setHomeItemClickListener(this);
adapterLikeSong.setData(boxLikeSongs);
vb.recycler.setLayoutManager(new LinearLayoutManager(this));
vb.recycler.setAdapter(adapterLikeSong);
vb.tvSongSize.setText(String.format(getString(R.string.like_song), boxLikeSongs.size()));
MyDownloadService.addDownloadListener(vmApplication);
vmApplication.downloadChange.observe(this, new Observer<Pair<Boolean, Download>>() {
@Override
public void onChanged(Pair<Boolean, Download> booleanDownloadPair) {
Boolean first = booleanDownloadPair.first;
Download downloads = booleanDownloadPair.second;
String id = downloads.request.id;
for (Pair<Integer,String> pair:downloadList){
Integer position = pair.first;
String videoId = pair.second;
if(id.equals(videoId)){
adapterLikeSong.updateDownloadStatus(first,position,videoId);
}
}
}
});
break;
case MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE_DOWNLOAD:
vb.tvTitle.setText(getString(R.string.text_offline_song));
MyDownloadService.updateDownloadUi(vmApplication);
vmApplication.downloadData.observe(this, new Observer<List<Download>>() {
@Override
public void onChanged(List<Download> downloads) {
AdapterDownloadSong adapterDownloadSong = new AdapterDownloadSong();
adapterDownloadSong.setHomeItemClickListener(LikeSongActivity.this);
adapterDownloadSong.setData(downloads);
vb.recycler.setLayoutManager(new LinearLayoutManager(LikeSongActivity.this));
vb.recycler.setAdapter(adapterDownloadSong);
vb.tvSongSize.setText(String.format(getString(R.string.download_song), downloads.size()));
}
});
break;
}
}
@Override
protected void onInitClick() {
vb.imBack.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();
}
}
@Override
public void onClickLikeSong(BoxLikeSong boxLikeSong, int index) {
List<ResponsePlayListInfo> playList = new ArrayList<>();
for (BoxLikeSong song : boxLikeSongs) {
String videoId1 = song.getVideoId();
String songName = song.getSongName();
String covert = song.getCovert();
String singerName = song.getSingerName();
long durationMs = song.getDurationMs();
String duration = song.getDuration();
ResponsePlayListInfo playListInfo = new ResponsePlayListInfo(covert, songName, singerName, durationMs, videoId1, duration);
playList.add(playListInfo);
}
vmApplication.reSetPlayList(playList);
String videoId = boxLikeSong.getVideoId();
CommonUtils.LogMsg("-------------like进入 传值 videoId= " + videoId);
Intent intent = new Intent(this, PlayActivity.class);
intent.putExtra(MyValue.KEY_PLAY_VIDEO_ID, videoId);
intent.putExtra(MyValue.KEY_PLAY_INDEX, index);
intent.putExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_LIKE);
startActivity(intent);
}
@OptIn(markerClass = UnstableApi.class)
@Override
public void onClickDownloadSong(Download download, int index) {
// MyDownloadService.updateDownloadUi(vmApplication)
String videoId = download.request.id;
CommonUtils.LogMsg("------------Download进入 传值 videoId= " + videoId);
Intent intent = new Intent(this, PlayActivity.class);
intent.putExtra(MyValue.KEY_PLAY_VIDEO_ID, videoId);
intent.putExtra(MyValue.KEY_PLAY_INDEX, index);
intent.putExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_DOWNLOAD);
startActivity(intent);
}
@Override
public void onDownloadSong(String videoId, int index) {
Pair<Integer, String> integerStringPair = new Pair<>(index, videoId);
downloadList.add(integerStringPair);
}
}

View File

@ -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.drawable.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.drawable.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();
}
}
});
}
}

View File

@ -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.drawable.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;
}
}
}
}

View File

@ -1,76 +0,0 @@
package com.hi.music.player.ui.activity.viewmodel;
import android.util.Pair;
import androidx.annotation.OptIn;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.exoplayer.offline.Download;
import androidx.media3.exoplayer.offline.DownloadCursor;
import com.google.gson.Gson;
import com.hi.music.player.api.RequestListener;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.BoxDownloadSong;
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.ResponseSingle;
import com.hi.music.player.media3.MyMediaControllerManager;
import com.hi.music.player.network.JsonHelper;
import com.hi.music.player.network.RetrofitManager;
import org.json.JSONObject;
import java.nio.charset.StandardCharsets;
import java.util.List;
import okhttp3.ResponseBody;
public class VMApplication extends ViewModel {
private MutableLiveData<List<ResponsePlayListInfo>> _playList = new MutableLiveData<List<ResponsePlayListInfo>>();
public LiveData<List<ResponsePlayListInfo>> playList = _playList;
private MutableLiveData<Integer> _playStatus = new MutableLiveData<Integer>();
public LiveData<Integer> playStatus = _playStatus;
private MutableLiveData<List<Download>> _downloadData = new MutableLiveData<>();
public LiveData<List<Download>> downloadData = _downloadData;
private MutableLiveData<Pair<Boolean,Download>> _downloadChange = new MutableLiveData<>();
public LiveData<Pair<Boolean,Download>> downloadChange = _downloadChange;
/**
* 重置播放列表
*
* @param list
*/
public void reSetPlayList(List<ResponsePlayListInfo> list) {
_playList.setValue(list);
}
public void setPlayStatus(int status) {
_playStatus.setValue(status);
}
@OptIn(markerClass = UnstableApi.class)
public void setDownloadData(List<Download> downloadList) {
_downloadData.setValue(downloadList);
}
@OptIn(markerClass = UnstableApi.class)
public void setDownloadChange(Pair<Boolean,Download> download) {
_downloadChange.setValue(download);
}
}

View File

@ -1,91 +0,0 @@
package com.hi.music.player.ui.activity.viewmodel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.hi.music.player.api.RequestListener;
import com.hi.music.player.helper.CommonUtils;
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.ResponseSingle;
import com.hi.music.player.media3.MyMediaControllerManager;
import com.hi.music.player.network.JsonHelper;
import com.hi.music.player.network.RetrofitManager;
import org.json.JSONObject;
import java.util.List;
import okhttp3.ResponseBody;
public class VMPlay extends ViewModel {
private MutableLiveData<List<ResponsePlayListInfo>> _playList = new MutableLiveData<List<ResponsePlayListInfo>>();
public LiveData<List<ResponsePlayListInfo>> playList = _playList;
private MutableLiveData<CustomerUrlInfo> _playUrlMutableLiveData = new MutableLiveData<CustomerUrlInfo>();
public LiveData<CustomerUrlInfo> playUrlLiveData = _playUrlMutableLiveData;
public void getPlayMusicList(String playlistId, String videoId, String params, String musicVideoType) {
RetrofitManager.getInstance().getPlayList(params, playlistId, videoId, musicVideoType, new RequestListener<ResponseBody>() {
@Override
public void onFail(String errorMsg) {
// TODO: 2024/10/8 播放列表拉取失败
_playList.setValue(null);
}
@Override
public void onSuccess(JSONObject data) {
// JSONObject jsonObject = CommonUtils.toJsonObject(data);
if (data != null) {
List<ResponsePlayListInfo> responsePlayListInfos = JsonHelper.ResolvePlayListJson(data);
_playList.setValue(responsePlayListInfos);
} else {
_playList.setValue(null);
}
}
});
}
public void getPlayUrl(String videoId, int playListIndex,boolean playNow) {
CustomerUrlInfo customerUrlInfo = new CustomerUrlInfo();
customerUrlInfo.setNeedPlayNow(playNow);
customerUrlInfo.setVideoId(videoId);
customerUrlInfo.setPlayMusicIndex(playListIndex);
RetrofitManager.getInstance().getPlayUrl(videoId, new RequestListener<ResponseBody>() {
@Override
public void onFail(String errorMsg) {
CommonUtils.LogMsg("-------------此次网络请求失败 playNow="+playNow +"--playListIndex="+playListIndex);
_playUrlMutableLiveData.setValue(customerUrlInfo);
}
@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;
}
MyMediaControllerManager.getInstance().UpdateAudioUrl(responsePlayUrl,playListIndex);
customerUrlInfo.setPlayUrl(responsePlayUrl);
}
_playUrlMutableLiveData.setValue(customerUrlInfo);
}
});
}
}

View File

@ -12,16 +12,13 @@ import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
import androidx.viewbinding.ViewBinding; import androidx.viewbinding.ViewBinding;
import com.hi.music.player.helper.ViewModelScope;
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
public abstract class BaseFragment<T extends ViewBinding> extends Fragment { public abstract class BaseFragment<T extends ViewBinding> extends Fragment {
private final ViewModelScope mViewModelScope = new ViewModelScope(); // private final ViewModelScope mViewModelScope = new ViewModelScope();
protected T Vb; protected T Vb;
protected AppCompatActivity mActivity; protected AppCompatActivity mActivity;
protected VMApplication vmApplication; // protected VMApplication vmApplication;
public BaseFragment() { public BaseFragment() {
} }
@ -34,7 +31,7 @@ public abstract class BaseFragment<T extends ViewBinding> extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
Vb = getFragmentVb(); Vb = getFragmentVb();
vmApplication = getApplicationScopeViewModel(VMApplication.class); // vmApplication = getApplicationScopeViewModel(VMApplication.class);
initView(); initView();
return Vb.getRoot(); return Vb.getRoot();
} }
@ -42,14 +39,14 @@ public abstract class BaseFragment<T extends ViewBinding> extends Fragment {
protected abstract T getFragmentVb(); protected abstract T getFragmentVb();
protected abstract void initView(); protected abstract void initView();
protected <K extends ViewModel> K getFragmentScopeViewModel(@NonNull Class<K> modelClass) { // protected <K extends ViewModel> K getFragmentScopeViewModel(@NonNull Class<K> modelClass) {
return mViewModelScope.getFragmentScopeViewModel(this, modelClass); // return mViewModelScope.getFragmentScopeViewModel(this, modelClass);
} // }
protected <K extends ViewModel> K getActivityScopeViewModel(@NonNull Class<K> modelClass) { // protected <K extends ViewModel> K getActivityScopeViewModel(@NonNull Class<K> modelClass) {
return mViewModelScope.getActivityScopeViewModel(mActivity, modelClass); // return mViewModelScope.getActivityScopeViewModel(mActivity, modelClass);
} // }
//
protected <K extends ViewModel> K getApplicationScopeViewModel(@NonNull Class<K> modelClass) { // protected <K extends ViewModel> K getApplicationScopeViewModel(@NonNull Class<K> modelClass) {
return mViewModelScope.getApplicationScopeViewModel(modelClass); // return mViewModelScope.getApplicationScopeViewModel(modelClass);
} // }
} }

View File

@ -1,180 +0,0 @@
package com.hi.music.player.ui.fragmnt;
import android.content.Intent;
import android.content.RestrictionsManager;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.hi.music.player.R;
import com.hi.music.player.adapter.AdapterHome;
import com.hi.music.player.api.HomeItemClickListener;
import com.hi.music.player.api.OnHasUrlAction;
import com.hi.music.player.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();
vmHome.data.observe(getViewLifecycleOwner(), new Observer<ResponseHome>() {
@Override
public void onChanged(ResponseHome responseHome) {
if (responseHome == null) {
adapterHome.removeLoadingFooter();
requestCount--;
return;
}
Glide.with(requireContext())
.asDrawable()
.load(responseHome.getBackgroundUrl())
.placeholder(R.drawable.placeholder)
.error(R.drawable.placeholder)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
// Vb.linearLayout.setBackground(resource);
return false;
}
})
.preload();
List<ResponseHomeChild> childList1 = responseHome.getChildList();
if (childList1 == null) return;
childList.addAll(childList1);
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 if (pageType.equals(MyValue.PAGE_TYPE_ALBUM)) {
// 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);
// }
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);
}
}
}
}

View File

@ -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.drawable.placeholder)
.error(R.drawable.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.drawable.placeholder)
.error(R.drawable.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);
}
}
}
}

View File

@ -1,224 +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) {
if(responseSearches == null){
CommonUtils.LogMsg("------------更新结果 null");
return;
}
adapterSearch.setData(responseSearches);
}
});
}
private void startQuery(String query){
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);
}
}
}

View File

@ -1,41 +0,0 @@
package com.hi.music.player.ui.fragmnt.viewmodel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.hi.music.player.api.RequestListener;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.response.ResponseCategoryList;
import com.hi.music.player.javabean.response.ResponseHome;
import com.hi.music.player.javabean.response.ResponsePlayUrl;
import com.hi.music.player.network.JsonHelper;
import com.hi.music.player.network.RetrofitManager;
import org.json.JSONObject;
import okhttp3.ResponseBody;
public class VMCategoryList extends ViewModel {
private MutableLiveData<ResponseCategoryList> _data = new MutableLiveData<>();
public LiveData<ResponseCategoryList> data = _data;
public void getList(String browseId) {
RetrofitManager.getInstance().getCategoryList(browseId, new RequestListener<ResponseBody>() {
@Override
public void onFail(String errorMsg) {
_data.setValue(null);
}
@Override
public void onSuccess(JSONObject data) {
if (data != null) {
ResponseCategoryList responseCategoryList = JsonHelper.ResolveCategoryList(data,browseId);
_data.setValue(responseCategoryList);
}
}
});
}
}

View File

@ -1,81 +0,0 @@
package com.hi.music.player.ui.fragmnt.viewmodel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.hi.music.player.MusicApplication;
import com.hi.music.player.api.RequestListener;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.helper.MyValue;
import com.hi.music.player.javabean.response.ResponseHome;
import com.hi.music.player.network.JsonHelper;
import com.hi.music.player.network.RetrofitManager;
import org.json.JSONObject;
import okhttp3.ResponseBody;
public class VMHome extends ViewModel {
private MutableLiveData<ResponseHome> _data = new MutableLiveData<ResponseHome>();
public LiveData<ResponseHome> data = _data;
private String continuation, clickTrackingParams, visitorData;
public void getHome() {
RetrofitManager.getInstance().getHomeData(new RequestListener<ResponseBody>() {
@Override
public void onFail(String errorMsg) {
_data.setValue(null);
}
@Override
public void onSuccess(JSONObject data) {
// JSONObject jsonObject = CommonUtils.toJsonObject(data);
if (data != null) {
ResponseHome responseHome = JsonHelper.ResolveHomeJson(data);
continuation = responseHome.getContinuation();
clickTrackingParams = responseHome.getClickTrackingParams();
visitorData = responseHome.getVisitorData();
MusicApplication.setVisitorData(visitorData);
_data.setValue(responseHome);
} else {
_data.setValue(null);
}
}
});
}
public void getHomeMore() {
RetrofitManager.getInstance().getHomeMoreData(continuation, clickTrackingParams, visitorData, new RequestListener<ResponseBody>() {
@Override
public void onFail(String errorMsg) {
_data.setValue(null);
}
@Override
public void onSuccess(JSONObject data) {
// JSONObject jsonObject = CommonUtils.toJsonObject(data);
if (data != null) {
ResponseHome responseHome = JsonHelper.ResolveHomeMoreJson(data);
continuation = responseHome.getContinuation();
clickTrackingParams = responseHome.getClickTrackingParams();
_data.setValue(responseHome);
} else {
_data.setValue(null);
}
}
});
}
}

View File

@ -1,39 +0,0 @@
package com.hi.music.player.ui.fragmnt.viewmodel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.hi.music.player.api.RequestListener;
import com.hi.music.player.javabean.response.ResponseCategoryList;
import com.hi.music.player.javabean.response.ResponseResult;
import com.hi.music.player.network.JsonHelper;
import com.hi.music.player.network.RetrofitManager;
import org.json.JSONObject;
import okhttp3.ResponseBody;
public class VMResultList extends ViewModel {
private MutableLiveData<ResponseResult> _data = new MutableLiveData<>();
public LiveData<ResponseResult> data = _data;
public void getList(String browseId) {
RetrofitManager.getInstance().getCategoryList(browseId, new RequestListener<ResponseBody>() {
@Override
public void onFail(String errorMsg) {
_data.setValue(null);
}
@Override
public void onSuccess(JSONObject data) {
if (data != null) {
ResponseResult responseResult = JsonHelper.ResolveSearchResultList(data);
_data.setValue(responseResult);
}
}
});
}
}

View File

@ -1,71 +0,0 @@
package com.hi.music.player.ui.fragmnt.viewmodel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.hi.music.player.api.RequestListener;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.response.ResponseHome;
import com.hi.music.player.javabean.response.ResponseSearch;
import com.hi.music.player.network.JsonHelper;
import com.hi.music.player.network.RetrofitManager;
import org.json.JSONObject;
import java.util.List;
import okhttp3.ResponseBody;
public class VMSearch extends ViewModel {
private MutableLiveData<List<String>> _suggestion = new MutableLiveData<List<String>>();
public LiveData<List<String>> suggestion = _suggestion;
private MutableLiveData<List<ResponseSearch>> _result= new MutableLiveData<List<ResponseSearch>>();
public LiveData<List<ResponseSearch>> result = _result;
public void getSuggestion(String input) {
RetrofitManager.getInstance().getSearchSuggestion(input,new RequestListener<ResponseBody>() {
@Override
public void onFail(String errorMsg) {
_suggestion.setValue(null);
}
@Override
public void onSuccess(JSONObject data) {
if (data != null) {
List<String> stringList = JsonHelper.ResolveSearchSuggestion(data);
CommonUtils.LogMsg("------------onSuccess= stringList="+stringList );
_suggestion.setValue(stringList);
} else {
_suggestion.setValue(null);
}
}
});
}
public void getSearchResult(String query) {
RetrofitManager.getInstance().getSearch(query, new RequestListener<ResponseBody>() {
@Override
public void onFail(String errorMsg) {
_result.setValue(null);
}
@Override
public void onSuccess(JSONObject data) {
if (data != null) {
List<ResponseSearch> responseSearches = JsonHelper.ResolveSearchResult(data);
_result.setValue(responseSearches);
} else {
_result.setValue(null);
}
}
});
}
}

View File

@ -1,61 +0,0 @@
package com.hi.music.player.ui.paging;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.paging.PagingSource;
import androidx.paging.PagingState;
import com.hi.music.player.api.RequestListener;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.response.ResponseHome;
import com.hi.music.player.network.JsonHelper;
import com.hi.music.player.network.RetrofitManager;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Single;
import kotlin.coroutines.Continuation;
import okhttp3.ResponseBody;
public class MyPagingSource extends PagingSource<Integer, ResponseHome> {
@Nullable
@Override
public Integer getRefreshKey(@NonNull PagingState<Integer, ResponseHome> pagingState) {
return null;
}
@Nullable
@Override
public Object load(@NonNull LoadParams<Integer> loadParams, @NonNull Continuation<? super PagingSource.LoadResult<Integer, ResponseHome>> continuation) {
int nextPage = 1;
Integer key = loadParams.getKey();
if (key != null) {
nextPage = key + 1;
}
// try {
// // 使用 Single 来处理异步请求
//
// List<ResponseHome> result = Single.<List<ResponseHome>>create(emitter -> {
// RetrofitManager.getInstance().getHomeData();
// })
// .blockingGet(); // 阻塞获取结果
//
// return new LoadResult.Page<>(
// result,
// page == 1 ? null : page - 1,
// result.isEmpty() ? null : page + 1
// );
// } catch (Exception e) {
// return new LoadResult.Error<>(e);
// }
//
return null;
}
}

View File

@ -1,307 +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_height="match_parent"
android:background="@color/black"
android:fillViewport="true"
android:id="@+id/root_layout"
android:layout_width="match_parent" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.PlayActivity">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/black_gradient" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<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"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.cardview.widget.CardView
android:id="@+id/card_playerView"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_marginStart="20dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="20dp"
app:cardBackgroundColor="@color/black"
app:cardCornerRadius="8dp"
app:cardElevation="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/im_back">
<androidx.media3.ui.PlayerView
android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:resize_mode="zoom"
app:show_buffering="when_playing"
app:show_shuffle_button="false"
app:use_controller="false" />
<ImageView
android:id="@+id/im_covert"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/im_back" />
</androidx.cardview.widget.CardView>
<ProgressBar
android:id="@+id/progressBarLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateTint="@color/white"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/card_playerView"
app:layout_constraintLeft_toLeftOf="@id/card_playerView"
app:layout_constraintRight_toRightOf="@id/card_playerView"
app:layout_constraintTop_toTopOf="@id/card_playerView" />
<include
android:id="@+id/layout_error"
layout="@layout/layout_error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@id/card_playerView"
app:layout_constraintLeft_toLeftOf="@id/card_playerView"
app:layout_constraintRight_toRightOf="@id/card_playerView"
app:layout_constraintTop_toTopOf="@id/card_playerView" />
<TextView
android:id="@+id/tv_song_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="25dp"
android:text=""
android:textColor="@color/text_color_1"
android:textSize="19sp"
app:layout_constraintLeft_toLeftOf="@id/card_playerView"
app:layout_constraintRight_toRightOf="@id/card_playerView"
app:layout_constraintTop_toBottomOf="@id/card_playerView" />
<TextView
android:id="@+id/tv_singer_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:text="9999999999999999999999999999999999999999999999"
android:textColor="@color/white_60_color"
android:textSize="15sp"
app:layout_constraintRight_toRightOf="@id/tv_song_name"
app:layout_constraintLeft_toLeftOf="@id/tv_song_name"
app:layout_constraintTop_toBottomOf="@id/tv_song_name" />
<LinearLayout
android:id="@+id/layout_like"
android:layout_width="wrap_content"
android:layout_height="34dp"
android:layout_marginTop="14dp"
android:background="@drawable/bg_like_layout"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="22dp"
android:paddingEnd="22dp"
app:layout_constraintLeft_toLeftOf="@id/card_playerView"
app:layout_constraintTop_toBottomOf="@id/tv_singer_name">
<ImageView
android:id="@+id/im_like"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/selector_like" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/like"
android:textColor="@color/white"
android:textSize="14sp" />
</LinearLayout>
<RelativeLayout
android:id="@+id/layout_download"
android:layout_width="wrap_content"
android:layout_height="34dp"
android:layout_marginStart="12dp"
android:background="@drawable/bg_like_layout"
android:orientation="horizontal"
android:paddingStart="22dp"
android:paddingEnd="22dp"
app:layout_constraintLeft_toRightOf="@id/layout_like"
app:layout_constraintTop_toTopOf="@id/layout_like">
<ImageView
android:id="@+id/im_download"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_centerVertical="true"
android:src="@drawable/selector_download" />
<ProgressBar
android:id="@+id/download_pb"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_centerVertical="true"
android:indeterminateTint="@color/panel_bg"
android:progressBackgroundTint="@color/panel_bg"
android:progressTint="@color/panel_bg"
android:visibility="gone" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="12dp"
android:layout_toEndOf="@id/im_download"
android:text="@string/download"
android:textColor="@color/white"
android:textSize="14sp" />
</RelativeLayout>
<SeekBar
android:id="@+id/play_progress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:maxHeight="3dp"
android:paddingStart="5dp"
android:paddingLeft="0dp"
android:paddingEnd="5dp"
android:paddingRight="0dp"
android:progress="3"
android:progressDrawable="@drawable/seekbar_progress_drawable"
android:thumb="@drawable/seekbar_thumb"
app:layout_constraintLeft_toLeftOf="@id/card_playerView"
app:layout_constraintRight_toRightOf="@id/card_playerView"
app:layout_constraintTop_toBottomOf="@id/layout_like" />
<ProgressBar
android:id="@+id/progressBar_buffer"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="3dp"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:progress="10"
android:progressDrawable="@drawable/horizontal_progressbar"
app:layout_constraintBottom_toBottomOf="@id/play_progress"
app:layout_constraintLeft_toLeftOf="@id/play_progress"
app:layout_constraintRight_toRightOf="@id/play_progress"
app:layout_constraintTop_toTopOf="@id/play_progress" />
<TextView
android:id="@+id/tv_current"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:paddingStart="5dp"
android:text="0:00"
android:textColor="@color/white_60_color"
app:layout_constraintStart_toStartOf="@id/play_progress"
app:layout_constraintTop_toBottomOf="@id/play_progress" />
<TextView
android:id="@+id/tv_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:paddingEnd="5dp"
android:text="0:00"
android:textColor="@color/white_60_color"
app:layout_constraintEnd_toEndOf="@id/play_progress"
app:layout_constraintTop_toBottomOf="@id/play_progress" />
<ImageView
android:id="@+id/btn_play"
android:layout_width="66dp"
android:layout_height="66dp"
android:layout_marginTop="15dp"
android:src="@drawable/selector_icon_play"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_duration" />
<ImageView
android:id="@+id/btn_previous"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginEnd="24dp"
android:padding="12dp"
android:src="@mipmap/icon_previous_true"
app:layout_constraintBottom_toBottomOf="@id/btn_play"
app:layout_constraintEnd_toStartOf="@id/btn_play"
app:layout_constraintTop_toTopOf="@id/btn_play" />
<ImageView
android:id="@+id/btn_next"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginStart="24dp"
android:padding="12dp"
android:src="@mipmap/icon_next_true"
app:layout_constraintBottom_toBottomOf="@id/btn_play"
app:layout_constraintStart_toEndOf="@id/btn_play"
app:layout_constraintTop_toTopOf="@id/btn_play" />
<ImageView
android:id="@+id/btn_music_list"
android:layout_width="44dp"
android:layout_height="44dp"
android:padding="10dp"
android:src="@mipmap/icon_list"
app:layout_constraintBottom_toBottomOf="@id/btn_play"
app:layout_constraintLeft_toRightOf="@id/btn_next"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/btn_play" />
<ImageView
android:id="@+id/btn_loop"
android:layout_width="44dp"
android:layout_height="44dp"
android:padding="10dp"
android:src="@drawable/icon_looper_no"
app:layout_constraintBottom_toBottomOf="@id/btn_play"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn_previous"
app:layout_constraintTop_toTopOf="@id/btn_play" />
</androidx.constraintlayout.widget.ConstraintLayout>
<include
android:id="@+id/layout_playList"
layout="@layout/dialog_play_list" />
</FrameLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -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="@drawable/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>