Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d7a136173 | ||
|
|
238ddf48fe | ||
|
|
f1cd9ec8ca | ||
|
|
d7320dc5f7 | ||
|
|
26b36f2e22 | ||
|
|
1ddf4b8d8f | ||
|
|
338a063e9e | ||
|
|
8b8a79f39b |
Binary file not shown.
BIN
app/OfflineMusicPlayer.jks
Normal file
BIN
app/OfflineMusicPlayer.jks
Normal file
Binary file not shown.
@ -6,25 +6,26 @@ plugins {
|
||||
// id("org.jetbrains.kotlin.android")
|
||||
// id ("kotlin-kapt")
|
||||
id("io.objectbox")
|
||||
id("com.google.gms.google-services")
|
||||
id("com.google.firebase.crashlytics")
|
||||
}
|
||||
|
||||
val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date())
|
||||
|
||||
android {
|
||||
namespace = "com.hi.music.player"
|
||||
namespace = "com.offline.music.playermp3"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
//com.hi.music.player
|
||||
applicationId = "com.hi.music.player.test1"
|
||||
applicationId = "com.offline.music.playermp3"
|
||||
minSdk = 23
|
||||
targetSdk = 34
|
||||
versionCode = 1
|
||||
versionName = "1.0.0"
|
||||
|
||||
setProperty("archivesBaseName", "MusicApp_V" + versionName + "(${versionCode})_$timestamp")
|
||||
setProperty(
|
||||
"archivesBaseName",
|
||||
"Offline Music Player" + versionName + "(${versionCode})_$timestamp"
|
||||
)
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@ -75,26 +76,25 @@ dependencies {
|
||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
||||
// kapt("com.github.bumptech.glide:compiler:4.16.0")
|
||||
// Glide 的图片变换库,包括高斯模糊
|
||||
implementation ("jp.wasabeef:glide-transformations:4.3.0")
|
||||
implementation("jp.wasabeef:glide-transformations:4.3.0")
|
||||
|
||||
|
||||
//提取图片主色
|
||||
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
|
||||
implementation("androidx.media3:media3-exoplayer:1.4.1")
|
||||
implementation("androidx.media3:media3-exoplayer-dash:1.4.1")
|
||||
implementation("androidx.media3:media3-session:1.4.1")
|
||||
implementation("androidx.media3:media3-ui:1.4.1")
|
||||
implementation ("androidx.media3:media3-database:1.4.1")
|
||||
// implementation("androidx.media3:media3-exoplayer:1.4.1")
|
||||
// implementation("androidx.media3:media3-exoplayer-dash:1.4.1")
|
||||
// implementation("androidx.media3:media3-session:1.4.1")
|
||||
// implementation("androidx.media3:media3-ui:1.4.1")
|
||||
// implementation ("androidx.media3:media3-database:1.4.1")
|
||||
//----------media3
|
||||
|
||||
//------------------firebase
|
||||
implementation(platform("com.google.firebase:firebase-bom:33.1.1"))
|
||||
implementation("com.google.firebase:firebase-crashlytics")
|
||||
implementation("com.google.firebase:firebase-analytics")
|
||||
implementation("com.google.firebase:firebase-config")
|
||||
|
||||
// implementation ("com.geyifeng.immersionbar:immersionbar:3.2.2")
|
||||
// implementation ("com.geyifeng.immersionbar:immersionbar-components:3.2.2")
|
||||
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "550960818622",
|
||||
"project_id": "himelody-and",
|
||||
"storage_bucket": "himelody-and.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:550960818622:android:96fd4141e43410fb24f1ef",
|
||||
"android_client_info": {
|
||||
"package_name": "com.hi.music.player.test1"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCp3XR60onMqiGj9pD8ADmrDEOOn__sQDk"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
app_name=Music Player
|
||||
package_name=com.hi.music.player.test
|
||||
keystoreFile=app/MusicPlayer.jks
|
||||
key_alias=MusicPlayerkey0
|
||||
key_store_password=MusicPlayer
|
||||
key_password=MusicPlayer
|
||||
app_name=Offline Music Player
|
||||
package_name=com.offline.music.player
|
||||
keystoreFile=app/OfflineMusicPlayer.jks
|
||||
key_alias=OfflineMusicPlayerkey0
|
||||
key_store_password=OfflineMusicPlayer
|
||||
key_password=OfflineMusicPlayer
|
||||
2
app/proguard-rules.pro
vendored
2
app/proguard-rules.pro
vendored
@ -29,7 +29,7 @@
|
||||
-dontwarn retrofit2.**
|
||||
-dontwarn javax.annotation.Nullable
|
||||
|
||||
-keep class com.hi.music.player.javabean.A_data.AudioItem { *; }
|
||||
-keep class com.offline.music.playermp3.javabean.A_data.AudioItem { *; }
|
||||
|
||||
# 保持 Context、Intent 和权限相关的公共方法
|
||||
-keep class android.content.Context { *; }
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.hi.music.player;
|
||||
package com.offline.music.playermp3;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
@ -17,24 +17,13 @@
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/im_logo"
|
||||
android:icon="@drawable/music_player_launch"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/im_logo"
|
||||
android:roundIcon="@drawable/music_player_launch"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.MusicApp"
|
||||
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
|
||||
android:name=".ui.activity.A_PlayActivity"
|
||||
android:screenOrientation="portrait"
|
||||
@ -43,20 +32,12 @@
|
||||
android:name=".ui.activity.A_SettingActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".ui.activity.PlayActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.A_HomeActivity"
|
||||
android:exported="true"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".ui.activity.HomeActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:exported="false">
|
||||
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ui.activity.A_SplashActivity"
|
||||
android:screenOrientation="portrait"
|
||||
@ -68,25 +49,25 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".media3.PlaybackService"
|
||||
android:exported="true"
|
||||
android:foregroundServiceType="mediaPlayback">
|
||||
<intent-filter>
|
||||
<action android:name="androidx.media3.session.MediaSessionService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<!-- <service-->
|
||||
<!-- android:name=".media3.PlaybackService"-->
|
||||
<!-- android:exported="true"-->
|
||||
<!-- android:foregroundServiceType="mediaPlayback">-->
|
||||
<!-- <intent-filter>-->
|
||||
<!-- <action android:name="androidx.media3.session.MediaSessionService" />-->
|
||||
<!-- </intent-filter>-->
|
||||
<!-- </service>-->
|
||||
|
||||
<service
|
||||
android:name=".media3.MyDownloadService"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="dataSync"
|
||||
tools:ignore="ForegroundServicePermission">
|
||||
<intent-filter>
|
||||
<action android:name="androidx.media3.exoplayer.downloadService.action.RESTART" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<!-- <service-->
|
||||
<!-- android:name=".media3.MyDownloadService"-->
|
||||
<!-- android:exported="false"-->
|
||||
<!-- android:foregroundServiceType="dataSync"-->
|
||||
<!-- tools:ignore="ForegroundServicePermission">-->
|
||||
<!-- <intent-filter>-->
|
||||
<!-- <action android:name="androidx.media3.exoplayer.downloadService.action.RESTART" />-->
|
||||
<!-- <category android:name="android.intent.category.DEFAULT" />-->
|
||||
<!-- </intent-filter>-->
|
||||
<!-- </service>-->
|
||||
<service
|
||||
android:name=".service.MusicPlayerForegroundService"
|
||||
android:enabled="true"
|
||||
|
||||
BIN
app/src/main/ic_launcher-playstore.png
Normal file
BIN
app/src/main/ic_launcher-playstore.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
@ -1,57 +0,0 @@
|
||||
package com.hi.music.player;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.database.StandaloneDatabaseProvider;
|
||||
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor;
|
||||
import androidx.media3.datasource.cache.SimpleCache;
|
||||
|
||||
import com.hi.music.player.api.MediaControllerStatusListener;
|
||||
import com.hi.music.player.firebase.RemoteConfigJava;
|
||||
import com.hi.music.player.firebase.Sp;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.media3.MyDownloadService;
|
||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
||||
import com.hi.music.player.objectbox.ObjectBoxManager;
|
||||
|
||||
public class MusicApplication extends Application {
|
||||
|
||||
public static Context myApplication;
|
||||
|
||||
public static String visitorData;
|
||||
|
||||
|
||||
|
||||
|
||||
public static void setVisitorData(String visitorData) {
|
||||
MusicApplication.visitorData = visitorData;
|
||||
}
|
||||
|
||||
public static String getVisitorData() {
|
||||
return visitorData;
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
myApplication = this;
|
||||
Sp.init(this);
|
||||
RemoteConfigJava.getInstance().init(this);
|
||||
ObjectBoxManager.init(this);
|
||||
|
||||
StandaloneDatabaseProvider databaseProvider = new StandaloneDatabaseProvider(this);
|
||||
MyDownloadService.init(this,databaseProvider);
|
||||
MyMediaControllerManager.getInstance().init(new MediaControllerStatusListener() {
|
||||
@Override
|
||||
public void onMediaControllerComplete(boolean isOk) {
|
||||
CommonUtils.LogMsg("=-----mediaController+" + isOk);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,78 +0,0 @@
|
||||
package com.hi.music.player.adapter;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.databinding.ItemCategoryBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.response.child.ResponseCategory;
|
||||
|
||||
public class AdapterCategory extends BaseAdapter<ResponseCategory, ItemCategoryBinding>{
|
||||
|
||||
@Override
|
||||
protected ItemCategoryBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemCategoryBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
|
||||
int itemViewType = getItemViewType(position);
|
||||
if (itemViewType == TYPE_ITEM) {
|
||||
VHolder<ItemCategoryBinding> itemHolder = (VHolder<ItemCategoryBinding>) holder;
|
||||
ItemCategoryBinding vb = itemHolder.getVb();
|
||||
ResponseCategory responseCategory = data.get(position);
|
||||
String pageType = responseCategory.getPageType();
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.load(responseCategory.getCovert())
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.into(vb.header);
|
||||
vb.tvTitle.setText(responseCategory.getTwoTitle());
|
||||
vb.tvSubtitle.setText(responseCategory.getTwoSubtitle());
|
||||
CommonUtils.LogMsg("title="+responseCategory.getTwoTitle()+"----------pageType="+pageType
|
||||
+"---browserId="+responseCategory.getBrowseId()+"---videoId="+responseCategory.getVideoId()+"---playListId="+responseCategory.getPlayListId());
|
||||
if(pageType == null){
|
||||
return;
|
||||
}
|
||||
// if(pageType.equals(MyValue.PAGE_TYPE_MV)||pageType.equals(MyValue.PAGE_TYPE_MV_LIST)){
|
||||
// ViewGroup.LayoutParams layoutParams = vb.header.getLayoutParams();
|
||||
// layoutParams.width = CommonUtils.dpToPx(280);
|
||||
// vb.header.setLayoutParams(layoutParams);
|
||||
// vb.header.setBackgroundResource(R.drawable.bg_black_13);
|
||||
//
|
||||
// }else {
|
||||
// ViewGroup.LayoutParams layoutParams = vb.header.getLayoutParams();
|
||||
// layoutParams.width = CommonUtils.dpToPx(170);
|
||||
// vb.header.setLayoutParams(layoutParams);
|
||||
// vb.header.setBackground(null);
|
||||
// }
|
||||
|
||||
|
||||
vb.header.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (homeItemClickListener != null) {
|
||||
homeItemClickListener.onClickItemCategory(responseCategory);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
package com.hi.music.player.adapter;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.api.onImageColorListener;
|
||||
import com.hi.music.player.databinding.ItemCategoryListBinding;
|
||||
import com.hi.music.player.databinding.ItemSingerBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
||||
import com.hi.music.player.javabean.response.child.ResponseCategoryListChild;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
||||
|
||||
public class AdapterCategoryList extends BaseAdapter<ResponsePlayListInfo, ItemCategoryListBinding> {
|
||||
|
||||
|
||||
private String mPageType;
|
||||
|
||||
public void setPageType(String mPageType) {
|
||||
this.mPageType = mPageType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemCategoryListBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemCategoryListBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
VHolder<ItemCategoryListBinding> itemHolder = (VHolder<ItemCategoryListBinding>) holder;
|
||||
ResponsePlayListInfo child = data.get(position);
|
||||
|
||||
ItemCategoryListBinding vb = itemHolder.getVb();
|
||||
vb.tvSongName.setText(child.getSongTitle());
|
||||
vb.tvDuration.setText(child.getDuration());
|
||||
String singerName = child.getSingerName();
|
||||
String describe = child.getDescribe();
|
||||
|
||||
switch (mPageType){
|
||||
case MyValue.PAGE_TYPE_ALBUM:
|
||||
vb.tvSingerName.setText(describe);
|
||||
vb.imCard.setVisibility(View.GONE);
|
||||
vb.tvPosition.setVisibility(View.VISIBLE);
|
||||
vb.tvPosition.setText(String.valueOf(position+1));
|
||||
break;
|
||||
default:
|
||||
vb.tvSingerName.setText(singerName);
|
||||
|
||||
vb.imCard.setVisibility(View.VISIBLE);
|
||||
vb.tvPosition.setVisibility(View.GONE);
|
||||
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.load(child.getSmallCovert())
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.image);
|
||||
break;
|
||||
}
|
||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
homeItemClickListener.onClickItemCategoryList(child, itemHolder.getAbsoluteAdapterPosition());
|
||||
}
|
||||
});
|
||||
|
||||
if(position == data.size() - 1){
|
||||
vb.place.setVisibility(View.VISIBLE);
|
||||
}else {
|
||||
vb.place.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
package com.hi.music.player.adapter;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.exoplayer.offline.Download;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.databinding.ItemLikeSongBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.BoxDownloadSong;
|
||||
import com.hi.music.player.javabean.BoxLikeSong;
|
||||
|
||||
public class AdapterDownloadSong extends BaseAdapter<Download, ItemLikeSongBinding> {
|
||||
|
||||
@Override
|
||||
protected ItemLikeSongBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemLikeSongBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
VHolder<ItemLikeSongBinding> itemHolder = (VHolder<ItemLikeSongBinding>) holder;
|
||||
ItemLikeSongBinding vb = itemHolder.getVb();
|
||||
Download download = data.get(position);
|
||||
BoxDownloadSong boxDownloadSong = CommonUtils.downloadToBean(download);
|
||||
|
||||
if (position == data.size()-1){
|
||||
vb.place.setVisibility(View.VISIBLE);
|
||||
}else {
|
||||
vb.place.setVisibility(View.GONE);
|
||||
}
|
||||
vb.layoutDownload.setVisibility(View.GONE);
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.load(boxDownloadSong.getCovert())
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.imCovert);
|
||||
vb.tvTitle.setText(boxDownloadSong.getSongName());
|
||||
vb.tvSingerName.setText(boxDownloadSong.getSingerName());
|
||||
|
||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(homeItemClickListener!= null){
|
||||
int absoluteAdapterPosition = itemHolder.getAbsoluteAdapterPosition();
|
||||
homeItemClickListener.onClickDownloadSong(download,absoluteAdapterPosition);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
package com.hi.music.player.adapter;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.databinding.ItemFooterLoadingBinding;
|
||||
import com.hi.music.player.databinding.ItemHomeBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.response.child.ResponseCategory;
|
||||
import com.hi.music.player.javabean.response.child.ResponseHomeChild;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AdapterHome extends BaseAdapter<ResponseHomeChild, ItemHomeBinding> {
|
||||
|
||||
@Override
|
||||
protected ItemHomeBinding getViewBinding(ViewGroup parent) {
|
||||
|
||||
return ItemHomeBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
int itemViewType = getItemViewType(position);
|
||||
if (itemViewType == TYPE_ITEM) {
|
||||
VHolder<ItemHomeBinding> itemHolder = (VHolder<ItemHomeBinding>) holder;
|
||||
ItemHomeBinding vb = itemHolder.getVb();
|
||||
ResponseHomeChild responseHomeChild = data.get(position);
|
||||
vb.headTitle.setText(responseHomeChild.getHeaderTitle());
|
||||
|
||||
List<ResponseSingle> singleList = responseHomeChild.getSingleList();
|
||||
List<ResponseCategory> categoryList = responseHomeChild.getCategoryList();
|
||||
CommonUtils.LogMsg("position="+position+"-----------headTitle-=" + responseHomeChild.getHeaderTitle()+"--singleList="+singleList+"---categoryList="+categoryList);
|
||||
if (singleList != null && singleList.size() > 0) {
|
||||
vb.recyclerSinger.setVisibility(View.VISIBLE);
|
||||
AdapterSinger adapterSinger = new AdapterSinger();
|
||||
adapterSinger.setHomeItemClickListener(homeItemClickListener);
|
||||
adapterSinger.addData(singleList);
|
||||
vb.recyclerSinger.setLayoutManager(new GridLayoutManager(MusicApplication.myApplication, 4, RecyclerView.HORIZONTAL, false));
|
||||
vb.recyclerSinger.setAdapter(adapterSinger);
|
||||
} else {
|
||||
vb.recyclerSinger.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (categoryList != null && categoryList.size() > 0) {
|
||||
vb.recyclerCategory.setVisibility(View.VISIBLE);
|
||||
AdapterCategory adapterCategory = new AdapterCategory();
|
||||
adapterCategory.setHomeItemClickListener(homeItemClickListener);
|
||||
adapterCategory.addData(categoryList);
|
||||
vb.recyclerCategory.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication, RecyclerView.HORIZONTAL, false));
|
||||
vb.recyclerCategory.setAdapter(adapterCategory);
|
||||
} else {
|
||||
vb.recyclerCategory.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if(position == data.size() - 1){
|
||||
vb.place.setVisibility(View.VISIBLE);
|
||||
}else {
|
||||
vb.place.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
VHolder<ItemFooterLoadingBinding> footerHolder = (VHolder<ItemFooterLoadingBinding>) holder;
|
||||
FrameLayout root = footerHolder.getVb().getRoot();
|
||||
if (isLoadingAdded) {
|
||||
root.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
root.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,215 +0,0 @@
|
||||
package com.hi.music.player.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.exoplayer.offline.Download;
|
||||
import androidx.media3.exoplayer.offline.DownloadRequest;
|
||||
import androidx.media3.exoplayer.offline.DownloadService;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.google.gson.Gson;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.api.onCheckDownload;
|
||||
import com.hi.music.player.databinding.ItemLikeSongBinding;
|
||||
import com.hi.music.player.databinding.ItemSingerBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.BoxDownloadSong;
|
||||
import com.hi.music.player.javabean.BoxLikeSong;
|
||||
import com.hi.music.player.javabean.CustomerDownload;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
||||
import com.hi.music.player.media3.MyDownloadService;
|
||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
||||
import com.hi.music.player.network.JsonHelper;
|
||||
import com.hi.music.player.network.RetrofitManager;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
public class AdapterLikeSong extends BaseAdapter<BoxLikeSong, ItemLikeSongBinding> {
|
||||
|
||||
private VMApplication vmApplication;
|
||||
|
||||
private List<Pair<Boolean, String>> status = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected ItemLikeSongBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemLikeSongBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
|
||||
public AdapterLikeSong(Context mContext, VMApplication vm) {
|
||||
super(mContext);
|
||||
vmApplication = vm;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void updateDownloadStatus(boolean isSuccess, int position, String videoId) {
|
||||
status.add(new Pair<>(isSuccess, videoId));
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
VHolder<ItemLikeSongBinding> itemHolder = (VHolder<ItemLikeSongBinding>) holder;
|
||||
ItemLikeSongBinding vb = itemHolder.getVb();
|
||||
BoxLikeSong boxLikeSong = data.get(position);
|
||||
String videoId = boxLikeSong.getVideoId();
|
||||
|
||||
if (position == data.size()-1){
|
||||
vb.place.setVisibility(View.VISIBLE);
|
||||
}else {
|
||||
vb.place.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
||||
for(Pair<Boolean,String> pair:status){
|
||||
if(pair.second.equals(videoId)){
|
||||
vb.imDownload.setSelected(pair.first);
|
||||
vb.imDownload.setVisibility(View.VISIBLE);
|
||||
vb.downloadPb.setVisibility(View.GONE);
|
||||
CommonUtils.LogMsg("--------------------状态更新");
|
||||
}
|
||||
}
|
||||
|
||||
MyDownloadService.queryIsDownload(videoId, new onCheckDownload() {
|
||||
@Override
|
||||
public void onHasDownload(CustomerDownload customerDownload) {
|
||||
boolean download = customerDownload.isDownload();
|
||||
if (download) {
|
||||
vb.imDownload.setSelected(true);
|
||||
} else {
|
||||
vb.imDownload.setSelected(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
vb.layoutDownload.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (vb.imDownload.isSelected()) {
|
||||
//已经下载
|
||||
Toast.makeText(mContext,mContext.getText(R.string.text_has_downloaded),Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
vb.imDownload.setVisibility(View.GONE);
|
||||
vb.downloadPb.setVisibility(View.VISIBLE);
|
||||
RetrofitManager.getInstance().getPlayUrl(videoId, new com.hi.music.player.api.RequestListener<ResponseBody>() {
|
||||
|
||||
@Override
|
||||
public void onFail(String errorMsg) {
|
||||
CommonUtils.LogMsg("-------------onFail");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(JSONObject data) {
|
||||
// JSONObject jsonObject = CommonUtils.toJsonObject(data);
|
||||
if (data != null) {
|
||||
ResponsePlayUrl responsePlayUrl = JsonHelper.ResolvePlayUrlJson(data);
|
||||
if (responsePlayUrl == null) {
|
||||
// TODO: 2024/9/27
|
||||
return;
|
||||
}
|
||||
String videoUrlMedium = responsePlayUrl.getVideoUrlMedium();
|
||||
|
||||
BoxDownloadSong downloadSong = new BoxDownloadSong();
|
||||
downloadSong.setVideoId(videoId);
|
||||
downloadSong.setCovert(String.valueOf(boxLikeSong.getCovert()));
|
||||
downloadSong.setSongName((String) boxLikeSong.getSongName());
|
||||
downloadSong.setSingerName((String) boxLikeSong.getSingerName());
|
||||
downloadSong.setDuration((String) boxLikeSong.getDuration());
|
||||
downloadSong.setDurationMs(boxLikeSong.getDurationMs());
|
||||
downloadSong.setVideoUrl(videoUrlMedium);
|
||||
Gson gson = new Gson();
|
||||
String info = gson.toJson(downloadSong);
|
||||
byte[] bytes = info.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
DownloadRequest downloadRequest = new DownloadRequest.Builder(videoId, Uri.parse(videoUrlMedium))
|
||||
.setMimeType("video/mp4")
|
||||
.setData(bytes)
|
||||
.build();
|
||||
|
||||
|
||||
DownloadService.sendAddDownload(
|
||||
mContext,
|
||||
MyDownloadService.class, // 上面定义的下载服务类
|
||||
downloadRequest,
|
||||
true // 是否在前台运行
|
||||
);
|
||||
if (homeItemClickListener != null) {
|
||||
homeItemClickListener.onDownloadSong(videoId, itemHolder.getAbsoluteAdapterPosition());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.load(boxLikeSong.getCovert())
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.imCovert);
|
||||
vb.tvTitle.setText(boxLikeSong.getSongName());
|
||||
vb.tvSingerName.setText(boxLikeSong.getSingerName());
|
||||
|
||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (homeItemClickListener != null) {
|
||||
int absoluteAdapterPosition = itemHolder.getAbsoluteAdapterPosition();
|
||||
homeItemClickListener.onClickLikeSong(boxLikeSong, absoluteAdapterPosition);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,118 +0,0 @@
|
||||
package com.hi.music.player.adapter;
|
||||
|
||||
import static androidx.media3.session.legacy.MediaControllerCompat.getMediaController;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.api.MediaControllerListener;
|
||||
import com.hi.music.player.databinding.ItemPlayListBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
||||
|
||||
public class AdapterPlayList extends BaseAdapter<ResponsePlayListInfo, ItemPlayListBinding> {
|
||||
|
||||
private String mCurVideId;
|
||||
|
||||
private String lastVideId;
|
||||
|
||||
// private int curMusicPos = 0;
|
||||
private MyMediaControllerManager instance = MyMediaControllerManager.getInstance();
|
||||
|
||||
@Override
|
||||
protected ItemPlayListBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemPlayListBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
public void setCurVideId(String curVideId) {
|
||||
lastVideId = mCurVideId;
|
||||
this.mCurVideId = curVideId;
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
ResponsePlayListInfo listInfo = data.get(i);
|
||||
if (listInfo.getVideoId().equals(curVideId)) {
|
||||
notifyItemChanged(i);
|
||||
}
|
||||
if (listInfo.getVideoId().equals(lastVideId)) {
|
||||
notifyItemChanged(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void updateCurMusicAnimation() {
|
||||
int curIndex = instance.getCurIndex();
|
||||
CommonUtils.LogMsg("--curIndex=" + curIndex);
|
||||
notifyItemChanged(curIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
ResponsePlayListInfo listInfo = data.get(position);
|
||||
VHolder<ItemPlayListBinding> itemHolder = (VHolder<ItemPlayListBinding>) holder;
|
||||
ItemPlayListBinding vb = itemHolder.getVb();
|
||||
|
||||
vb.songName.setText(listInfo.getSongTitle());
|
||||
String singerName = listInfo.getSingerName();
|
||||
String describe = listInfo.getDescribe();
|
||||
if (singerName != null && !singerName.isEmpty()) {
|
||||
vb.artistName.setText(singerName);
|
||||
} else if (describe != null && !describe.isEmpty()) {
|
||||
vb.artistName.setText(describe);
|
||||
}
|
||||
|
||||
String covert;
|
||||
String small = listInfo.getSmallCovert();
|
||||
String covert1 = listInfo.getCovert();
|
||||
if (small == null || small.isEmpty()) {
|
||||
covert = covert1;
|
||||
} else {
|
||||
covert = small;
|
||||
}
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
// .apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10))))
|
||||
.load(covert)
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.into(vb.imCovert);
|
||||
|
||||
MediaItem currentMediaItem = instance.getCurMediaItem();
|
||||
if (currentMediaItem != null && currentMediaItem.mediaId.equals(listInfo.getVideoId())) {
|
||||
vb.viewPlaying.setVisibility(View.VISIBLE);
|
||||
vb.itemLayout.setBackgroundColor(CommonUtils.getMyColor(R.color.cur_play_music));
|
||||
if (instance.getIsPlaying()) {
|
||||
vb.viewPlaying.startAnimating();
|
||||
lastVideId = listInfo.getVideoId();
|
||||
CommonUtils.LogMsg("-------playAnimation " + itemHolder.getAbsoluteAdapterPosition());
|
||||
} else {
|
||||
vb.viewPlaying.pauseAnimating();
|
||||
CommonUtils.LogMsg("-------pauseAnimation " + itemHolder.getAbsoluteAdapterPosition());
|
||||
}
|
||||
} else {
|
||||
vb.viewPlaying.setVisibility(View.GONE);
|
||||
vb.itemLayout.setBackgroundColor(CommonUtils.getMyColor(R.color.color_transparent));
|
||||
|
||||
}
|
||||
|
||||
vb.itemLayout.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
CommonUtils.LogMsg("-------onClick curMusicPos=" + itemHolder.getAbsoluteAdapterPosition());
|
||||
setCurVideId(listInfo.getVideoId());
|
||||
instance.playPositionMusic(itemHolder.getAbsoluteAdapterPosition());
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
package com.hi.music.player.adapter;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.databinding.ItemResultListAlbumBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.response.child.ResponseResultListChild;
|
||||
|
||||
public class AdapterResultListAlbum extends BaseAdapter<ResponseResultListChild, ItemResultListAlbumBinding>{
|
||||
@Override
|
||||
protected ItemResultListAlbumBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemResultListAlbumBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
ResponseResultListChild listChild = data.get(position);
|
||||
|
||||
|
||||
VHolder<ItemResultListAlbumBinding> itemHolder = (VHolder<ItemResultListAlbumBinding>) holder;
|
||||
ItemResultListAlbumBinding vb = itemHolder.getVb();
|
||||
if(position == data.size()-1){
|
||||
vb.view.setVisibility(View.VISIBLE);
|
||||
}else {
|
||||
vb.view.setVisibility(View.GONE);
|
||||
}
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.load(listChild.getThumbnail())
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.header);
|
||||
vb.tvTitle.setText(listChild.getSongName());
|
||||
vb.tvSubtitle.setText(listChild.getSubTitle());
|
||||
vb.header.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(homeItemClickListener != null){
|
||||
int absoluteAdapterPosition = itemHolder.getAbsoluteAdapterPosition();
|
||||
String videoId = listChild.getVideoId();
|
||||
String browserId = listChild.getBrowserId();
|
||||
homeItemClickListener.onClickResultSong(listChild,absoluteAdapterPosition);
|
||||
// if(videoId == null||videoId.isEmpty()){
|
||||
// homeItemClickListener.onClickResultAlbum(listChild,absoluteAdapterPosition);
|
||||
// }else if(browserId!= null&&!browserId.isEmpty()){
|
||||
// homeItemClickListener.onClickResultSong(listChild,absoluteAdapterPosition);
|
||||
// }
|
||||
}
|
||||
}
|
||||
});
|
||||
CommonUtils.LogMsg("-------Album getBrowserId="+listChild.getBrowserId()+"---getPlayListId= "+listChild.getPlayListId()+"---getVideoId="+listChild.getVideoId());
|
||||
}
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
package com.hi.music.player.adapter;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.databinding.ItemResultListSongBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.response.child.ResponseResultListChild;
|
||||
|
||||
public class AdapterResultListSong extends BaseAdapter<ResponseResultListChild, ItemResultListSongBinding> {
|
||||
@Override
|
||||
protected ItemResultListSongBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemResultListSongBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
ResponseResultListChild listChild = data.get(position);
|
||||
|
||||
VHolder<ItemResultListSongBinding> itemHolder = (VHolder<ItemResultListSongBinding>) holder;
|
||||
ItemResultListSongBinding vb = itemHolder.getVb();
|
||||
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.load(listChild.getThumbnail())
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.imCovert);
|
||||
vb.tvSongName.setText(listChild.getSongName());
|
||||
String playCount = listChild.getPlayCount();
|
||||
String subTitle = listChild.getSubTitle();
|
||||
if (playCount == null){
|
||||
vb.tvSubtitle.setText(subTitle);
|
||||
}else {
|
||||
String s = subTitle + " • " + playCount;
|
||||
vb.tvSubtitle.setText(s);
|
||||
}
|
||||
|
||||
|
||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (homeItemClickListener != null) {
|
||||
int absoluteAdapterPosition = itemHolder.getAbsoluteAdapterPosition();
|
||||
String videoId = listChild.getVideoId();
|
||||
String browserId = listChild.getBrowserId();
|
||||
homeItemClickListener.onClickResultSong(listChild, absoluteAdapterPosition);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CommonUtils.LogMsg("-------Song getBrowserId=" + listChild.getBrowserId() + "---getPlayListId= " + listChild.getPlayListId() + "---getVideoId=" + listChild.getVideoId());
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
package com.hi.music.player.adapter;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.databinding.ItemSearchBinding;
|
||||
import com.hi.music.player.databinding.ItemSearchChildBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.response.ResponseSearch;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSearchChild;
|
||||
|
||||
public class AdapterSearchChild extends BaseAdapter<ResponseSearchChild, ItemSearchChildBinding> {
|
||||
@Override
|
||||
protected ItemSearchChildBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemSearchChildBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
ResponseSearchChild responseSearchChild = data.get(position);
|
||||
VHolder<ItemSearchChildBinding> itemHolder = (VHolder<ItemSearchChildBinding>) holder;
|
||||
ItemSearchChildBinding vb = itemHolder.getVb();
|
||||
|
||||
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(13))))
|
||||
.load(responseSearchChild.getSongCovert())
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.imCovert);
|
||||
|
||||
vb.tvTitle.setText(responseSearchChild.getSongTitle());
|
||||
vb.tvSubtitle.setText(responseSearchChild.getSongDescribe());
|
||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (homeItemClickListener != null) {
|
||||
homeItemClickListener.onClickSearchResult(responseSearchChild);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
package com.hi.music.player.adapter;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.databinding.ItemSingerBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
||||
|
||||
public class AdapterSinger extends BaseAdapter<ResponseSingle, ItemSingerBinding> {
|
||||
|
||||
@Override
|
||||
protected ItemSingerBinding getViewBinding(ViewGroup parent) {
|
||||
return ItemSingerBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
int itemViewType = getItemViewType(position);
|
||||
if (itemViewType == TYPE_ITEM) {
|
||||
VHolder<ItemSingerBinding> itemHolder = (VHolder<ItemSingerBinding>) holder;
|
||||
ItemSingerBinding vb = itemHolder.getVb();
|
||||
ResponseSingle responseSingle = data.get(position);
|
||||
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.load(responseSingle.getSingerHead())
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.header);
|
||||
vb.tvSingerName.setText(responseSingle.getSingerName());
|
||||
vb.tvSongName.setText(responseSingle.getSongTitle());
|
||||
// vb.tvDescribe.setText(responseSingle.getDescription());
|
||||
vb.getRoot().setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (homeItemClickListener != null) {
|
||||
homeItemClickListener.onClickItemSinger(responseSingle);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
package com.hi.music.player.api;
|
||||
|
||||
public interface MediaControllerStatusListener {
|
||||
|
||||
|
||||
void onMediaControllerComplete(boolean isOk);
|
||||
|
||||
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.hi.music.player.api;
|
||||
|
||||
public interface OnHasUrlAction {
|
||||
void onHasUrl();
|
||||
}
|
||||
@ -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) ;
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
package com.hi.music.player.api;
|
||||
|
||||
import com.hi.music.player.javabean.CustomerDownload;
|
||||
|
||||
public interface onCheckDownload {
|
||||
void onHasDownload(CustomerDownload customerDownload);
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.hi.music.player.api;
|
||||
|
||||
public interface onImageColorListener {
|
||||
void onImageColor(int color);
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.hi.music.player.api;
|
||||
|
||||
public interface onPlayNextListener {
|
||||
void onPlayNext(boolean hasNext);
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,127 +0,0 @@
|
||||
package com.hi.music.player.dialog;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.net.Uri;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.adapter.AdapterPlayList;
|
||||
import com.hi.music.player.api.onImageColorListener;
|
||||
import com.hi.music.player.databinding.DialogPlayListBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
||||
import com.hi.music.player.media3.MyControllerView;
|
||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DialogPlayList extends BaseDialog<DialogPlayListBinding> {
|
||||
private MyMediaControllerManager instance;
|
||||
|
||||
@Override
|
||||
protected DialogPlayListBinding getViewBinding(LayoutInflater inflater, ViewGroup container) {
|
||||
return DialogPlayListBinding.inflate(inflater, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
|
||||
instance = MyMediaControllerManager.getInstance();
|
||||
initPlayListUi();
|
||||
|
||||
MediaItem currentMediaItem = instance.getCurMediaItem();
|
||||
if (currentMediaItem != null) {
|
||||
Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri;
|
||||
vb.topSongName.setText(currentMediaItem.mediaMetadata.title);
|
||||
vb.topSingerName.setText(currentMediaItem.mediaMetadata.artist);
|
||||
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10))))
|
||||
.load(artworkUri)
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
CommonUtils.getDominantDarkColor1(resource, new onImageColorListener() {
|
||||
@Override
|
||||
public void onImageColor(int color) {
|
||||
if (color == -1) {
|
||||
return;
|
||||
}
|
||||
int lighterColor = CommonUtils.adjustBrightness(color, 1.2f); // 比原始颜色亮 20%
|
||||
int darkerColor = CommonUtils.adjustBrightness(color, 0.8f); // 比原始颜色暗 20%
|
||||
// GradientDrawable gradientDrawable = new GradientDrawable(
|
||||
// GradientDrawable.Orientation.TOP_BOTTOM,
|
||||
// new int[]{lighterColor, darkerColor} // 浅到深渐变
|
||||
// );
|
||||
vb.topLayout.setBackgroundColor(darkerColor);
|
||||
Drawable newDrawable = CommonUtils.getNewDrawable(lighterColor, 24f, 24f, 0, 0);
|
||||
vb.listLayout.setBackground(newDrawable);
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.topIm);
|
||||
}
|
||||
vb.imPlay.setSelected(instance.getIsPlaying());
|
||||
|
||||
vb.imPlay.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
vb.imPlay.setSelected(!vb.imPlay.isSelected());
|
||||
if (vb.imPlay.isSelected()) {
|
||||
instance.play();
|
||||
} else {
|
||||
instance.pause();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullScreen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void initPlayListUi() {
|
||||
List<ResponsePlayListInfo> playList = instance.getPlayList();
|
||||
AdapterPlayList adapterPlayList = new AdapterPlayList();
|
||||
vb.recyclerList.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication));
|
||||
adapterPlayList.addData(playList);
|
||||
vb.recyclerList.setAdapter(adapterPlayList);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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:45:07
|
||||
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();
|
||||
//
|
||||
// }
|
||||
}
|
||||
@ -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;
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
package com.hi.music.player.javabean.requestbody.child;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
|
||||
public class ContextBody {
|
||||
|
||||
private Client client = new Client();
|
||||
|
||||
private ThirdParty thirdParty = new ThirdParty();
|
||||
|
||||
|
||||
// public ThirdParty getThirdParty() {
|
||||
// return thirdParty;
|
||||
// }
|
||||
|
||||
public Client getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void setClient(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class ThirdParty{
|
||||
//https://www.youtube.com/watch?v=UqyT8IEBkvY
|
||||
private String embedUrl;
|
||||
|
||||
public void setEmbedUrl(String embedUrl) {
|
||||
this.embedUrl = embedUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -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;
|
||||
// }
|
||||
}
|
||||
@ -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_MEDIUM、AUDIO_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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
// }
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -1,199 +0,0 @@
|
||||
package com.hi.music.player.media3;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.database.StandaloneDatabaseProvider;
|
||||
import androidx.media3.datasource.DefaultHttpDataSource;
|
||||
import androidx.media3.datasource.cache.SimpleCache;
|
||||
import androidx.media3.exoplayer.offline.Download;
|
||||
import androidx.media3.exoplayer.offline.DownloadCursor;
|
||||
import androidx.media3.exoplayer.offline.DownloadIndex;
|
||||
import androidx.media3.exoplayer.offline.DownloadManager;
|
||||
import androidx.media3.exoplayer.offline.DownloadNotificationHelper;
|
||||
import androidx.media3.exoplayer.offline.DownloadService;
|
||||
import androidx.media3.exoplayer.scheduler.Scheduler;
|
||||
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.api.onCheckDownload;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.javabean.CustomerDownload;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
|
||||
@UnstableApi
|
||||
public class MyDownloadService extends DownloadService {
|
||||
private static final int FOREGROUND_NOTIFICATION_ID = 1;
|
||||
private static final String CHANNEL_ID = "download_song_channel_id";
|
||||
|
||||
private static DownloadManager mDownloadManager;
|
||||
|
||||
private static SimpleCache downloadCache;
|
||||
|
||||
public MyDownloadService() {
|
||||
super(FOREGROUND_NOTIFICATION_ID,
|
||||
DEFAULT_FOREGROUND_NOTIFICATION_UPDATE_INTERVAL,
|
||||
CHANNEL_ID, // 通知渠道 ID
|
||||
R.string.app_name, // 通知渠道名称
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
public static SimpleCache getDownloadCache() {
|
||||
return downloadCache;
|
||||
}
|
||||
|
||||
public static void init(Context context, StandaloneDatabaseProvider databaseProvider) {
|
||||
if (mDownloadManager == null) {
|
||||
downloadCache = MyDownloadCacheManager.getMyCache(databaseProvider);
|
||||
DefaultHttpDataSource.Factory factory = new DefaultHttpDataSource.Factory();
|
||||
Executor downloadExecutor = Runnable::run;
|
||||
|
||||
mDownloadManager = new DownloadManager(
|
||||
context,
|
||||
databaseProvider, // 数据库提供者
|
||||
downloadCache,
|
||||
factory, // 数据源工厂
|
||||
downloadExecutor // 线程池
|
||||
);
|
||||
|
||||
mDownloadManager.setMaxParallelDownloads(3); // 设置最大并行下载数
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized DownloadManager getMyDownloadManager() {
|
||||
|
||||
return mDownloadManager;
|
||||
}
|
||||
|
||||
public static void addDownloadListener(VMApplication vmApplication) {
|
||||
mDownloadManager.addListener(new DownloadManager.Listener() {
|
||||
@Override
|
||||
public void onDownloadChanged(@NonNull DownloadManager downloadManager, Download download, @Nullable Exception finalException) {
|
||||
String id = download.request.id;
|
||||
|
||||
|
||||
if (download.state == Download.STATE_COMPLETED) {
|
||||
// 下载完成
|
||||
vmApplication.setDownloadChange(new Pair<>(true, download));
|
||||
CommonUtils.LogMsg("----------------下载完成 id=" + id + "--thread=" + Thread.currentThread().getName());
|
||||
updateDownloadUi(vmApplication);
|
||||
|
||||
} else if (download.state == Download.STATE_FAILED) {
|
||||
// 下载失败
|
||||
CommonUtils.LogMsg("----------------下载失败 id=" + id + "---finalException=" + finalException.getMessage());
|
||||
|
||||
vmApplication.setDownloadChange(new Pair<>(false, download));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadRemoved(DownloadManager downloadManager, Download download) {
|
||||
String id = download.request.id;
|
||||
CommonUtils.LogMsg("----------------onDownloadRemoved id=" + id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static void queryIsDownload(String videoId, onCheckDownload listener) {
|
||||
Disposable subscribe = Observable.fromCallable(() -> {
|
||||
// 不允许返回null,所以采用CustomerDownload类包装
|
||||
DownloadIndex downloadIndex = mDownloadManager.getDownloadIndex();
|
||||
Download download = downloadIndex.getDownload(videoId);
|
||||
|
||||
return new CustomerDownload(download, download != null);
|
||||
|
||||
}).subscribeOn(Schedulers.io())
|
||||
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(listener::onHasDownload);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 下载完成的数量增加
|
||||
*
|
||||
* @param vmApplication
|
||||
*/
|
||||
@UnstableApi
|
||||
public static void updateDownloadUi(VMApplication vmApplication) {
|
||||
Disposable subscribe = Observable.fromCallable(() -> {
|
||||
// 第一部分操作:在IO线程
|
||||
DownloadIndex downloadIndex = mDownloadManager.getDownloadIndex();
|
||||
DownloadCursor downloads = downloadIndex.getDownloads(Download.STATE_COMPLETED);
|
||||
|
||||
return downloads;
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
// .observeOn(Schedulers.computation()) // 切换到计算线程
|
||||
// .map(result -> {
|
||||
// // 第二部分操作:在computation线程
|
||||
// return result + " -> Step 2 completed";
|
||||
// })
|
||||
.observeOn(AndroidSchedulers.mainThread()) // 切换到主线程
|
||||
.subscribe(finalResult -> {
|
||||
// 最终结果处理:在主线程
|
||||
Download curDownload = null;
|
||||
// int count = finalResult.getCount();
|
||||
// if (finalResult.moveToLast()) {
|
||||
// curDownload = finalResult.getDownload();
|
||||
// }
|
||||
List<Download> downloadList = new ArrayList<>();
|
||||
while (finalResult.moveToNext()) {
|
||||
Download download = finalResult.getDownload();
|
||||
downloadList.add(download);
|
||||
}
|
||||
|
||||
|
||||
CommonUtils.LogMsg("----------------下载总数量 -count=" + downloadList.size());
|
||||
vmApplication.setDownloadData(downloadList);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected DownloadManager getDownloadManager() {
|
||||
return getMyDownloadManager();
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Scheduler getScheduler() {
|
||||
// 返回 null 表示不需要使用调度器
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Notification getForegroundNotification(List<Download> downloads, int notMetRequirements) {
|
||||
// 构建用于显示下载进度的通知
|
||||
return buildNotification(downloads, notMetRequirements);
|
||||
}
|
||||
|
||||
private Notification buildNotification(
|
||||
List<Download> downloads, int notMetRequirements) {
|
||||
|
||||
return new DownloadNotificationHelper(this, CHANNEL_ID)
|
||||
.buildProgressNotification(this, R.drawable.ic_download, null, null, downloads, notMetRequirements);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,421 +0,0 @@
|
||||
package com.hi.music.player.media3;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.MediaMetadata;
|
||||
import androidx.media3.common.PlaybackException;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.session.MediaController;
|
||||
import androidx.media3.session.SessionToken;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.api.MediaControllerListener;
|
||||
import com.hi.music.player.api.MediaControllerStatusListener;
|
||||
import com.hi.music.player.api.OnHasUrlAction;
|
||||
import com.hi.music.player.api.onCheckDownload;
|
||||
import com.hi.music.player.api.onPlayNextListener;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.CustomerDownload;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
||||
import com.hi.music.player.network.RetrofitManager;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class MyMediaControllerManager {
|
||||
|
||||
private static volatile MyMediaControllerManager myMediaControllerManagerInstance;
|
||||
|
||||
private MediaController mediaController;
|
||||
|
||||
private MediaControllerListener mListener;
|
||||
|
||||
private VMApplication mVmApplication;
|
||||
|
||||
|
||||
//播放列表总数量
|
||||
private List<ResponsePlayListInfo> playList;
|
||||
|
||||
public static MyMediaControllerManager getInstance() {
|
||||
if (myMediaControllerManagerInstance == null) {
|
||||
synchronized (RetrofitManager.class) {
|
||||
if (myMediaControllerManagerInstance == null) {
|
||||
myMediaControllerManagerInstance = new MyMediaControllerManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return myMediaControllerManagerInstance;
|
||||
}
|
||||
|
||||
public void init(MediaControllerStatusListener statusListener) {
|
||||
SessionToken sessionToken =
|
||||
new SessionToken(MusicApplication.myApplication, new ComponentName(MusicApplication.myApplication, PlaybackService.class));
|
||||
ListenableFuture<MediaController> controllerFuture =
|
||||
new MediaController.Builder(MusicApplication.myApplication, sessionToken).buildAsync();
|
||||
controllerFuture.addListener(() -> {
|
||||
// Call controllerFuture.get() to retrieve the MediaController.
|
||||
// MediaController implements the Player interface, so it can be
|
||||
// attached to the PlayerView UI component.
|
||||
// playerView.setPlayer(controllerFuture.get());
|
||||
try {
|
||||
mediaController = controllerFuture.get();
|
||||
statusListener.onMediaControllerComplete(true);
|
||||
CommonUtils.LogMsg("=-----mediaController+" + mediaController);
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
CommonUtils.LogErrorMsg(e.getMessage());
|
||||
statusListener.onMediaControllerComplete(false);
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void addListener(VMApplication vmApplication, MediaControllerListener listener) {
|
||||
mVmApplication = vmApplication;
|
||||
mListener = listener;
|
||||
mediaController.addListener(new Player.Listener() {
|
||||
@Override
|
||||
public void onPlayerError(PlaybackException error) {
|
||||
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_ERROR);
|
||||
mVmApplication.setPlayStatus(MyValue.PLAY_STATUS_CODE_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaItemTransition(@Nullable MediaItem mediaItem, int reason) {
|
||||
//当前媒体项发生变化,切歌
|
||||
if (mediaItem == null) {
|
||||
//第二次进入PlayActitivity ,调用resetPlayList(),这里为null
|
||||
return;
|
||||
}
|
||||
mListener.onChangeMusic(mediaItem);
|
||||
mVmApplication.setPlayStatus(MyValue.PLAY_STATUS_CHANGE_MUSIC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIsPlayingChanged(boolean isPlaying) {
|
||||
|
||||
if (isPlaying) {
|
||||
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PLAYING);
|
||||
mVmApplication.setPlayStatus(MyValue.PLAY_STATUS_CODE_PLAYING);
|
||||
// TODO: 2024/10/15 自动播放完成切歌到下一首播放没有触发这里请求下一首
|
||||
checkUrl(false);
|
||||
|
||||
} else {
|
||||
// 播放器暂停或停止
|
||||
mListener.onPlayStatus(MyValue.PLAY_STATUS_CODE_PAUSE);
|
||||
mVmApplication.setPlayStatus(MyValue.PLAY_STATUS_CODE_PAUSE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackStateChanged(int playbackState) {
|
||||
mListener.onPlayStatus(playbackState);
|
||||
mVmApplication.setPlayStatus(playbackState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity(Player.PositionInfo oldPosition, Player.PositionInfo newPosition, int reason) {
|
||||
// 快进、快退等操作
|
||||
// CommonUtils.LogMsg("=-----快进、快退+" + newPosition.positionMs);
|
||||
// mediaControllerListener.onPlayStatus(playbackState);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void checkUrl(boolean playNextNow) {
|
||||
if (mediaController.hasNextMediaItem()) {
|
||||
int nextMediaItemIndex = mediaController.getNextMediaItemIndex();
|
||||
onCallRequestUrl(nextMediaItemIndex, playNextNow, new OnHasUrlAction() {
|
||||
@Override
|
||||
public void onHasUrl() {
|
||||
CommonUtils.LogMsg("-------------有有效URl--播放检查下一首 位置=" + nextMediaItemIndex);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (mediaController.hasPreviousMediaItem()) {
|
||||
int previousMediaItemIndex = mediaController.getPreviousMediaItemIndex();
|
||||
onCallRequestUrl(previousMediaItemIndex, false, new OnHasUrlAction() {
|
||||
@Override
|
||||
public void onHasUrl() {
|
||||
CommonUtils.LogMsg("-------------有有效URl--播放检查上一首 位置=" + previousMediaItemIndex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public MediaController getMediaController() {
|
||||
return mediaController;
|
||||
}
|
||||
|
||||
/**
|
||||
* 针对已经下载过的数据,从download构造出MediaItem 直接替换
|
||||
* @param index
|
||||
* @param mediaItem
|
||||
*/
|
||||
public void replaceMediaItem(int index, MediaItem mediaItem) {
|
||||
mediaController.replaceMediaItem(index, mediaItem);
|
||||
}
|
||||
|
||||
public long getContentPos() {
|
||||
if (mediaController == null) return 0;
|
||||
return mediaController.getContentPosition();
|
||||
}
|
||||
|
||||
public long getBufferPos() {
|
||||
if (mediaController == null) return 0;
|
||||
return mediaController.getBufferedPosition();
|
||||
}
|
||||
|
||||
public MediaItem getCurMediaItem() {
|
||||
return mediaController.getCurrentMediaItem();
|
||||
}
|
||||
|
||||
public Boolean getIsPlaying() {
|
||||
return mediaController.isPlaying();
|
||||
}
|
||||
|
||||
public int getCurIndex() {
|
||||
return mediaController.getCurrentMediaItemIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* //0 不循环、1 单曲循环、2 列表循环、
|
||||
*
|
||||
* @param mode
|
||||
*/
|
||||
public void setMode(int mode) {
|
||||
switch (mode) {
|
||||
case 0:
|
||||
mediaController.setRepeatMode(Player.REPEAT_MODE_OFF);
|
||||
break;
|
||||
case 1:
|
||||
mediaController.setRepeatMode(Player.REPEAT_MODE_ONE);
|
||||
break;
|
||||
case 2:
|
||||
mediaController.setRepeatMode(Player.REPEAT_MODE_ALL);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getRepeatMode() {
|
||||
return mediaController.getRepeatMode();
|
||||
|
||||
}
|
||||
|
||||
public String getCurVideoId() {
|
||||
MediaItem currentMediaItem = mediaController.getCurrentMediaItem();
|
||||
if (currentMediaItem != null) {
|
||||
return currentMediaItem.mediaId;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新播放列表中的音频url
|
||||
*
|
||||
* @param playUrl
|
||||
*/
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
public void UpdateAudioUrl(ResponsePlayUrl playUrl, int index) {
|
||||
for (int i = 0; i < mediaController.getMediaItemCount(); i++) {
|
||||
MediaItem mediaItemAt = mediaController.getMediaItemAt(i);
|
||||
if (mediaItemAt.mediaId.equals(playUrl.getVideoId())) {
|
||||
|
||||
MediaItem.Builder builder = mediaItemAt.buildUpon();
|
||||
builder.setMediaId(playUrl.getVideoId());
|
||||
builder.setUri(playUrl.getVideoUrlMedium());
|
||||
// builder.setCustomCacheKey(playUrl.getVideoUrlMedium());
|
||||
//针对于,已经从分类合集列表页面进入播放页面的数据(只有小的封面图)
|
||||
if (mediaItemAt.mediaMetadata.artworkUri == null) {
|
||||
MediaMetadata.Builder builder1 = mediaItemAt.mediaMetadata.buildUpon();
|
||||
builder1.setArtworkUri(Uri.parse(playUrl.getBigCovert()));
|
||||
builder.setMediaMetadata(builder1.build());
|
||||
}
|
||||
|
||||
CharSequence title = mediaController.getMediaItemAt(i).mediaMetadata.title;
|
||||
CommonUtils.LogMsg("-------------更新播放列表中的音频--id=" + playUrl.getVideoId());
|
||||
mediaController.replaceMediaItem(i, builder.build());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlayList(List<ResponsePlayListInfo> playList) {
|
||||
this.playList = playList;
|
||||
addMusicPlayList(playList);
|
||||
}
|
||||
|
||||
public List<ResponsePlayListInfo> getPlayList() {
|
||||
return playList;
|
||||
}
|
||||
|
||||
public void resetPlayList() {
|
||||
mediaController.clearMediaItems();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加播放列表(不带音频url)
|
||||
* 注意没有setUri的不会被实际添加到mediaController(mediaController.getMediaItemCount())
|
||||
* 这里setUri 一个占位
|
||||
*
|
||||
* @param listInfo
|
||||
*/
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
public void addMusicPlayList(List<ResponsePlayListInfo> listInfo) {
|
||||
playList = listInfo;
|
||||
for (int i = 0; i < listInfo.size(); i++) {
|
||||
ResponsePlayListInfo playInfo = listInfo.get(i);
|
||||
|
||||
MediaItem.Builder builder = new MediaItem.Builder();
|
||||
String videoId = playInfo.getVideoId();
|
||||
//唯一标识符
|
||||
builder.setMediaId(videoId);
|
||||
builder.setUri("-------test-----");
|
||||
builder.setCustomCacheKey(videoId);
|
||||
MediaMetadata.Builder MediaMetadata_builder = new MediaMetadata.Builder();
|
||||
|
||||
MediaMetadata_builder.setArtist(playInfo.getSingerName());
|
||||
MediaMetadata_builder.setDescription(playInfo.getDuration());
|
||||
MediaMetadata_builder.setDurationMs(playInfo.getDurationMs());
|
||||
if (playInfo.getCovert() != null && !playInfo.getCovert().isEmpty())
|
||||
MediaMetadata_builder.setArtworkUri(Uri.parse(playInfo.getCovert()));
|
||||
MediaMetadata_builder.setTitle(playInfo.getSongTitle());
|
||||
|
||||
CommonUtils.LogMsg("----------添加播放列表 i=" + i + "---" + playInfo.getSingerName() + "-------VideoId=" + videoId + "---playInfo.getDuration()=" + playInfo.getDuration());
|
||||
// MediaMetadata_builder.setRecordingYear(Integer.parseInt(playInfo.getYear()));
|
||||
builder.setMediaMetadata(MediaMetadata_builder.build());
|
||||
mediaController.addMediaItem(builder.build());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void addMusicPlayList(MediaItem mediaItem) {
|
||||
mediaController.addMediaItem(mediaItem);
|
||||
}
|
||||
|
||||
public void play() {
|
||||
if (!mediaController.isPlaying()) {
|
||||
CommonUtils.LogMsg("-----------prepare");
|
||||
mediaController.prepare();
|
||||
mediaController.play();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
if (mediaController.isPlaying())
|
||||
mediaController.pause();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (mediaController.isPlaying())
|
||||
mediaController.stop();
|
||||
}
|
||||
|
||||
public void playNext(onPlayNextListener listener) {
|
||||
if (mediaController.hasNextMediaItem()) {
|
||||
int nextMediaItemIndex = mediaController.getNextMediaItemIndex();
|
||||
|
||||
onCallRequestUrl(nextMediaItemIndex, true, new OnHasUrlAction() {
|
||||
@Override
|
||||
public void onHasUrl() {
|
||||
mediaController.seekToNextMediaItem();
|
||||
mediaController.play();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
listener.onPlayNext(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void playPrevious() {
|
||||
if (mediaController.hasPreviousMediaItem()) {
|
||||
|
||||
int previousMediaItemIndex = mediaController.getPreviousMediaItemIndex();
|
||||
onCallRequestUrl(previousMediaItemIndex, true, new OnHasUrlAction() {
|
||||
@Override
|
||||
public void onHasUrl() {
|
||||
mediaController.seekToPreviousMediaItem();
|
||||
mediaController.play();
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
mediaController.seekTo(0);
|
||||
mediaController.play();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 播放指定播放列表位置的歌曲
|
||||
*
|
||||
* @param index
|
||||
*/
|
||||
public void playPositionMusic(int index) {
|
||||
if (index >= mediaController.getMediaItemCount()) {
|
||||
CommonUtils.LogErrorMsg("-------------数组越界");
|
||||
return;
|
||||
}
|
||||
|
||||
stop();
|
||||
mediaController.seekTo(index, 0);
|
||||
onCallRequestUrl(index, true, new OnHasUrlAction() {
|
||||
@Override
|
||||
public void onHasUrl() {
|
||||
mediaController.play();
|
||||
CommonUtils.LogMsg("-------------有有效URl--播放指定播放列表位置的歌曲 index=" + index);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private void onCallRequestUrl(int index, boolean playNow, OnHasUrlAction action) {
|
||||
MediaItem mediaItemAt = mediaController.getMediaItemAt(index);
|
||||
boolean b = CommonUtils.hasValidUri(mediaItemAt);
|
||||
if (!b) {
|
||||
//查看
|
||||
MyDownloadService.queryIsDownload(mediaItemAt.mediaId, new onCheckDownload() {
|
||||
@Override
|
||||
public void onHasDownload(CustomerDownload customerDownload) {
|
||||
if (customerDownload.isDownload()) {
|
||||
MediaItem mediaItem = CommonUtils.downloadToMediaItem(customerDownload.getDownloadData());
|
||||
mediaController.replaceMediaItem(index, mediaItem);
|
||||
CommonUtils.LogMsg("-------------请求URl 已经下载过 index" + index + "---playNow=" + playNow);
|
||||
} else {
|
||||
CommonUtils.LogMsg("-------------请求URl index" + index + "---playNow=" + playNow);
|
||||
mListener.onRequestNextUri(mediaItemAt.mediaId, index, playNow);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
action.onHasUrl();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
package com.hi.music.player.media3;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.database.StandaloneDatabaseProvider;
|
||||
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor;
|
||||
import androidx.media3.datasource.cache.SimpleCache;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
/**
|
||||
* 播放缓存
|
||||
*/
|
||||
public class MyPlayCacheManager {
|
||||
|
||||
private static SimpleCache playCache;
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
public static SimpleCache getInitPlayCache(Context context) {
|
||||
if (playCache == null) {
|
||||
File cacheDir = new File(context.getCacheDir(), "media_cache");
|
||||
long maxCacheSize = 100 * 1024 * 1024; // 缓存大小 100MB
|
||||
StandaloneDatabaseProvider databaseProvider = new StandaloneDatabaseProvider(context);
|
||||
playCache = new SimpleCache(cacheDir, new LeastRecentlyUsedCacheEvictor(maxCacheSize), databaseProvider);
|
||||
// MyDownloadService.init(context,databaseProvider);
|
||||
}
|
||||
return playCache;
|
||||
}
|
||||
|
||||
public static SimpleCache getPlayCache() {
|
||||
return playCache;
|
||||
}
|
||||
}
|
||||
@ -1,176 +0,0 @@
|
||||
package com.hi.music.player.media3;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.datasource.DataSource;
|
||||
import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.datasource.DefaultDataSource;
|
||||
import androidx.media3.datasource.DefaultHttpDataSource;
|
||||
import androidx.media3.datasource.ResolvingDataSource;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.datasource.cache.CacheDataSource;
|
||||
import androidx.media3.datasource.cache.SimpleCache;
|
||||
import androidx.media3.exoplayer.DefaultLoadControl;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
|
||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
|
||||
import androidx.media3.exoplayer.source.MediaSource;
|
||||
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
|
||||
import androidx.media3.session.MediaSession;
|
||||
import androidx.media3.session.MediaSessionService;
|
||||
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class PlaybackService extends MediaSessionService {
|
||||
private MediaSession mediaSession = null;
|
||||
private ExoPlayer player;
|
||||
|
||||
private SimpleCache playCache, downloadCache;
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
DynamicMediaSourceFactory customMediaSourceFactory = new DynamicMediaSourceFactory(getCacheDataSourceFactory(this));
|
||||
ProgressiveMediaSource.Factory factory = new ProgressiveMediaSource.Factory(getUrlFactory());
|
||||
|
||||
|
||||
// 创建 DefaultLoadControl,配置缓冲参数
|
||||
DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
|
||||
.setBufferDurationsMs(3000, // minBufferMs: 播放前的最小缓冲时间(毫秒)
|
||||
300000, // maxBufferMs: 最大缓冲时间(毫秒)
|
||||
3000, // bufferForPlaybackMs: 播放时的目标缓冲时间(毫秒)
|
||||
2000) // bufferForPlaybackAfterRebufferMs: 重新缓冲后的缓冲时间(毫秒)
|
||||
.build();
|
||||
|
||||
|
||||
CacheDataSource.Factory cacheDataSourceFactory = getCacheDataSourceFactory(this);
|
||||
MediaSource.Factory mediaSourceFactory = new ProgressiveMediaSource.Factory(cacheDataSourceFactory);
|
||||
CacheDataSource dataSource = cacheDataSourceFactory.createDataSource();
|
||||
|
||||
player = new ExoPlayer.Builder(this)
|
||||
.setMediaSourceFactory(factory)
|
||||
.setLoadControl(loadControl)
|
||||
.build();
|
||||
mediaSession = new MediaSession.Builder(this, player)
|
||||
.build();
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 创建带缓存的数据源工厂
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private CacheDataSource.Factory getCacheDataSourceFactory(Context context) {
|
||||
DefaultDataSource.Factory factory = new DefaultDataSource.Factory(this);
|
||||
playCache = MyPlayCacheManager.getInitPlayCache(context);
|
||||
CacheDataSource.Factory factory1 = new CacheDataSource.Factory().setCache(playCache)
|
||||
.setUpstreamDataSourceFactory(new DefaultHttpDataSource.Factory()
|
||||
.setConnectTimeoutMs(16000)
|
||||
.setReadTimeoutMs(8000)
|
||||
.setUserAgent("Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0"))
|
||||
.setEventListener(new CacheDataSource.EventListener() {
|
||||
@Override
|
||||
public void onCachedBytesRead(long cacheSizeBytes, long cachedBytesRead) {
|
||||
CommonUtils.LogMsg("-----------缓存2 -PlayCache-" + cacheSizeBytes + "----cacheSizeBytes=" + cachedBytesRead);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCacheIgnored(int reason) {
|
||||
CommonUtils.LogMsg("-----------缓存2忽略 PlayCache=" + reason);
|
||||
}
|
||||
});
|
||||
downloadCache = MyDownloadService.getDownloadCache();
|
||||
return new CacheDataSource.Factory()
|
||||
.setCache(downloadCache)
|
||||
.setUpstreamDataSourceFactory(factory1)
|
||||
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
|
||||
.setEventListener(new CacheDataSource.EventListener() {
|
||||
@Override
|
||||
public void onCachedBytesRead(long cacheSizeBytes, long cachedBytesRead) {
|
||||
CommonUtils.LogMsg("-----------缓存1 DownloadCache --" + cacheSizeBytes + "----cacheSizeBytes=" + cachedBytesRead);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCacheIgnored(int reason) {
|
||||
CommonUtils.LogMsg("-----------缓存1忽略DownloadCache =" + reason);
|
||||
}
|
||||
});
|
||||
// .setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
|
||||
}
|
||||
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private DataSource.Factory getUrlFactory() {
|
||||
long chunkLength = 512 * 1024L;
|
||||
return new ResolvingDataSource.Factory(getCacheDataSourceFactory(this), new ResolvingDataSource.Resolver() {
|
||||
|
||||
|
||||
@Override
|
||||
public DataSpec resolveDataSpec(DataSpec dataSpec) {
|
||||
CommonUtils.LogMsg("--------resolveDataSpec dataSpec.key=" + dataSpec.key+"---dataSpec.uri="+dataSpec.uri);
|
||||
return dataSpec;
|
||||
|
||||
// long length = 1L;
|
||||
// String videoId = dataSpec.key;
|
||||
// long position = dataSpec.position;
|
||||
// if (dataSpec.length >= 0) {
|
||||
// length = dataSpec.length;
|
||||
// }
|
||||
//
|
||||
// if (downloadCache.isCached(videoId,position,length)){
|
||||
// CommonUtils.LogMsg("--------resolveDataSpec downloadCache" );
|
||||
// return dataSpec;
|
||||
// }else if(playCache.isCached(videoId,position,chunkLength)){
|
||||
// CommonUtils.LogMsg("--------resolveDataSpec playCache" );
|
||||
// return dataSpec;
|
||||
// }else {
|
||||
// CommonUtils.LogMsg("--------resolveDataSpec uri" );
|
||||
// return dataSpec;
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri resolveReportedUri(Uri uri) {
|
||||
CommonUtils.LogMsg("--------resolveDataSpec uri=" + uri);
|
||||
return ResolvingDataSource.Resolver.super.resolveReportedUri(Uri.parse("---"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) {
|
||||
return mediaSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskRemoved(@Nullable Intent rootIntent) {
|
||||
Player player = mediaSession.getPlayer();
|
||||
if (!player.getPlayWhenReady()
|
||||
|| player.getMediaItemCount() == 0
|
||||
|| player.getPlaybackState() == Player.STATE_ENDED) {
|
||||
// Stop the service if not playing, continue playing in the background
|
||||
// otherwise.
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
mediaSession.getPlayer().release();
|
||||
mediaSession.release();
|
||||
mediaSession = null;
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
@ -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
@ -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);
|
||||
|
||||
}
|
||||
@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,207 +0,0 @@
|
||||
package com.hi.music.player.network;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.api.RequestListener;
|
||||
import com.hi.music.player.javabean.requestbody.BodyHome;
|
||||
import com.hi.music.player.javabean.requestbody.BodyPlay;
|
||||
import com.hi.music.player.javabean.requestbody.BodyPlayUrl;
|
||||
import com.hi.music.player.javabean.requestbody.BodySearch;
|
||||
import com.hi.music.player.javabean.requestbody.BodySearchSuggestion;
|
||||
import com.hi.music.player.javabean.requestbody.child.Client;
|
||||
import com.hi.music.player.javabean.requestbody.child.ContextBody;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
public class RetrofitManager {
|
||||
|
||||
private String base_Host = "https://music.youtube.com/";
|
||||
|
||||
private String base_Host_test = "https://rr2---sn-tt1e7nlz.googlevideo.com/";
|
||||
private static volatile RetrofitManager REQUEST_MANAGER;
|
||||
|
||||
private Retrofit retrofit;
|
||||
public MediaType JSON = MediaType.get("application/json; charset=utf-8");
|
||||
private MusicApi musicApi;
|
||||
|
||||
private String header1 = "playlistPanelVideoRenderer(title,navigationEndpoint,longBylineText,shortBylineText,thumbnail,lengthText)";
|
||||
private String header = "contents.singleColumnMusicWatchNextResultsRenderer.tabbedRenderer.watchNextTabbedResultsRenderer.tabs.tabRenderer.content.musicQueueRenderer.content.playlistPanelRenderer(continuations,contents(automixPreviewVideoRenderer," + header1 + "))";
|
||||
|
||||
private RetrofitManager() {
|
||||
|
||||
musicApi = getRetrofit().create(MusicApi.class);
|
||||
}
|
||||
private synchronized Retrofit getRetrofit() {
|
||||
if (retrofit == null) {
|
||||
long DEFAULT_TIMEOUT = 5;
|
||||
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
|
||||
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
OkHttpClient client = new OkHttpClient.Builder()
|
||||
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
|
||||
.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
|
||||
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
|
||||
.addInterceptor(httpLoggingInterceptor)
|
||||
.build();
|
||||
retrofit = new Retrofit.Builder()
|
||||
.baseUrl(base_Host)
|
||||
.client(client)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
.build();
|
||||
}
|
||||
return retrofit;
|
||||
}
|
||||
|
||||
public static RetrofitManager getInstance() {
|
||||
if (REQUEST_MANAGER == null) {
|
||||
synchronized (RetrofitManager.class) { //锁,防止线程问题
|
||||
if (REQUEST_MANAGER == null) {
|
||||
REQUEST_MANAGER = new RetrofitManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return REQUEST_MANAGER;
|
||||
}
|
||||
|
||||
|
||||
public void getHomeData(RequestListener<ResponseBody> requestListener) {
|
||||
BodyHome bodyHome = new BodyHome();
|
||||
Gson gson = new Gson();
|
||||
String s = gson.toJson(bodyHome);
|
||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
||||
musicApi.getHomeData(requestBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.unsubscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new ObserverWrapper<ResponseBody>(requestListener));
|
||||
}
|
||||
|
||||
public void getHomeMoreData(String continuation, String itct, String visitorData, RequestListener<ResponseBody> requestListener) {
|
||||
BodyHome bodyHome = new BodyHome();
|
||||
bodyHome.getContext().getClient().setVisitorData(visitorData);
|
||||
Gson gson = new Gson();
|
||||
String s = gson.toJson(bodyHome);
|
||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
||||
|
||||
HashMap<String, String> stringHashMap = new HashMap<>();
|
||||
stringHashMap.put("ctoken", continuation);
|
||||
stringHashMap.put("continuation", continuation);
|
||||
stringHashMap.put("type", "next");
|
||||
stringHashMap.put("itct", itct);
|
||||
stringHashMap.put("prettyPrint", "false");
|
||||
musicApi.getHomeMoreData(continuation, continuation, "next", itct, false, requestBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.unsubscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new ObserverWrapper<ResponseBody>(requestListener));
|
||||
}
|
||||
|
||||
|
||||
public void getPlayList(String params, String playlistId, String videoId, String musicVideoType, RequestListener<ResponseBody> requestListener) {
|
||||
BodyPlay bodyPlay = new BodyPlay();
|
||||
bodyPlay.setParams(params);
|
||||
bodyPlay.setPlaylistId(playlistId);
|
||||
bodyPlay.setVideoId(videoId);
|
||||
bodyPlay.getWatchEndpointMusicSupportedConfigs().setMusicVideoType(musicVideoType);
|
||||
Gson gson = new Gson();
|
||||
String s = gson.toJson(bodyPlay);
|
||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
||||
musicApi.getMusicPlayPage(header, requestBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.unsubscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new ObserverWrapper<ResponseBody>(requestListener));
|
||||
}
|
||||
|
||||
|
||||
public void getPlayUrl(String videoId, RequestListener<ResponseBody> requestListener) {
|
||||
BodyPlayUrl bodyPlay = new BodyPlayUrl();
|
||||
bodyPlay.setVideoId(videoId);
|
||||
Client client = bodyPlay.getContext().getClient();
|
||||
client.setClientName("ANDROID");
|
||||
client.setClientVersion("19.05.36");
|
||||
client.setPlatform("DESKTOP");
|
||||
String visitorData = MusicApplication.getVisitorData();
|
||||
// client.setVisitorData("CgtWN1RXaURPN3LNZyiZK9e4BjIKCgJVUXIEGgAgPW%3D%3D");
|
||||
client.setVisitorData(visitorData);
|
||||
// bodyPlay.getContext().getThirdParty().setEmbedUrl("https://www.youtube.com/watch?v="+videoId);
|
||||
|
||||
|
||||
Gson gson = new Gson();
|
||||
String s = gson.toJson(bodyPlay);
|
||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
||||
musicApi.getMusicPlayUrl(requestBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.unsubscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new ObserverWrapper<ResponseBody>(requestListener));
|
||||
}
|
||||
|
||||
|
||||
public void getCategoryList(String browserId, RequestListener<ResponseBody> requestListener) {
|
||||
BodyHome bodyHome = new BodyHome();
|
||||
bodyHome.setBrowseId(browserId);
|
||||
// bodyHome.setBrowseId("VLPLI-asvmHZWNo_xjMMfD_v2O2lTyCdrjaK");
|
||||
|
||||
Client client = bodyHome.getContext().getClient();
|
||||
client.setClientVersion("1.20240506.01.00");
|
||||
|
||||
|
||||
Gson gson = new Gson();
|
||||
String s = gson.toJson(bodyHome);
|
||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
||||
|
||||
|
||||
musicApi.getCategoryList(requestBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.unsubscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new ObserverWrapper<>(requestListener));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void getSearchSuggestion(String input, RequestListener<ResponseBody> requestListener) {
|
||||
BodySearchSuggestion body = new BodySearchSuggestion();
|
||||
body.setInput(input);
|
||||
Client client = body.getContext().getClient();
|
||||
client.setClientVersion("1.20240506.01.00");
|
||||
Gson gson = new Gson();
|
||||
String s = gson.toJson(body);
|
||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
||||
musicApi.getSearchSuggestion(requestBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.unsubscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new ObserverWrapper<>(requestListener));
|
||||
}
|
||||
|
||||
|
||||
public void getSearch(String query, RequestListener<ResponseBody> requestListener) {
|
||||
BodySearch body = new BodySearch();
|
||||
body.setQuery(query);
|
||||
Client client = body.getContext().getClient();
|
||||
client.setClientVersion("1.20240506.01.00");
|
||||
Gson gson = new Gson();
|
||||
String s = gson.toJson(body);
|
||||
RequestBody requestBody = RequestBody.Companion.create(s, JSON);
|
||||
musicApi.getSearch(requestBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.unsubscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new ObserverWrapper<>(requestListener));
|
||||
}
|
||||
}
|
||||
@ -1,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,252 +0,0 @@
|
||||
package com.hi.music.player.ui.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.view.WindowCompat;
|
||||
import androidx.core.view.WindowInsetsControllerCompat;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.CircleCrop;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.api.onPlayNextListener;
|
||||
import com.hi.music.player.databinding.ActivityBaseBinding;
|
||||
import com.hi.music.player.databinding.LayoutPanelBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.helper.ViewModelScope;
|
||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
||||
|
||||
public abstract class BaseActivity<T extends ViewBinding> extends AppCompatActivity implements View.OnClickListener {
|
||||
|
||||
private final ViewModelScope mViewModelScope = new ViewModelScope();
|
||||
|
||||
protected T vb;
|
||||
|
||||
private Window window;
|
||||
private View decorView;
|
||||
protected View mView;
|
||||
private ActivityBaseBinding rootVb;
|
||||
|
||||
protected VMApplication vmApplication;
|
||||
protected MyMediaControllerManager mediaControllerManager;
|
||||
|
||||
private Handler mHandler;
|
||||
private Runnable mRunnable;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
vb = getViewBinding();
|
||||
View root = vb.getRoot();
|
||||
rootVb = ActivityBaseBinding.inflate(getLayoutInflater(), null, false);
|
||||
rootVb.frameLayout.addView(root);
|
||||
setContentView(rootVb.getRoot());
|
||||
window = getWindow();
|
||||
decorView = window.getDecorView();
|
||||
mView = decorView.getRootView();
|
||||
vmApplication = getApplicationScopeViewModel(VMApplication.class);
|
||||
mediaControllerManager = MyMediaControllerManager.getInstance();
|
||||
|
||||
if (showPanel())
|
||||
initPanel();
|
||||
setStatusBar();
|
||||
if (isFullScreen()) {
|
||||
// ImmersionBar.with(this).init();//设置沉浸式效果
|
||||
// ImmersionBar.setStatusBarView(this,0);
|
||||
initFullScreen();
|
||||
}
|
||||
onCreateInit();
|
||||
onInitClick();
|
||||
}
|
||||
|
||||
protected abstract T getViewBinding();
|
||||
|
||||
|
||||
protected abstract void onCreateInit();
|
||||
|
||||
protected abstract void onInitClick();
|
||||
|
||||
public abstract boolean isFullScreen();
|
||||
|
||||
public abstract boolean statusBarLight();
|
||||
|
||||
public abstract boolean showPanel();
|
||||
|
||||
|
||||
|
||||
private void initPanel() {
|
||||
LayoutPanelBinding panelVb = LayoutPanelBinding.inflate(getLayoutInflater());
|
||||
View panelView = panelVb.getRoot();
|
||||
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
CommonUtils.dpToPx(74)
|
||||
);
|
||||
initProgressHandler(panelVb);
|
||||
panelVb.imPlay.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
panelVb.imPlay.setSelected(!panelVb.imPlay.isSelected());
|
||||
if (panelVb.imPlay.isSelected()) {
|
||||
mediaControllerManager.play();
|
||||
} else {
|
||||
mediaControllerManager.pause();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
panelVb.imNext.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mediaControllerManager.playNext(new onPlayNextListener() {
|
||||
@Override
|
||||
public void onPlayNext(boolean hasNext) {
|
||||
if (!hasNext) {
|
||||
Toast.makeText(MusicApplication.myApplication, getString(R.string.no_next_song_yet), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
panelVb.layoutPanel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(MusicApplication.myApplication, PlayActivity.class);
|
||||
intent.putExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_PANEL);
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
if (this instanceof HomeActivity) {
|
||||
layoutParams.setMargins(CommonUtils.dpToPx(22), 0, CommonUtils.dpToPx(22), CommonUtils.dpToPx(82));
|
||||
} else {
|
||||
layoutParams.setMargins(CommonUtils.dpToPx(22), 0, CommonUtils.dpToPx(22), CommonUtils.dpToPx(10));
|
||||
}
|
||||
|
||||
layoutParams.gravity = Gravity.BOTTOM;
|
||||
vmApplication.playStatus.observe(this, new Observer<Integer>() {
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public void onChanged(Integer integer) {
|
||||
CommonUtils.LogMsg("----------面板 播放状态更新=" + integer);
|
||||
if (panelView.getParent() == null) {
|
||||
CommonUtils.LogMsg("----------显示面板");
|
||||
rootVb.frameLayout.addView(panelView, layoutParams);
|
||||
mHandler.post(mRunnable);
|
||||
}
|
||||
MediaItem currentMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
if(currentMediaItem!= null){
|
||||
Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri;
|
||||
CharSequence title = currentMediaItem.mediaMetadata.title;
|
||||
CharSequence artist = currentMediaItem.mediaMetadata.artist;
|
||||
|
||||
if (currentMediaItem.mediaMetadata.durationMs != null) {
|
||||
long durationMs = currentMediaItem.mediaMetadata.durationMs;
|
||||
panelVb.circularPb.setMaxProgress((int) durationMs);
|
||||
}
|
||||
if(artworkUri!= null){
|
||||
CommonUtils.LogMsg("----------artworkUri="+artworkUri.toString());
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.load(artworkUri.toString())
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.transform(new CircleCrop())
|
||||
.into(panelVb.image);
|
||||
}
|
||||
panelVb.title.setText(title);
|
||||
panelVb.singer.setText(artist);
|
||||
}
|
||||
|
||||
switch (integer) {
|
||||
case Player.STATE_IDLE:
|
||||
|
||||
case Player.STATE_ENDED:
|
||||
case Player.STATE_READY:
|
||||
|
||||
case MyValue.PLAY_STATUS_CODE_PAUSE:
|
||||
case Player.STATE_BUFFERING:
|
||||
case MyValue.PLAY_STATUS_CODE_ERROR:
|
||||
|
||||
//快进没有缓冲的时候触发
|
||||
//播放完成
|
||||
panelVb.imPlay.setSelected(false);
|
||||
break;
|
||||
case MyValue.PLAY_STATUS_CHANGE_MUSIC:
|
||||
case MyValue.PLAY_STATUS_CODE_PLAYING:
|
||||
panelVb.imPlay.setSelected(true);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void initProgressHandler(LayoutPanelBinding panelBinding) {
|
||||
mHandler = new Handler();
|
||||
mRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updatePlaybackProgress(panelBinding);
|
||||
mHandler.postDelayed(this, 1000);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void updatePlaybackProgress(LayoutPanelBinding panelBinding) {
|
||||
// 获取当前播放位置
|
||||
long contentPos = mediaControllerManager.getContentPos();
|
||||
long bufferPos = mediaControllerManager.getBufferPos();
|
||||
|
||||
// CommonUtils.LogMsg("---------播放进度-----contentPos=" + contentPos + "-----缓冲进度=" + bufferPos);
|
||||
panelBinding.circularPb.setProgress((int) contentPos);
|
||||
}
|
||||
private void setStatusBar() {
|
||||
//深色模式
|
||||
WindowInsetsControllerCompat insetsController = WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView());
|
||||
insetsController.setAppearanceLightStatusBars(statusBarLight());
|
||||
}
|
||||
|
||||
private void initFullScreen() {
|
||||
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
// mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
|
||||
protected <K extends ViewModel> K getActivityScopeViewModel(@NonNull Class<K> modelClass) {
|
||||
return mViewModelScope.getActivityScopeViewModel(this, modelClass);
|
||||
}
|
||||
|
||||
protected <K extends ViewModel> K getApplicationScopeViewModel(@NonNull Class<K> modelClass) {
|
||||
return mViewModelScope.getApplicationScopeViewModel(modelClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mHandler != null && mRunnable != null)
|
||||
mHandler.removeCallbacks(mRunnable);
|
||||
}
|
||||
}
|
||||
@ -1,259 +0,0 @@
|
||||
package com.hi.music.player.ui.activity;
|
||||
|
||||
import static com.bumptech.glide.request.RequestOptions.bitmapTransform;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransitionOptions;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.adapter.AdapterCategoryList;
|
||||
import com.hi.music.player.api.HomeItemClickListener;
|
||||
import com.hi.music.player.api.onImageColorListener;
|
||||
import com.hi.music.player.databinding.ActivityCategoryListBinding;
|
||||
import com.hi.music.player.databinding.ActivityHomeBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.response.ResponseCategoryList;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
||||
import com.hi.music.player.javabean.response.child.ResponseCategory;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMCategoryList;
|
||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMHome;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import jp.wasabeef.glide.transformations.BlurTransformation;
|
||||
|
||||
|
||||
/**
|
||||
* 音乐合集或者专辑列表页面
|
||||
*/
|
||||
public class CategoryListActivity extends BaseActivity<ActivityCategoryListBinding> implements HomeItemClickListener {
|
||||
|
||||
|
||||
private VMCategoryList vm;
|
||||
// private VMApplication vmApplication;
|
||||
|
||||
private ResponseCategoryList mCategoryList;
|
||||
private String mPageType;
|
||||
private String twoSubtitle;
|
||||
private String browseId;
|
||||
|
||||
@Override
|
||||
protected ActivityCategoryListBinding getViewBinding() {
|
||||
return ActivityCategoryListBinding.inflate(getLayoutInflater());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreateInit() {
|
||||
vm = getActivityScopeViewModel(VMCategoryList.class);
|
||||
// vmApplication = getApplicationScopeViewModel(VMApplication.class);
|
||||
Intent intent = getIntent();
|
||||
if (intent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPageType= intent.getStringExtra(MyValue.KEY_CATEGORY_LIST_TYPE);
|
||||
twoSubtitle = intent.getStringExtra(MyValue.KEY_CATEGORY_LIST_SINGER_NAME);
|
||||
browseId = intent.getStringExtra(MyValue.KEY_CATEGORY_LIST_BROWSER_ID);
|
||||
|
||||
vb.pbLoading.setVisibility(View.VISIBLE);
|
||||
vm.getList(browseId);
|
||||
vm.data.observe(this, new Observer<ResponseCategoryList>() {
|
||||
@Override
|
||||
public void onChanged(ResponseCategoryList responseCategoryList) {
|
||||
if (responseCategoryList == null) {
|
||||
vb.pbLoading.setVisibility(View.GONE);
|
||||
updateErrorLayout(getString(R.string.playList_loading_failed),true);
|
||||
return;
|
||||
}
|
||||
mCategoryList = responseCategoryList;
|
||||
loadInfo(mCategoryList);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
private void updateErrorLayout(String msg, boolean isShow) {
|
||||
if (isShow)
|
||||
vb.layoutError.linearRetry.setVisibility(View.VISIBLE);
|
||||
else vb.layoutError.linearRetry.setVisibility(View.GONE);
|
||||
|
||||
if(msg!= null&&!msg.isEmpty()){
|
||||
vb.layoutError.tvErrorMsg.setText(msg);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onInitClick() {
|
||||
vb.imBack.setOnClickListener(this);
|
||||
vb.btnPlay.setOnClickListener(this);
|
||||
vb.layoutError.tvRetry.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullScreen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean statusBarLight() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showPanel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.equals(vb.imBack)) {
|
||||
finish();
|
||||
} else if (v.equals(vb.btnPlay)) {
|
||||
int musicIndex = 0;
|
||||
Intent intent = new Intent(this, PlayActivity.class);
|
||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST, mCategoryList.getList().get(musicIndex));
|
||||
// intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST_INDEX,musicIndex);
|
||||
intent.putExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_SOURCE_CATEGORY);
|
||||
startActivity(intent);
|
||||
vmApplication.reSetPlayList(mCategoryList.getList());
|
||||
}else if(v.equals(vb.layoutError.tvRetry)){
|
||||
vb.pbLoading.setVisibility(View.VISIBLE);
|
||||
updateErrorLayout(null,false);
|
||||
vm.getList(browseId);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadInfo(ResponseCategoryList info) {
|
||||
vb.btnPlay.setVisibility(View.VISIBLE);
|
||||
switch (mPageType) {
|
||||
case MyValue.PAGE_TYPE_LIST:
|
||||
vb.tvSingerName.setVisibility(View.GONE);
|
||||
break;
|
||||
case MyValue.PAGE_TYPE_ALBUM:
|
||||
vb.tvSingerName.setVisibility(View.VISIBLE);
|
||||
String singNameValue = "";
|
||||
String singName = info.getSingName();
|
||||
if(singName!= null&&!singName.isEmpty()){
|
||||
singNameValue= singName;
|
||||
}else {
|
||||
String[] split = twoSubtitle.split("•");
|
||||
if (split != null && split.length > 1) {
|
||||
singNameValue = split[1];
|
||||
}
|
||||
}
|
||||
CommonUtils.LogMsg("singNameValue=" + singNameValue);
|
||||
vb.tvSingerName.setText(singNameValue);
|
||||
for (ResponsePlayListInfo playListInfo : info.getList()) {
|
||||
playListInfo.setSingerName(singNameValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
vb.tvTitle.setText(info.getTitle());
|
||||
vb.tvSubTitle.setText(info.getDescription());
|
||||
|
||||
AdapterCategoryList adapterCategoryList = new AdapterCategoryList();
|
||||
adapterCategoryList.setHomeItemClickListener(this);
|
||||
adapterCategoryList.setPageType(mPageType);
|
||||
vb.recyclerview.setLayoutManager(new LinearLayoutManager(this));
|
||||
adapterCategoryList.setData(info.getList());
|
||||
vb.recyclerview.setAdapter(adapterCategoryList);
|
||||
loadCovert(info.getCovert());
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void loadCovert(String url) {
|
||||
// 加载图片并应用高斯模糊效果
|
||||
Glide.with(this)
|
||||
.load(url)
|
||||
.apply(bitmapTransform(new BlurTransformation(25, 3))) // 设置模糊半径和模糊采样
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
CommonUtils.extractColorsFromImage(resource,vb.imBg);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.preload();
|
||||
|
||||
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
// .apply(bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10))))
|
||||
.load(url)
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
vb.pbLoading.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
// CommonUtils.getDominantDarkColor1(resource, new onImageColorListener() {
|
||||
// @Override
|
||||
// public void onImageColor(int color) {
|
||||
// if (color == -1) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// });
|
||||
vb.pbLoading.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.imCovert);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onClickItemCategoryList(ResponsePlayListInfo data, int musicIndex) {
|
||||
Intent intent = new Intent(this, PlayActivity.class);
|
||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST, data);
|
||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST_INDEX, musicIndex);
|
||||
intent.putExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_SOURCE_CATEGORY);
|
||||
startActivity(intent);
|
||||
vmApplication.reSetPlayList(mCategoryList.getList());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -1,862 +0,0 @@
|
||||
package com.hi.music.player.ui.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.MediaMetadata;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.datasource.cache.SimpleCache;
|
||||
import androidx.media3.exoplayer.offline.Download;
|
||||
import androidx.media3.exoplayer.offline.DownloadManager;
|
||||
import androidx.media3.exoplayer.offline.DownloadRequest;
|
||||
import androidx.media3.exoplayer.offline.DownloadService;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.google.gson.Gson;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.adapter.AdapterDownloadSong;
|
||||
import com.hi.music.player.adapter.AdapterPlayList;
|
||||
import com.hi.music.player.api.LikeSongListener;
|
||||
import com.hi.music.player.api.MediaControllerListener;
|
||||
import com.hi.music.player.api.onCheckDownload;
|
||||
import com.hi.music.player.api.onImageColorListener;
|
||||
import com.hi.music.player.api.onPlayNextListener;
|
||||
import com.hi.music.player.databinding.ActivityPlayBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.BoxDownloadSong;
|
||||
import com.hi.music.player.javabean.BoxLikeSong;
|
||||
import com.hi.music.player.javabean.CustomerDownload;
|
||||
import com.hi.music.player.javabean.CustomerUrlInfo;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayListInfo;
|
||||
import com.hi.music.player.javabean.response.ResponsePlayUrl;
|
||||
import com.hi.music.player.javabean.response.child.ResponseCategory;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
||||
import com.hi.music.player.media3.MyDownloadService;
|
||||
import com.hi.music.player.media3.MyMediaControllerManager;
|
||||
import com.hi.music.player.media3.MyPlayCacheManager;
|
||||
import com.hi.music.player.objectbox.ObjectBoxManager;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMPlay;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PlayActivity extends BaseActivity<ActivityPlayBinding> implements SeekBar.OnSeekBarChangeListener {
|
||||
|
||||
|
||||
//单曲进入传递的数据
|
||||
private ResponseSingle responseSingle;
|
||||
private VMPlay vmPlay;
|
||||
|
||||
|
||||
private Handler mHandler;
|
||||
private Runnable mRunnable;
|
||||
|
||||
|
||||
private AdapterPlayList adapterPlayList;
|
||||
|
||||
|
||||
//播放列表ui初始化
|
||||
private boolean initPlayList = false;
|
||||
|
||||
private GradientDrawable gradientDrawable;
|
||||
private int lighterColor, darkerColor;
|
||||
|
||||
// 0 播放列表请求失败 1 立即播放的歌曲请求失败 2 封面图加载失败
|
||||
private int netError = 0;
|
||||
|
||||
|
||||
// 请求失败的立即播放的歌曲信息
|
||||
private CustomerUrlInfo mCustomerUrlInfo;
|
||||
private int mEnterType;
|
||||
|
||||
|
||||
//-------单曲进入播放列表接口请求需要的参数
|
||||
private String playlistId, videoId, params, musicVideoType = "";
|
||||
//-------单曲进入播放列表接口请求需要的参数
|
||||
|
||||
private int mDefaultPlayStartIndex = 0;
|
||||
|
||||
|
||||
private int[] imageStates = {
|
||||
R.drawable.icon_looper_no,
|
||||
R.drawable.icon_looper_1,
|
||||
R.drawable.icon_looper
|
||||
};
|
||||
|
||||
//0 不循环、1 列表循环、2 单曲循环、
|
||||
private int currentMode = 0;
|
||||
|
||||
private List<BoxDownloadSong> downloadSongList = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected ActivityPlayBinding getViewBinding() {
|
||||
return ActivityPlayBinding.inflate(getLayoutInflater());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreateInit() {
|
||||
// vb.progressBarLoading.setVisibility(View.VISIBLE);
|
||||
vmPlay = getActivityScopeViewModel(VMPlay.class);
|
||||
initMediaController();
|
||||
Intent intent = getIntent();
|
||||
mEnterType = intent.getIntExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_SOURCE_SINGLE);
|
||||
initPlayerView();
|
||||
initProgressHandler();
|
||||
|
||||
CommonUtils.LogMsg("--------mEnterType=" + mEnterType);
|
||||
switch (mEnterType) {
|
||||
case MyValue.TYPE_ENTER_SOURCE_SINGLE:
|
||||
// 0--首页单曲进入
|
||||
updateMediaPlayList();
|
||||
responseSingle = (ResponseSingle) intent.getSerializableExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER);
|
||||
playlistId = responseSingle.getPlaylistId();
|
||||
videoId = responseSingle.getVideoId();
|
||||
params = responseSingle.getParams();
|
||||
musicVideoType = responseSingle.getMusicVideoType();
|
||||
mDefaultPlayStartIndex = intent.getIntExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST_INDEX, mDefaultPlayStartIndex);
|
||||
|
||||
SimpleCache playCache = MyPlayCacheManager.getPlayCache();
|
||||
// boolean songCached = CommonUtils.isSongCached(playCache, videoId);
|
||||
|
||||
// CommonUtils.LogMsg("---------------是否有播放缓存--songCached="+songCached +"--name="+responseSingle.getSongTitle());
|
||||
|
||||
vmPlay.getPlayMusicList(playlistId, videoId, params, musicVideoType);
|
||||
vmPlay.playList.observe(this, new Observer<List<ResponsePlayListInfo>>() {
|
||||
@Override
|
||||
public void onChanged(List<ResponsePlayListInfo> listInfos) {
|
||||
vmApplication.reSetPlayList(listInfos);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case MyValue.TYPE_ENTER_SOURCE_CATEGORY:
|
||||
// 1--首页音乐分类合集列表进入
|
||||
|
||||
updateMediaPlayList();
|
||||
ResponsePlayListInfo playListInfo = (ResponsePlayListInfo) intent.getSerializableExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST);
|
||||
mDefaultPlayStartIndex = intent.getIntExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST_INDEX, mDefaultPlayStartIndex);
|
||||
videoId = playListInfo.getVideoId();
|
||||
break;
|
||||
|
||||
case MyValue.TYPE_ENTER_SOURCE_MV:
|
||||
// 2--首页单个视频mv进入
|
||||
|
||||
updateMediaPlayList();
|
||||
ResponseCategory responseCategory = (ResponseCategory) intent.getSerializableExtra(MyValue.KEY_PLAY_ACTIVITY_MV);
|
||||
videoId = responseCategory.getVideoId();
|
||||
playlistId = responseCategory.getPlayListId();
|
||||
params = responseCategory.getParams();
|
||||
musicVideoType = responseCategory.getMusicVideoType();
|
||||
vmPlay.getPlayMusicList(playlistId, videoId, params, musicVideoType);
|
||||
vmPlay.playList.observe(this, new Observer<List<ResponsePlayListInfo>>() {
|
||||
@Override
|
||||
public void onChanged(List<ResponsePlayListInfo> listInfos) {
|
||||
vmApplication.reSetPlayList(listInfos);
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
case MyValue.TYPE_ENTER_PANEL:
|
||||
// 3--控制面板进入
|
||||
MediaItem curMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
loadInfo(curMediaItem);
|
||||
mHandler.post(mRunnable);
|
||||
vb.progressBarLoading.setVisibility(View.GONE);
|
||||
vb.btnPlay.setSelected(mediaControllerManager.getIsPlaying());
|
||||
break;
|
||||
|
||||
case MyValue.TYPE_ENTER_LIKE:
|
||||
// 4--从喜爱歌曲进入
|
||||
updateMediaPlayList();
|
||||
videoId = intent.getStringExtra(MyValue.KEY_PLAY_VIDEO_ID);
|
||||
mDefaultPlayStartIndex = intent.getIntExtra(MyValue.KEY_PLAY_INDEX, mDefaultPlayStartIndex);
|
||||
CommonUtils.LogMsg("-------------like进入 videoId= " + videoId + "---mDefaultPlayStartIndex=" + mDefaultPlayStartIndex);
|
||||
break;
|
||||
|
||||
case MyValue.TYPE_ENTER_DOWNLOAD:
|
||||
// 5--从下载歌曲进入
|
||||
videoId = intent.getStringExtra(MyValue.KEY_PLAY_VIDEO_ID);
|
||||
mDefaultPlayStartIndex = intent.getIntExtra(MyValue.KEY_PLAY_INDEX, mDefaultPlayStartIndex);
|
||||
CommonUtils.LogMsg("-------------下载歌曲 videoId= " + videoId + "---mDefaultPlayStartIndex=" + mDefaultPlayStartIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
addDownloadListener();
|
||||
vmPlay.playUrlLiveData.observe(this, new Observer<CustomerUrlInfo>() {
|
||||
@Override
|
||||
public void onChanged(CustomerUrlInfo customerUrlInfo) {
|
||||
if (customerUrlInfo.isNeedPlayNow() && customerUrlInfo.getPlayUrl() == null) {
|
||||
// TODO: 2024/9/26 需要马上播放这首歌曲,但是此次网络请求失败
|
||||
CommonUtils.LogErrorMsg("-------------需要马上播放这首歌曲,但是此次网络请求失败");
|
||||
updateErrorLayout(getString(R.string.song_loading_failed), true);
|
||||
netError = 1;
|
||||
mCustomerUrlInfo = customerUrlInfo;
|
||||
initShowPlayList(false);
|
||||
vb.progressBarLoading.setVisibility(View.GONE);
|
||||
mediaControllerManager.pause();
|
||||
return;
|
||||
}
|
||||
int second = customerUrlInfo.getPlayMusicIndex();
|
||||
if (customerUrlInfo.isNeedPlayNow()) {
|
||||
mediaControllerManager.playPositionMusic(second);
|
||||
// mediaControllerManager.play();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新播放列表
|
||||
*/
|
||||
private void updateMediaPlayList() {
|
||||
vmApplication.playList.observe(this, new Observer<List<ResponsePlayListInfo>>() {
|
||||
@Override
|
||||
public void onChanged(List<ResponsePlayListInfo> playList) {
|
||||
if (playList == null) {
|
||||
CommonUtils.LogErrorMsg("--------更新-playList null");
|
||||
netError = 0;
|
||||
updateErrorLayout(getString(R.string.playList_loading_failed), true);
|
||||
vb.progressBarLoading.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
CommonUtils.LogMsg("--------更新-playList " + playList.size() + "--videoId=" + videoId);
|
||||
if (playList.size() > 0) {
|
||||
updateErrorLayout(null, false);
|
||||
setPlayListAndGetUrl(playList, videoId, mDefaultPlayStartIndex);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateErrorLayout(String msg, boolean isShow) {
|
||||
if (isShow)
|
||||
vb.layoutError.linearRetry.setVisibility(View.VISIBLE);
|
||||
else vb.layoutError.linearRetry.setVisibility(View.GONE);
|
||||
|
||||
if (msg != null && !msg.isEmpty()) {
|
||||
vb.layoutError.tvErrorMsg.setText(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置播放列表,并请求当前需要播放的音乐url
|
||||
*
|
||||
* @param list
|
||||
* @param id
|
||||
* @param index
|
||||
*/
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private void setPlayListAndGetUrl(List<ResponsePlayListInfo> list, String id, int index) {
|
||||
mediaControllerManager.resetPlayList();
|
||||
MyMediaControllerManager.getInstance().setPlayList(list);
|
||||
MyDownloadService.queryIsDownload(id, new onCheckDownload() {
|
||||
@Override
|
||||
public void onHasDownload(CustomerDownload customerDownload) {
|
||||
if(customerDownload.isDownload()){
|
||||
MediaItem mediaItem = CommonUtils.downloadToMediaItem(customerDownload.getDownloadData());
|
||||
mediaControllerManager.replaceMediaItem(index,mediaItem);
|
||||
CommonUtils.LogMsg("-------------setPlayListAndGetUrl已经下载过 index" + index + "---playNow=" + true);
|
||||
mediaControllerManager.playPositionMusic(index);
|
||||
}else {
|
||||
CommonUtils.LogMsg("-------------setPlayListAndGetUrl index" + index + "---playNow=" + true);
|
||||
vmPlay.getPlayUrl(id, index, true);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private void initPlayerView() {
|
||||
vb.playerView.setShowRewindButton(false);
|
||||
vb.playerView.setShowPreviousButton(false);
|
||||
vb.playerView.setPlayer(mediaControllerManager.getMediaController());
|
||||
}
|
||||
|
||||
private void initMediaController() {
|
||||
int repeatMode = mediaControllerManager.getRepeatMode();
|
||||
CommonUtils.LogMsg("-------------repeatMode=" + repeatMode);
|
||||
vb.btnLoop.setImageResource(imageStates[repeatMode]);
|
||||
mediaControllerManager.addListener(vmApplication, new MediaControllerListener() {
|
||||
@Override
|
||||
public void onPlayStatus(int playStatus) {
|
||||
|
||||
switch (playStatus) {
|
||||
case Player.STATE_IDLE:
|
||||
CommonUtils.LogMsg("-------------IDLE");
|
||||
break;
|
||||
case Player.STATE_BUFFERING:
|
||||
//快进没有缓冲的时候触发
|
||||
vb.btnPlay.setSelected(false);
|
||||
// vb.progressBarLoading.setVisibility(View.VISIBLE);
|
||||
CommonUtils.LogMsg("-------------缓冲");
|
||||
break;
|
||||
case Player.STATE_READY:
|
||||
vb.btnPlay.setSelected(true);
|
||||
mHandler.post(mRunnable);
|
||||
vb.progressBarLoading.setVisibility(View.GONE);
|
||||
CommonUtils.LogMsg("-------------准备");
|
||||
break;
|
||||
|
||||
case Player.STATE_ENDED:
|
||||
//播放完成
|
||||
vb.btnPlay.setSelected(false);
|
||||
CommonUtils.LogMsg("------------- 播放完成");
|
||||
mHandler.removeCallbacks(mRunnable); // 停止更新
|
||||
updatePlayComplete();
|
||||
break;
|
||||
|
||||
case MyValue.PLAY_STATUS_CODE_PAUSE:
|
||||
CommonUtils.LogMsg("------------- 暂停");
|
||||
vb.btnPlay.setSelected(false);
|
||||
vb.layoutPlayList.imPlay.setSelected(false);
|
||||
break;
|
||||
case MyValue.PLAY_STATUS_CODE_PLAYING:
|
||||
|
||||
CommonUtils.LogMsg("------------- 播放ing getCurIndex=" + mediaControllerManager.getCurIndex());
|
||||
vb.progressBarLoading.setVisibility(View.GONE);
|
||||
updateErrorLayout(null, false);
|
||||
vb.btnPlay.setSelected(true);
|
||||
vb.layoutPlayList.imPlay.setSelected(true);
|
||||
break;
|
||||
case MyValue.PLAY_STATUS_CODE_ERROR:
|
||||
vb.progressBarLoading.setVisibility(View.GONE);
|
||||
int currentMediaItemIndex = mediaControllerManager.getMediaController().getCurrentMediaItemIndex();
|
||||
CommonUtils.LogMsg("------------- 播放错误 currentMediaItemIndex=" + currentMediaItemIndex);
|
||||
mediaControllerManager.playPositionMusic(currentMediaItemIndex);
|
||||
// TODO: 2024/10/16
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestNextUri(String videoId, int playListIndex, boolean playNow) {
|
||||
if (playNow) {
|
||||
// vb.progressBarLoading.setVisibility(View.VISIBLE);
|
||||
}
|
||||
vmPlay.getPlayUrl(videoId, playListIndex, playNow);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onChangeMusic(MediaItem mediaItem) {
|
||||
CommonUtils.LogMsg("歌曲切换-" + mediaItem.mediaMetadata.title + "---id=" + mediaItem.mediaId);
|
||||
loadInfo(mediaItem);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitClick() {
|
||||
vb.btnPlay.setOnClickListener(this);
|
||||
vb.playProgress.setOnSeekBarChangeListener(this);
|
||||
vb.btnNext.setOnClickListener(this);
|
||||
vb.btnPrevious.setOnClickListener(this);
|
||||
vb.imBack.setOnClickListener(this);
|
||||
vb.btnMusicList.setOnClickListener(this);
|
||||
vb.layoutError.tvRetry.setOnClickListener(this);
|
||||
vb.btnLoop.setOnClickListener(this);
|
||||
vb.layoutLike.setOnClickListener(this);
|
||||
vb.layoutDownload.setOnClickListener(this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新播放进度Ui、缓冲进度
|
||||
*/
|
||||
private void updatePlaybackProgress() {
|
||||
// 获取当前播放位置
|
||||
long contentPos = mediaControllerManager.getContentPos();
|
||||
long bufferPos = mediaControllerManager.getBufferPos();
|
||||
|
||||
|
||||
String s = CommonUtils.convertMillisToTime(contentPos);
|
||||
vb.tvCurrent.setText(s);
|
||||
vb.playProgress.setProgress((int) contentPos);
|
||||
vb.progressBarBuffer.setProgress((int) bufferPos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 播放完成 更新播放进度Ui
|
||||
*/
|
||||
private void updatePlayComplete() {
|
||||
vb.tvCurrent.setText(vb.tvDuration.getText().toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加载当前播放歌曲信息
|
||||
*/
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private void loadInfo(MediaItem mediaItem) {
|
||||
MediaMetadata mediaMetadata = mediaItem.mediaMetadata;
|
||||
CommonUtils.LogMsg("--------------加载当前播放歌曲信息 title=" + mediaMetadata.title);
|
||||
if (mediaMetadata.artworkUri != null) {
|
||||
loadCovert(mediaMetadata.artworkUri.toString());
|
||||
}
|
||||
vb.tvSongName.setText(mediaMetadata.title);
|
||||
vb.tvSingerName.setText(mediaMetadata.artist);
|
||||
vb.tvDuration.setText(mediaMetadata.description);
|
||||
|
||||
if (mediaMetadata.durationMs != null) {
|
||||
long durationMs = mediaMetadata.durationMs;
|
||||
vb.playProgress.setMax((int) durationMs);
|
||||
vb.progressBarBuffer.setMax((int) durationMs);
|
||||
}
|
||||
if (vb.layoutPlayList.linearLayout.getVisibility() == View.VISIBLE) {
|
||||
updatePlayListUi();
|
||||
}
|
||||
|
||||
//刷新当前歌曲的喜爱状态
|
||||
boolean isLike = ObjectBoxManager.queryIsLike(mediaItem.mediaId);
|
||||
vb.imLike.setSelected(isLike);
|
||||
|
||||
//刷新当前歌曲的下载状态
|
||||
String mediaId = mediaItem.mediaId;
|
||||
MyDownloadService.queryIsDownload(mediaId, new onCheckDownload() {
|
||||
@Override
|
||||
public void onHasDownload(CustomerDownload customerDownload) {
|
||||
vb.imDownload.setSelected(customerDownload.isDownload());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void loadCovert(String url) {
|
||||
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
.load(url)
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
// netError = 2;
|
||||
// vb.tvErrorMsg.setText(getString(R.string.image_loading_failed));
|
||||
// vb.linearRetry.setVisibility(View.VISIBLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
vb.imCovert.setImageDrawable(resource);
|
||||
CommonUtils.getMainColor(resource, new onImageColorListener() {
|
||||
@Override
|
||||
public void onImageColor(int color) {
|
||||
if (color == -1) {
|
||||
return;
|
||||
}
|
||||
lighterColor = CommonUtils.adjustBrightness(color, 0.8f); // 比原始颜色亮 20%
|
||||
darkerColor = CommonUtils.adjustBrightness(color, 0.6f); // 比原始颜色暗 20%
|
||||
gradientDrawable = new GradientDrawable(
|
||||
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||
new int[]{lighterColor, darkerColor} // 浅到深渐变
|
||||
);
|
||||
vb.rootLayout.setBackground(gradientDrawable);
|
||||
|
||||
if (vb.layoutPlayList.linearLayout.getVisibility() == View.VISIBLE) {
|
||||
updatePlayListColor();
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.preload();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void initProgressHandler() {
|
||||
mHandler = new Handler();
|
||||
mRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updatePlaybackProgress();
|
||||
mHandler.postDelayed(this, 1000);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullScreen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean statusBarLight() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showPanel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.equals(vb.btnPlay)) {
|
||||
vb.btnPlay.setSelected(!vb.btnPlay.isSelected());
|
||||
if (vb.btnPlay.isSelected()) {
|
||||
mediaControllerManager.play();
|
||||
} else {
|
||||
mediaControllerManager.pause();
|
||||
}
|
||||
} else if (v.equals(vb.btnNext)) {
|
||||
mediaControllerManager.playNext(new onPlayNextListener() {
|
||||
@Override
|
||||
public void onPlayNext(boolean hasNext) {
|
||||
if (!hasNext) {
|
||||
Toast.makeText(PlayActivity.this, getString(R.string.no_next_song_yet), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} else if (v.equals(vb.btnPrevious)) {
|
||||
mediaControllerManager.playPrevious();
|
||||
} else if (v.equals(vb.imBack)) {
|
||||
finish();
|
||||
} else if (v.equals(vb.btnMusicList)) {
|
||||
initShowPlayList(true);
|
||||
} else if (v.equals(vb.layoutPlayList.imPlay)) {
|
||||
vb.layoutPlayList.imPlay.setSelected(!vb.layoutPlayList.imPlay.isSelected());
|
||||
if (vb.layoutPlayList.imPlay.isSelected()) {
|
||||
mediaControllerManager.play();
|
||||
} else {
|
||||
mediaControllerManager.pause();
|
||||
}
|
||||
if (adapterPlayList != null) {
|
||||
adapterPlayList.updateCurMusicAnimation();
|
||||
}
|
||||
} else if (v.equals(vb.layoutError.tvRetry)) {
|
||||
//重试按钮
|
||||
updateErrorLayout(null, false);
|
||||
switch (netError) {
|
||||
case 0:
|
||||
switch (mEnterType) {
|
||||
case MyValue.TYPE_ENTER_SOURCE_SINGLE:
|
||||
vmPlay.getPlayMusicList(playlistId, videoId, params, musicVideoType);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
vb.progressBarLoading.setVisibility(View.VISIBLE);
|
||||
int curIndex = mediaControllerManager.getCurIndex();
|
||||
|
||||
String curVideoId = mediaControllerManager.getCurVideoId();
|
||||
|
||||
String videoId1 = mCustomerUrlInfo.getVideoId();
|
||||
int playMusicIndex = mCustomerUrlInfo.getPlayMusicIndex();
|
||||
|
||||
CommonUtils.LogMsg("-------重试 curIndex=" + curIndex + "----curVideoId=" + curVideoId + "---videoId1=" + videoId1 + "---playMusicIndex=" + playMusicIndex);
|
||||
|
||||
vmPlay.getPlayUrl(mCustomerUrlInfo.getVideoId(), mCustomerUrlInfo.getPlayMusicIndex(), true);
|
||||
break;
|
||||
case 2:
|
||||
MediaItem curMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
MediaMetadata mediaMetadata = curMediaItem.mediaMetadata;
|
||||
if (mediaMetadata.artworkUri != null) {
|
||||
loadCovert(mediaMetadata.artworkUri.toString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (v.equals(vb.btnLoop)) {
|
||||
currentMode = (currentMode + 1) % imageStates.length;
|
||||
vb.btnLoop.setImageResource(imageStates[currentMode]);
|
||||
CommonUtils.LogMsg("----currentMode=" + currentMode);
|
||||
mediaControllerManager.setMode(currentMode);
|
||||
} else if (v.equals(vb.layoutLike)) {
|
||||
boolean selected = vb.imLike.isSelected();
|
||||
vb.imLike.setSelected(!selected);
|
||||
boolean newSelect = vb.imLike.isSelected();
|
||||
MediaItem curMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
MediaMetadata mediaMetadata = curMediaItem.mediaMetadata;
|
||||
if (mediaMetadata.title != null && mediaMetadata.artist != null && mediaMetadata.durationMs != null && mediaMetadata.description != null) {
|
||||
BoxLikeSong boxLikeSong = new BoxLikeSong(mediaMetadata.title.toString(),
|
||||
mediaMetadata.artist.toString(),
|
||||
curMediaItem.mediaId,
|
||||
String.valueOf(mediaMetadata.artworkUri),
|
||||
mediaMetadata.durationMs, mediaMetadata.description.toString());
|
||||
if (newSelect) {
|
||||
ObjectBoxManager.insertOrUpdateLike(boxLikeSong);
|
||||
} else {
|
||||
ObjectBoxManager.deleteLike(boxLikeSong);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if (v.equals(vb.layoutDownload)) {
|
||||
if (vb.imDownload.isSelected()) {
|
||||
//已经下载
|
||||
Toast.makeText(this,getText(R.string.text_has_downloaded),Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
vb.downloadPb.setVisibility(View.VISIBLE);
|
||||
vb.imDownload.setVisibility(View.INVISIBLE);
|
||||
BoxDownloadSong curMediaItemInfo = getCurMediaItemInfo();
|
||||
if (curMediaItemInfo != null) {
|
||||
Gson gson = new Gson();
|
||||
String info = gson.toJson(curMediaItemInfo);
|
||||
byte[] data = info.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
String videoId1 = curMediaItemInfo.getVideoId();
|
||||
CommonUtils.LogMsg("----------------开始下载 id=" + videoId1);
|
||||
DownloadRequest downloadRequest = new DownloadRequest.Builder(videoId1, Uri.parse(curMediaItemInfo.getVideoUrl()))
|
||||
.setMimeType("video/mp4")
|
||||
.setData(data)
|
||||
.build();
|
||||
|
||||
// 启动 DownloadService 进行下载
|
||||
DownloadService.sendAddDownload(
|
||||
this,
|
||||
MyDownloadService.class, // 上面定义的下载服务类
|
||||
downloadRequest,
|
||||
true // 是否在前台运行
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private BoxDownloadSong getCurMediaItemInfo() {
|
||||
MediaItem curMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
if (curMediaItem == null) {
|
||||
return null;
|
||||
}
|
||||
MediaMetadata mediaMetadata = curMediaItem.mediaMetadata;
|
||||
if (mediaMetadata.title == null || mediaMetadata.artist == null || mediaMetadata.description == null
|
||||
|| mediaMetadata.durationMs == null || curMediaItem.localConfiguration == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BoxDownloadSong boxDownloadSong = new BoxDownloadSong();
|
||||
boxDownloadSong.setVideoId(curMediaItem.mediaId);
|
||||
boxDownloadSong.setCovert(String.valueOf(mediaMetadata.artworkUri));
|
||||
boxDownloadSong.setSongName((String) mediaMetadata.title);
|
||||
boxDownloadSong.setSingerName((String) mediaMetadata.artist);
|
||||
boxDownloadSong.setDuration((String) mediaMetadata.description);
|
||||
boxDownloadSong.setDurationMs(mediaMetadata.durationMs);
|
||||
boxDownloadSong.setVideoUrl(String.valueOf(curMediaItem.localConfiguration.uri));
|
||||
|
||||
return boxDownloadSong;
|
||||
}
|
||||
|
||||
/**
|
||||
* 控制播放列表的显示
|
||||
*
|
||||
* @param show
|
||||
*/
|
||||
private void initShowPlayList(boolean show) {
|
||||
if (show) {
|
||||
Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_up);
|
||||
vb.layoutPlayList.linearLayout.startAnimation(animation);
|
||||
vb.layoutPlayList.linearLayout.setVisibility(View.VISIBLE);
|
||||
vb.contentLayout.setVisibility(View.GONE);
|
||||
|
||||
if (!initPlayList) {
|
||||
List<ResponsePlayListInfo> playList;
|
||||
if (mEnterType == MyValue.TYPE_ENTER_DOWNLOAD){
|
||||
playList = new ArrayList<>();
|
||||
for(BoxDownloadSong data:downloadSongList){
|
||||
ResponsePlayListInfo playListInfo = new ResponsePlayListInfo();
|
||||
playListInfo.setSongTitle(data.getSongName());
|
||||
playListInfo.setSingerName(data.getSingerName());
|
||||
playListInfo.setCovert(data.getCovert());
|
||||
playListInfo.setSmallCovert(data.getCovert());
|
||||
playListInfo.setVideoId(data.getVideoId());
|
||||
playListInfo.setDuration(data.getDuration());
|
||||
playListInfo.setDurationMs(data.getDurationMs());
|
||||
playList.add(playListInfo);
|
||||
}
|
||||
|
||||
}else {
|
||||
playList = mediaControllerManager.getPlayList();
|
||||
}
|
||||
adapterPlayList = new AdapterPlayList();
|
||||
vb.layoutPlayList.recyclerList.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication));
|
||||
adapterPlayList.setData(playList);
|
||||
// TODO: 2024/10/16 播放列表显示
|
||||
vb.layoutPlayList.recyclerList.setAdapter(adapterPlayList);
|
||||
vb.layoutPlayList.imPlay.setOnClickListener(this);
|
||||
initPlayList = true;
|
||||
|
||||
}
|
||||
updatePlayListUi();
|
||||
|
||||
} else {
|
||||
|
||||
vb.rootLayout.setBackground(gradientDrawable);
|
||||
vb.contentLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_down);
|
||||
vb.layoutPlayList.linearLayout.startAnimation(animation);
|
||||
vb.layoutPlayList.linearLayout.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新播放列表的显示
|
||||
*/
|
||||
private void updatePlayListUi() {
|
||||
CommonUtils.LogMsg("----------更新播放列表的显示");
|
||||
|
||||
MediaItem currentMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
if (currentMediaItem != null) {
|
||||
if (adapterPlayList != null) {
|
||||
adapterPlayList.setCurVideId(currentMediaItem.mediaId);
|
||||
}
|
||||
Uri artworkUri = currentMediaItem.mediaMetadata.artworkUri;
|
||||
vb.layoutPlayList.topSongName.setText(currentMediaItem.mediaMetadata.title);
|
||||
vb.layoutPlayList.topSingerName.setText(currentMediaItem.mediaMetadata.artist);
|
||||
updatePlayListColor();
|
||||
Glide.with(MusicApplication.myApplication)
|
||||
.asDrawable()
|
||||
// .apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(10))))
|
||||
.load(artworkUri)
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.layoutPlayList.topIm);
|
||||
}
|
||||
vb.layoutPlayList.imPlay.setSelected(mediaControllerManager.getIsPlaying());
|
||||
}
|
||||
|
||||
private void updatePlayListColor() {
|
||||
vb.layoutPlayList.topLayout.setBackgroundColor(darkerColor);
|
||||
GradientDrawable gradientDrawable = new GradientDrawable(
|
||||
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||
new int[]{darkerColor, darkerColor}
|
||||
);
|
||||
vb.rootLayout.setBackground(gradientDrawable);
|
||||
Drawable newDrawable = CommonUtils.getNewDrawable(lighterColor, 24f, 24f, 0, 0);
|
||||
vb.layoutPlayList.listLayout.setBackground(newDrawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mHandler != null && mRunnable != null)
|
||||
mHandler.removeCallbacks(mRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (vb.layoutPlayList.linearLayout.getVisibility() == View.VISIBLE) {
|
||||
initShowPlayList(false);
|
||||
} else {
|
||||
super.onBackPressed(); // 调用系统默认的返回行为
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
if (fromUser) {
|
||||
mediaControllerManager.getMediaController().seekTo(progress);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private void addDownloadListener() {
|
||||
MyDownloadService.addDownloadListener(vmApplication);
|
||||
vmApplication.downloadData.observe(this, new Observer<List<Download>>() {
|
||||
@Override
|
||||
public void onChanged(List<Download> downloads) {
|
||||
if (downloads == null || downloads.size() == 0) {
|
||||
return;
|
||||
}
|
||||
String id = downloads.get(downloads.size() - 1).request.id;
|
||||
|
||||
MediaItem curMediaItem = mediaControllerManager.getCurMediaItem();
|
||||
if (curMediaItem != null) {
|
||||
String mediaId = mediaControllerManager.getCurMediaItem().mediaId;
|
||||
if (mediaId.equals(id)) {
|
||||
vb.downloadPb.setVisibility(View.GONE);
|
||||
vb.imDownload.setVisibility(View.VISIBLE);
|
||||
vb.imDownload.setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
CommonUtils.LogMsg("-------onChanged id=" + id);
|
||||
if (mEnterType == MyValue.TYPE_ENTER_DOWNLOAD) {
|
||||
//下载进入播放,这里进行重置播放列表并播放
|
||||
mediaControllerManager.resetPlayList();
|
||||
for (Download data : downloads) {
|
||||
BoxDownloadSong boxDownloadSong = CommonUtils.downloadToBean(data);
|
||||
downloadSongList.add(boxDownloadSong);
|
||||
MediaItem mediaItem = CommonUtils.downloadToMediaItem(data);
|
||||
mediaControllerManager.addMusicPlayList(mediaItem);
|
||||
}
|
||||
mediaControllerManager.playPositionMusic(mDefaultPlayStartIndex);
|
||||
mediaControllerManager.play();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,169 +0,0 @@
|
||||
package com.hi.music.player.ui.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.MusicApplication;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.adapter.AdapterResult;
|
||||
import com.hi.music.player.api.HomeItemClickListener;
|
||||
import com.hi.music.player.databinding.ActivityResultListBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.response.ResponseResult;
|
||||
import com.hi.music.player.javabean.response.child.ResponseResultListChild;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMCategoryList;
|
||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMResultList;
|
||||
|
||||
public class ResultListActivity extends BaseActivity<ActivityResultListBinding> implements HomeItemClickListener {
|
||||
private VMResultList vm;
|
||||
private String key;
|
||||
|
||||
@Override
|
||||
protected ActivityResultListBinding getViewBinding() {
|
||||
return ActivityResultListBinding.inflate(getLayoutInflater());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreateInit() {
|
||||
vm = getActivityScopeViewModel(VMResultList.class);
|
||||
key = getIntent().getStringExtra(MyValue.KEY_SEARCH_RESULT_BROWSER_ID);
|
||||
vm.getList(key);
|
||||
|
||||
vm.data.observe(this, new Observer<ResponseResult>() {
|
||||
@Override
|
||||
public void onChanged(ResponseResult responseResult) {
|
||||
vb.pbLoading.setVisibility(View.GONE);
|
||||
if (responseResult == null) {
|
||||
vb.layoutError.linearRetry.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
vb.pbLoading.setVisibility(View.GONE);
|
||||
loadInfo(responseResult);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void loadInfo(ResponseResult result) {
|
||||
Glide.with(this)
|
||||
.asDrawable()
|
||||
.load(result.getMainCovert())
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(4))))
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
CommonUtils.LogMsg(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(vb.covert);
|
||||
vb.mainTitle.setText(result.getMainTitle());
|
||||
AdapterResult adapterResult = new AdapterResult(this);
|
||||
adapterResult.setHomeItemClickListener(this);
|
||||
adapterResult.setData(result.getList());
|
||||
vb.listRecycler.setAdapter(adapterResult);
|
||||
vb.listRecycler.setLayoutManager(new LinearLayoutManager(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitClick() {
|
||||
vb.imBack.setOnClickListener(this);
|
||||
vb.layoutError.tvRetry.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullScreen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean statusBarLight() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showPanel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.equals(vb.imBack)) {
|
||||
finish();
|
||||
} else if (v.equals(vb.layoutError.tvRetry)) {
|
||||
vm.getList(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickResultSong(ResponseResultListChild child, int index) {
|
||||
String videoId = child.getVideoId();
|
||||
String playListId = child.getPlayListId();
|
||||
String browserId = child.getBrowserId();
|
||||
String pageType = child.getPageType();
|
||||
String thumbnail = child.getThumbnail();
|
||||
String songName = child.getSongName();
|
||||
String subTitle = child.getSubTitle();
|
||||
|
||||
if (videoId != null && !videoId.isEmpty()) {
|
||||
ResponseSingle responseSingle = new ResponseSingle();
|
||||
responseSingle.setSongTitle(songName);
|
||||
responseSingle.setSingerHead(thumbnail);
|
||||
responseSingle.setVideoId(videoId);
|
||||
responseSingle.setPlaylistId(playListId);
|
||||
Intent intent = new Intent(this, PlayActivity.class);
|
||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER, responseSingle);
|
||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_CATEGORY_LIST_INDEX, index);
|
||||
CommonUtils.LogMsg("-------------index=" + index);
|
||||
startActivity(intent);
|
||||
} else {
|
||||
switch (pageType) {
|
||||
case "MUSIC_PAGE_TYPE_ALBUM":
|
||||
//专辑
|
||||
CommonUtils.LogMsg("------------专辑-index=" + index + "--subTitle=" + subTitle);
|
||||
case "MUSIC_PAGE_TYPE_PLAYLIST":
|
||||
//精选
|
||||
Intent intent1 = new Intent(this, CategoryListActivity.class);
|
||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_TYPE, pageType);
|
||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_SINGER_NAME, subTitle);
|
||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_BROWSER_ID, browserId);
|
||||
startActivity(intent1);
|
||||
break;
|
||||
case "MUSIC_PAGE_TYPE_ARTIST":
|
||||
//粉丝可能还喜欢
|
||||
Intent intent = new Intent(this, ResultListActivity.class);
|
||||
intent.putExtra(MyValue.KEY_SEARCH_RESULT_BROWSER_ID, browserId);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,168 +0,0 @@
|
||||
package com.hi.music.player.ui.fragmnt;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.RestrictionsManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.adapter.AdapterHome;
|
||||
import com.hi.music.player.api.HomeItemClickListener;
|
||||
import com.hi.music.player.api.OnHasUrlAction;
|
||||
import com.hi.music.player.databinding.FragmentHomeBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.response.ResponseHome;
|
||||
import com.hi.music.player.javabean.response.child.ResponseCategory;
|
||||
import com.hi.music.player.javabean.response.child.ResponseHomeChild;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
||||
import com.hi.music.player.network.RetrofitManager;
|
||||
import com.hi.music.player.ui.activity.CategoryListActivity;
|
||||
import com.hi.music.player.ui.activity.PlayActivity;
|
||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMHome;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
public class HomeFragment extends BaseFragment<FragmentHomeBinding> implements HomeItemClickListener {
|
||||
|
||||
|
||||
private VMHome vmHome;
|
||||
|
||||
|
||||
private int requestCount = 1;
|
||||
|
||||
private int totalPage = 3;
|
||||
|
||||
|
||||
private List<ResponseHomeChild> childList = new ArrayList<>();
|
||||
|
||||
|
||||
@Override
|
||||
protected FragmentHomeBinding getFragmentVb() {
|
||||
// 返回正确的 ViewBinding 实例
|
||||
return FragmentHomeBinding.inflate(getLayoutInflater());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
|
||||
// //标题导航栏颜色设置
|
||||
// Vb.toolbar.setTitleTextColor(getResources().getColor(R.color.white));
|
||||
AdapterHome adapterHome = new AdapterHome();
|
||||
adapterHome.setHomeItemClickListener(this);
|
||||
|
||||
|
||||
vmHome = getFragmentScopeViewModel(VMHome.class);
|
||||
adapterHome.addLoadingFooter();
|
||||
vmHome.getHome();
|
||||
Vb.tvRetry.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
adapterHome.addLoadingFooter();
|
||||
vmHome.getHome();
|
||||
}
|
||||
});
|
||||
|
||||
vmHome.data.observe(getViewLifecycleOwner(), new Observer<ResponseHome>() {
|
||||
@Override
|
||||
public void onChanged(ResponseHome responseHome) {
|
||||
if (responseHome == null) {
|
||||
adapterHome.removeLoadingFooter();
|
||||
requestCount--;
|
||||
if(requestCount == 0){
|
||||
Vb.layoutError.setVisibility(View.VISIBLE);
|
||||
Vb.recyclerSongOfTheDay.setVisibility(View.GONE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Vb.layoutError.setVisibility(View.GONE);
|
||||
Vb.recyclerSongOfTheDay.setVisibility(View.VISIBLE);
|
||||
|
||||
List<ResponseHomeChild> childList1 = responseHome.getChildList();
|
||||
if (childList1 == null) return;
|
||||
childList.addAll(childList1);
|
||||
adapterHome.removeLoadingFooter();
|
||||
adapterHome.addData(childList1);
|
||||
if (requestCount == 1) {
|
||||
adapterHome.addLoadingFooter();
|
||||
vmHome.getHomeMore();
|
||||
requestCount++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
Vb.recyclerSongOfTheDay.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
Vb.recyclerSongOfTheDay.setAdapter(adapterHome);
|
||||
Vb.recyclerSongOfTheDay.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
if (layoutManager != null && layoutManager.findLastVisibleItemPosition() == childList.size() - 1) {
|
||||
if (requestCount < totalPage && !adapterHome.isLoadingAdded()) {
|
||||
CommonUtils.LogMsg("------loadmore--");
|
||||
adapterHome.addLoadingFooter();
|
||||
vmHome.getHomeMore();
|
||||
requestCount++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClickItemSinger(ResponseSingle data) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
Intent intent = new Intent(activity, PlayActivity.class);
|
||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER, data);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickItemCategory(ResponseCategory data) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
String pageType = data.getPageType();
|
||||
String browseId = data.getBrowseId();
|
||||
String twoSubtitle = data.getTwoSubtitle();
|
||||
if (pageType.equals(MyValue.PAGE_TYPE_MV)||pageType.equals(MyValue.PAGE_TYPE_MV_LIST)) {
|
||||
Intent intent = new Intent(activity, PlayActivity.class);
|
||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_MV, data);
|
||||
intent.putExtra(MyValue.KEY_ENTER_SOURCE, MyValue.TYPE_ENTER_SOURCE_MV);
|
||||
startActivity(intent);
|
||||
}
|
||||
else {
|
||||
Intent intent = new Intent(activity, CategoryListActivity.class);
|
||||
intent.putExtra(MyValue.KEY_CATEGORY_LIST_TYPE, pageType);
|
||||
intent.putExtra(MyValue.KEY_CATEGORY_LIST_SINGER_NAME, twoSubtitle);
|
||||
intent.putExtra(MyValue.KEY_CATEGORY_LIST_BROWSER_ID, browseId);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,143 +0,0 @@
|
||||
package com.hi.music.player.ui.fragmnt;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.exoplayer.offline.Download;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.api.LikeSongListener;
|
||||
import com.hi.music.player.databinding.FragmentProfileBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.BoxDownloadSong;
|
||||
import com.hi.music.player.javabean.BoxLikeSong;
|
||||
import com.hi.music.player.media3.MyDownloadService;
|
||||
import com.hi.music.player.objectbox.ObjectBoxManager;
|
||||
import com.hi.music.player.ui.activity.LikeSongActivity;
|
||||
import com.hi.music.player.ui.activity.viewmodel.VMApplication;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.objectbox.reactive.DataSubscription;
|
||||
|
||||
|
||||
public class ProfileFragment extends BaseFragment<FragmentProfileBinding> implements View.OnClickListener {
|
||||
|
||||
|
||||
private DataSubscription dataSubscription;
|
||||
|
||||
private int likeSongCount = 0;
|
||||
private int downloadSongCount = 0;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected FragmentProfileBinding getFragmentVb() {
|
||||
return FragmentProfileBinding.inflate(getLayoutInflater());
|
||||
}
|
||||
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
@Override
|
||||
protected void initView() {
|
||||
|
||||
dataSubscription = ObjectBoxManager.setLikeDataListener(new LikeSongListener() {
|
||||
@Override
|
||||
public void onLikeSongChange(List<BoxLikeSong> data) {
|
||||
CommonUtils.LogMsg("------onLikeSongChange data=" + data.size());
|
||||
int size = data.size();
|
||||
likeSongCount = size;
|
||||
Vb.tvLikeSize.setText(String.format(getString(R.string.like_song), size));
|
||||
if (size == 0) {
|
||||
Vb.likeCovert.setVisibility(View.GONE);
|
||||
Vb.likeDefault.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
Vb.likeCovert.setVisibility(View.VISIBLE);
|
||||
Vb.likeDefault.setVisibility(View.GONE);
|
||||
BoxLikeSong boxLikeSong = data.get(size - 1);
|
||||
Glide.with(requireContext())
|
||||
.asDrawable()
|
||||
.load(boxLikeSong.getCovert())
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.error(R.mipmap.im_placeholder)
|
||||
.into(Vb.likeCovert);
|
||||
}
|
||||
}
|
||||
});
|
||||
MyDownloadService.updateDownloadUi(vmApplication);
|
||||
|
||||
vmApplication.downloadData.observe(getViewLifecycleOwner(), new Observer<List<Download>>() {
|
||||
@Override
|
||||
public void onChanged(List<Download> downloads) {
|
||||
int size = downloads.size();
|
||||
Vb.tvDownloadSize.setText(String.format(getString(R.string.download_song), size));
|
||||
downloadSongCount = size;
|
||||
if (size > 0) {
|
||||
Download download = downloads.get(downloads.size() - 1);
|
||||
BoxDownloadSong boxDownloadSong = CommonUtils.downloadToBean(download);
|
||||
|
||||
Vb.downloadCovert.setVisibility(View.VISIBLE);
|
||||
Vb.downloadDefault.setVisibility(View.GONE);
|
||||
Glide.with(requireContext())
|
||||
.asDrawable()
|
||||
.load(boxDownloadSong.getCovert())
|
||||
.placeholder(R.mipmap.im_placeholder)
|
||||
.error(R.mipmap.im_placeholder)
|
||||
.into(Vb.downloadCovert);
|
||||
} else {
|
||||
Vb.downloadCovert.setVisibility(View.GONE);
|
||||
Vb.downloadDefault.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vb.relayoutLike.setOnClickListener(this);
|
||||
Vb.relayoutDownload.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
CommonUtils.LogMsg("------ProfileFragment-onStart");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if (dataSubscription != null) {
|
||||
dataSubscription.cancel();
|
||||
}
|
||||
CommonUtils.LogMsg("------ProfileFragment-onDestroyView");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
CommonUtils.LogMsg("------ProfileFragment-onDestroy");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.equals(Vb.relayoutLike)) {
|
||||
if (likeSongCount > 0) {
|
||||
Intent intent = new Intent(requireActivity(), LikeSongActivity.class);
|
||||
intent.putExtra(MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE, MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE_LIKE);
|
||||
startActivity(intent);
|
||||
}
|
||||
} else if (v.equals(Vb.relayoutDownload)) {
|
||||
if (downloadSongCount > 0) {
|
||||
Intent intent = new Intent(requireActivity(), LikeSongActivity.class);
|
||||
intent.putExtra(MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE, MyValue.KEY_ENTER_LIKE_ACTIVITY_TYPE_DOWNLOAD);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,230 +0,0 @@
|
||||
package com.hi.music.player.ui.fragmnt;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.hi.music.player.adapter.AdapterSearch;
|
||||
import com.hi.music.player.adapter.AdapterSuggestion;
|
||||
import com.hi.music.player.api.HomeItemClickListener;
|
||||
import com.hi.music.player.databinding.FragmentSearchBinding;
|
||||
import com.hi.music.player.helper.CommonUtils;
|
||||
import com.hi.music.player.helper.MyValue;
|
||||
import com.hi.music.player.javabean.response.ResponseSearch;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSearchChild;
|
||||
import com.hi.music.player.javabean.response.child.ResponseSingle;
|
||||
import com.hi.music.player.ui.activity.CategoryListActivity;
|
||||
import com.hi.music.player.ui.activity.PlayActivity;
|
||||
import com.hi.music.player.ui.activity.ResultListActivity;
|
||||
import com.hi.music.player.ui.fragmnt.viewmodel.VMSearch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class SearchFragment extends BaseFragment<FragmentSearchBinding> implements HomeItemClickListener, View.OnClickListener {
|
||||
|
||||
|
||||
private VMSearch vmSearch;
|
||||
|
||||
@Override
|
||||
protected FragmentSearchBinding getFragmentVb() {
|
||||
return FragmentSearchBinding.inflate(getLayoutInflater());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
// Vb.etSearch.requestFocus();
|
||||
vmSearch = getFragmentScopeViewModel(VMSearch.class);
|
||||
|
||||
Vb.etSearch.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
String input = s.toString();
|
||||
if (!input.isEmpty()) {
|
||||
vmSearch.getSuggestion(input);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
Vb.etSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
String s = v.getText().toString();
|
||||
CommonUtils.LogMsg("------------v=" + s);
|
||||
startQuery(s);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
});
|
||||
initSuggestionRecycler();
|
||||
initResultRecycler();
|
||||
|
||||
}
|
||||
|
||||
private void initSuggestionRecycler() {
|
||||
AdapterSuggestion adapterSuggestion = new AdapterSuggestion();
|
||||
Vb.recyclerSuggestion.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
Vb.recyclerSuggestion.setAdapter(adapterSuggestion);
|
||||
adapterSuggestion.setHomeItemClickListener(this);
|
||||
Vb.imCancel.setOnClickListener(this);
|
||||
vmSearch.suggestion.observe(getViewLifecycleOwner(), new Observer<List<String>>() {
|
||||
@Override
|
||||
public void onChanged(List<String> strings) {
|
||||
if (strings != null) {
|
||||
adapterSuggestion.setData(strings);
|
||||
CommonUtils.LogMsg("------------更新=");
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void initResultRecycler(){
|
||||
AdapterSearch adapterSearch = new AdapterSearch();
|
||||
adapterSearch.setHomeItemClickListener(this);
|
||||
Vb.recyclerResult.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
Vb.recyclerResult.setAdapter(adapterSearch);
|
||||
vmSearch.result.observe(getViewLifecycleOwner(), new Observer<List<ResponseSearch>>() {
|
||||
@Override
|
||||
public void onChanged(List<ResponseSearch> responseSearches) {
|
||||
Vb.pbloading.setVisibility(View.GONE);
|
||||
if(responseSearches == null){
|
||||
Vb.recyclerResult.setVisibility(View.GONE);
|
||||
Vb.layoutError.setVisibility(View.VISIBLE);
|
||||
CommonUtils.LogMsg("------------更新结果 null");
|
||||
return;
|
||||
}
|
||||
Vb.recyclerResult.setVisibility(View.VISIBLE);
|
||||
Vb.layoutError.setVisibility(View.GONE);
|
||||
adapterSearch.setData(responseSearches);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void startQuery(String query){
|
||||
Vb.pbloading.setVisibility(View.VISIBLE);
|
||||
Vb.recyclerSuggestion.setVisibility(View.GONE);
|
||||
Vb.recyclerResult.setVisibility(View.VISIBLE);
|
||||
vmSearch.getSearchResult(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickItemSuggestion(boolean isSearch, String data) {
|
||||
if (isSearch) {
|
||||
startQuery(data);
|
||||
} else {
|
||||
Vb.etSearch.setText(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.equals(Vb.imCancel)) {
|
||||
Vb.etSearch.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//点击搜索结果的play按钮
|
||||
@Override
|
||||
public void onClickSearchResultBest(ResponseSearch responseSearch) {
|
||||
String beastBrowserId = responseSearch.getBeastBrowserId();
|
||||
String beastVideoId = responseSearch.getBeastVideoId();
|
||||
String beastSongTitle = responseSearch.getBeastSongTitle();
|
||||
String beastSongTCovert = responseSearch.getBeastSongTCovert();
|
||||
String pageType = responseSearch.getPageType();
|
||||
|
||||
if(beastVideoId!= null&&!beastVideoId.isEmpty()){
|
||||
CommonUtils.LogMsg("---------击搜索结果的play按钮--beastVideoId="+beastVideoId);
|
||||
|
||||
ResponseSingle responseSingle = new ResponseSingle();
|
||||
responseSingle.setSongTitle(beastSongTitle);
|
||||
responseSingle.setSingerHead(beastSongTCovert);
|
||||
responseSingle.setVideoId(beastVideoId);
|
||||
responseSingle.setPlaylistId("");
|
||||
Intent intent = new Intent(requireActivity(), PlayActivity.class);
|
||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER, responseSingle);
|
||||
startActivity(intent);
|
||||
}else if(beastBrowserId!= null&&!beastBrowserId.isEmpty()){
|
||||
CommonUtils.LogMsg("---------击搜索结果的play按钮--pageType="+pageType);
|
||||
switch (pageType){
|
||||
case "MUSIC_PAGE_TYPE_PLAYLIST":
|
||||
case "MUSIC_PAGE_TYPE_ALBUM":
|
||||
Intent intent1 = new Intent(requireActivity(), CategoryListActivity.class);
|
||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_TYPE, pageType);
|
||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_SINGER_NAME, responseSearch.getBeastSongDescribe());
|
||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_BROWSER_ID, beastBrowserId);
|
||||
startActivity(intent1);
|
||||
break;
|
||||
default:
|
||||
Intent intent = new Intent(requireActivity(), ResultListActivity.class);
|
||||
intent.putExtra(MyValue.KEY_SEARCH_RESULT_BROWSER_ID, beastBrowserId);
|
||||
startActivity(intent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//点击搜索结果普通项
|
||||
@Override
|
||||
public void onClickSearchResult(ResponseSearchChild responseSearchChild) {
|
||||
String browserId = responseSearchChild.getBrowserId();
|
||||
String songVideoId = responseSearchChild.getSongVideoId();
|
||||
String songCovert = responseSearchChild.getSongCovert();
|
||||
String songTitle = responseSearchChild.getSongTitle();
|
||||
String songDescribe = responseSearchChild.getSongDescribe();
|
||||
|
||||
if(browserId!= null&&!browserId.isEmpty()){
|
||||
String pageType = responseSearchChild.getPageType();
|
||||
CommonUtils.LogMsg("---------点击搜索结果--pageType="+pageType);
|
||||
switch (pageType){
|
||||
case "MUSIC_PAGE_TYPE_ARTIST":
|
||||
Intent intent = new Intent(requireActivity(), ResultListActivity.class);
|
||||
intent.putExtra(MyValue.KEY_SEARCH_RESULT_BROWSER_ID, browserId);
|
||||
startActivity(intent);
|
||||
break;
|
||||
default:
|
||||
Intent intent1 = new Intent(requireActivity(), CategoryListActivity.class);
|
||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_TYPE, pageType);
|
||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_SINGER_NAME, songDescribe);
|
||||
intent1.putExtra(MyValue.KEY_CATEGORY_LIST_BROWSER_ID, browserId);
|
||||
startActivity(intent1);
|
||||
break;
|
||||
}
|
||||
|
||||
}else {
|
||||
CommonUtils.LogMsg("---------点击搜索结果--VideoId="+songVideoId);
|
||||
|
||||
ResponseSingle responseSingle = new ResponseSingle();
|
||||
responseSingle.setSongTitle(songTitle);
|
||||
responseSingle.setSingerHead(songCovert);
|
||||
responseSingle.setVideoId(songVideoId);
|
||||
responseSingle.setPlaylistId("");
|
||||
Intent intent = new Intent(requireActivity(), PlayActivity.class);
|
||||
intent.putExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER, responseSingle);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.offline.music.playermp3;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
public class MusicApplication extends Application {
|
||||
|
||||
public static Context myApplication;
|
||||
|
||||
public static String visitorData;
|
||||
|
||||
|
||||
|
||||
|
||||
public static void setVisitorData(String visitorData) {
|
||||
MusicApplication.visitorData = visitorData;
|
||||
}
|
||||
|
||||
public static String getVisitorData() {
|
||||
return visitorData;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
myApplication = this;
|
||||
// Sp.init(this);
|
||||
// RemoteConfigJava.getInstance().init(this);
|
||||
// ObjectBoxManager.init(this);
|
||||
// MyMediaControllerManager.getInstance().init(new MediaControllerStatusListener() {
|
||||
// @Override
|
||||
// public void onMediaControllerComplete(boolean isOk) {
|
||||
// CommonUtils.LogMsg("=-----mediaController+" + isOk);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,12 +1,12 @@
|
||||
package com.hi.music.player.adapter;
|
||||
package com.offline.music.playermp3.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.A_HomeFragment;
|
||||
import com.hi.music.player.ui.fragmnt.A_ImportFragment;
|
||||
import com.offline.music.playermp3.ui.fragmnt.A_HomeFragment;
|
||||
import com.offline.music.playermp3.ui.fragmnt.A_ImportFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.hi.music.player.adapter;
|
||||
package com.offline.music.playermp3.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -12,23 +12,24 @@ import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.javabean.A_data.AudioItem;
|
||||
import com.hi.music.player.ui.activity.A_PlayActivity;
|
||||
import com.offline.music.playermp3.R;
|
||||
import com.offline.music.playermp3.javabean.A_data.AudioItem;
|
||||
import com.offline.music.playermp3.ui.activity.A_PlayActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class A_ImportFragmentAdapter extends RecyclerView.Adapter<A_ImportFragmentAdapter.ViewHolder> {
|
||||
|
||||
private Context context;
|
||||
private List<AudioItem> audioFiles = new ArrayList<>();
|
||||
private AudioItem audioItem;
|
||||
private OnOptionClickListener onOptionClickListener;;
|
||||
private OnOptionClickListener onOptionClickListener;
|
||||
private String newName;
|
||||
|
||||
public A_ImportFragmentAdapter(Context context) {
|
||||
public A_ImportFragmentAdapter(Context context, String newName) {
|
||||
this.context = context;
|
||||
this.newName = newName;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -39,21 +40,31 @@ public class A_ImportFragmentAdapter extends RecyclerView.Adapter<A_ImportFragme
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
audioItem = audioFiles.get(position);
|
||||
AudioItem audioItem1 = audioFiles.get(position);
|
||||
|
||||
holder.title.setText(audioItem.getName());
|
||||
holder.time.setText(audioItem.getDuration());
|
||||
Log.d("Adapter", "onBindViewHolder: " + audioItem.getDuration());
|
||||
holder.title.setText(audioItem1.getName());
|
||||
holder.time.setText(audioItem1.getDuration());
|
||||
Log.d("Adapter", "onBindViewHolder: " + audioItem1.getDuration());
|
||||
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(context, A_PlayActivity.class);
|
||||
intent.putExtra("Path", audioItem);
|
||||
intent.putExtra("Path", audioItem1);
|
||||
intent.putExtra("newName",newName);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
});holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(context, A_PlayActivity.class);
|
||||
intent.putExtra("Path", audioItem1);
|
||||
intent.putExtra("newName",newName);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
holder.bind(audioItem1); // 通过 bind 方法将 audioItem1 传递到 ViewHolder
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -66,6 +77,11 @@ public class A_ImportFragmentAdapter extends RecyclerView.Adapter<A_ImportFragme
|
||||
notifyDataSetChanged(); // Update UI when the data changes
|
||||
}
|
||||
|
||||
// 假设你的 adapter 类中有这个方法来返回某个位置的 AudioItem 对象
|
||||
public AudioItem getAudioFile(int position) {
|
||||
return audioFiles.get(position); // 返回位置上的 AudioItem 对象
|
||||
}
|
||||
|
||||
public void updateTitle(int position, String newTitle) {
|
||||
if (position >= 0 && position < audioFiles.size()) {
|
||||
audioFiles.get(position).setName(newTitle); // 假设 AudioItem 有一个 setName 方法
|
||||
@ -86,12 +102,12 @@ public class A_ImportFragmentAdapter extends RecyclerView.Adapter<A_ImportFragme
|
||||
void onOptionClick(int position, String filePath, View anchorView);
|
||||
}
|
||||
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
ImageView option;
|
||||
TextView title;
|
||||
TextView time;
|
||||
private AudioItem audioItem; // 定义一个 audioItem 字段
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
@ -101,14 +117,16 @@ public class A_ImportFragmentAdapter extends RecyclerView.Adapter<A_ImportFragme
|
||||
time = itemView.findViewById(R.id.time);
|
||||
|
||||
option.setOnClickListener(v -> {
|
||||
int position = getBindingAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION && onOptionClickListener != null) {
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION && onOptionClickListener != null && audioItem != null) {
|
||||
onOptionClickListener.onOptionClick(position, audioItem.getFile(), option);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 添加 bind 方法,将 audioItem 传递给 ViewHolder
|
||||
public void bind(AudioItem audioItem) {
|
||||
this.audioItem = audioItem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.hi.music.player.adapter;
|
||||
package com.offline.music.playermp3.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -14,10 +14,10 @@ import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.hi.music.player.R;
|
||||
import com.hi.music.player.helper.AudioItemDiffCallback;
|
||||
import com.hi.music.player.javabean.A_data.AudioItem;
|
||||
import com.hi.music.player.ui.activity.A_PlayActivity;
|
||||
import com.offline.music.playermp3.R;
|
||||
import com.offline.music.playermp3.helper.AudioItemDiffCallback;
|
||||
import com.offline.music.playermp3.javabean.A_data.AudioItem;
|
||||
import com.offline.music.playermp3.ui.activity.A_PlayActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user