首页数据

This commit is contained in:
litingting 2024-09-20 10:10:04 +08:00
parent dcc182827c
commit 1cb103d464
33 changed files with 1162 additions and 292 deletions

View File

@ -52,4 +52,8 @@ dependencies {
implementation("io.reactivex.rxjava2:rxjava:2.2.21") implementation("io.reactivex.rxjava2:rxjava:2.2.21")
implementation("io.reactivex.rxjava2:rxandroid:2.1.1") implementation("io.reactivex.rxjava2:rxandroid:2.1.1")
implementation ("com.squareup.okhttp3:logging-interceptor:4.11.0") implementation ("com.squareup.okhttp3:logging-interceptor:4.11.0")
implementation ("androidx.paging:paging-runtime-ktx:3.3.2")
implementation("com.github.bumptech.glide:glide:4.16.0")
} }

View File

@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application <application
android:name=".MusicApplication"
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
@ -14,6 +15,9 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.MusicApp" android:theme="@style/Theme.MusicApp"
tools:targetApi="31"> tools:targetApi="31">
<activity
android:name=".ui.activity.PlayActivity"
android:exported="false" />
<activity <activity
android:name=".ui.activity.MainActivity" android:name=".ui.activity.MainActivity"
android:exported="false" /> android:exported="false" />

View File

@ -1,13 +1,23 @@
package com.hi.music.player; package com.hi.music.player;
import android.app.Application; import android.app.Application;
import android.content.Context;
public class MusicApplication extends Application { public class MusicApplication extends Application {
private final static MusicApplication sInstance = new MusicApplication(); // private final static MusicApplication sInstance = new MusicApplication();
public static MusicApplication getInstance() { public static Context myApplication;
return sInstance; // public static MusicApplication getInstance() {
// return sInstance;
// }
@Override
public void onCreate() {
super.onCreate();
myApplication = this;
} }
} }

View File

@ -0,0 +1,72 @@
package com.hi.music.player.adapter;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.RoundedCorner;
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.databinding.ItemHomeBinding;
import com.hi.music.player.databinding.ItemSingerBinding;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.response.ResponseCategory;
import com.hi.music.player.javabean.response.ResponseSingle;
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);
Glide.with(MusicApplication.myApplication)
.asDrawable()
.apply(RequestOptions.bitmapTransform(new RoundedCorners(CommonUtils.dpToPx(13))))
.load(responseCategory.getCovert())
.placeholder(R.mipmap.ic_launcher)
.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(responseCategory.getTwoTitle());
vb.tvSubtitle.setText(responseCategory.getTwoSubtitle());
}
}
}

View File

@ -0,0 +1,79 @@
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.api.ClickSingerListener;
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.ResponseCategory;
import com.hi.music.player.javabean.response.ResponseHomeChild;
import com.hi.music.player.javabean.response.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();
if (singleList != null && singleList.size() > 0) {
vb.recyclerSinger.setVisibility(View.VISIBLE);
CommonUtils.LogMsg("-----------singleList-=" + singleList.size());
AdapterSinger adapterSinger = new AdapterSinger();
adapterSinger.setSingleClickSingerListener(singleClickSingerListener);
adapterSinger.addData(singleList);
vb.recyclerSinger.setLayoutManager(new GridLayoutManager(MusicApplication.myApplication, 4, RecyclerView.HORIZONTAL, false));
vb.recyclerSinger.setAdapter(adapterSinger);
} else {
vb.recyclerSinger.setVisibility(View.GONE);
}
List<ResponseCategory> categoryList = responseHomeChild.getCategoryList();
if (categoryList != null && categoryList.size() > 0) {
vb.recyclerCategory.setVisibility(View.VISIBLE);
CommonUtils.LogMsg("-----------categoryList-=" + categoryList.size());
AdapterCategory adapterCategory = new AdapterCategory();
adapterCategory.addData(categoryList);
vb.recyclerCategory.setLayoutManager(new LinearLayoutManager(MusicApplication.myApplication, RecyclerView.HORIZONTAL, false));
vb.recyclerCategory.setAdapter(adapterCategory);
} else {
vb.recyclerCategory.setVisibility(View.GONE);
}
} else {
VHolder<ItemFooterLoadingBinding> footerHolder = (VHolder<ItemFooterLoadingBinding>) holder;
FrameLayout root = footerHolder.getVb().getRoot();
if (isLoadingAdded) {
root.setVisibility(View.VISIBLE);
} else {
root.setVisibility(View.GONE);
}
}
}
}

View File

@ -0,0 +1,81 @@
package com.hi.music.player.adapter;
import android.content.Intent;
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.databinding.ItemHomeBinding;
import com.hi.music.player.databinding.ItemSingerBinding;
import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.response.ResponseHomeChild;
import com.hi.music.player.javabean.response.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.ic_launcher)
.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 (singleClickSingerListener != null) {
singleClickSingerListener.onClickSingerItem(responseSingle);
}
}
});
}
}
}

View File

@ -0,0 +1,106 @@
package com.hi.music.player.adapter;
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.ClickSingerListener;
import com.hi.music.player.databinding.ItemFooterLoadingBinding;
import com.hi.music.player.javabean.response.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 static final int TYPE_ITEM = 0;
protected static final int TYPE_FOOTER = 1;
protected boolean isLoadingAdded = false;
protected ClickSingerListener<ResponseSingle> singleClickSingerListener;
public void setSingleClickSingerListener(ClickSingerListener<ResponseSingle> singleClickSingerListener) {
this.singleClickSingerListener = singleClickSingerListener;
}
public void addData(List<K> data) {
this.data.addAll(data);
notifyDataSetChanged();
}
public void addLoadingFooter() {
isLoadingAdded = true;
// notifyItemInserted(data.size());
}
// Hide loading footer
public void removeLoadingFooter() {
isLoadingAdded = false;
int position = data.size();
if (position > 0)
notifyItemRemoved(position);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == TYPE_ITEM) {
T viewBinding = getViewBinding(parent);
return new VHolder<>(viewBinding);
} else {
// Inflate footer layout
ItemFooterLoadingBinding inflate = ItemFooterLoadingBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new VHolder<>(inflate);
}
}
protected abstract T getViewBinding(ViewGroup parent);
@Override
public int getItemViewType(int position) {
return (position == data.size() && isLoadingAdded) ? TYPE_FOOTER : TYPE_ITEM;
}
@Override
public int getItemCount() {
return data.size() + (isLoadingAdded ? 1 : 0);
}
public static class VHolder<V extends ViewBinding> extends RecyclerView.ViewHolder {
private V vb;
public V getVb() {
return vb;
}
public VHolder(@NonNull V itemView) {
super(itemView.getRoot());
vb = itemView;
}
}
public static class FooterHolder extends RecyclerView.ViewHolder {
private ItemFooterLoadingBinding vb;
public ItemFooterLoadingBinding getVb() {
return vb;
}
public FooterHolder(@NonNull ItemFooterLoadingBinding itemView) {
super(itemView.getRoot());
vb = itemView;
}
}
}

View File

@ -0,0 +1,6 @@
package com.hi.music.player.api;
public interface ClickSingerListener<T> {
void onClickSingerItem(T data) ;
}

View File

@ -1,7 +1,11 @@
package com.hi.music.player.helper; package com.hi.music.player.helper;
import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import com.hi.music.player.MusicApplication;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -27,4 +31,31 @@ public class CommonUtils {
return null; 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;
}
} }

View File

@ -0,0 +1,7 @@
package com.hi.music.player.helper;
public class MyValue {
//-----------------------------PlayActivity
public static String KEY_PLAY_ACTIVITY_SINGER = "click_singer";
//-----------------------------PlayActivity
}

View File

@ -1,7 +1,8 @@
package com.hi.music.player.javabean.requestbody; package com.hi.music.player.javabean.requestbody;
import com.hi.music.player.javabean.requestbody.child.ContextBody;
import java.io.Serializable; import java.io.Serializable;
import java.util.Locale;
/** /**
@ -11,43 +12,17 @@ public class BodyHome implements Serializable {
private String browseId = "FEmusic_home"; private String browseId = "FEmusic_home";
private Context context = new Context(); private ContextBody context = new ContextBody();
public Context getContext() { public ContextBody getContext() {
return context; return context;
} }
public void setContext(Context context) { public void setContext(ContextBody context) {
this.context = context; this.context = context;
} }
public class Context implements Serializable{
private Client client = new Client();
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
}
public class Client implements Serializable{
private String clientName = "WEB_REMIX";
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;
}
}
} }

View File

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

View File

@ -0,0 +1,36 @@
package com.hi.music.player.javabean.requestbody.child;
import java.io.Serializable;
import java.util.Locale;
public class ContextBody {
private Client client = new Client();
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public class Client implements Serializable {
private String clientName = "WEB_REMIX";
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;
}
}
}

View File

@ -13,7 +13,6 @@ public class ResponseHome {
//用于更多数据请求的ctoken //用于更多数据请求的ctoken
private String continuation; private String continuation;
@Nullable @Nullable
//用于更多数据请求的visitorData(只有第一个接口会返回该值) //用于更多数据请求的visitorData(只有第一个接口会返回该值)
private String visitorData; private String visitorData;

View File

@ -1,6 +1,8 @@
package com.hi.music.player.javabean.response; package com.hi.music.player.javabean.response;
public class ResponseSingle { import java.io.Serializable;
public class ResponseSingle implements Serializable {
//歌手头像 //歌手头像
private String SingerHead; private String SingerHead;
@ -13,6 +15,14 @@ public class ResponseSingle {
private String Description; private String Description;
private String videoId;
private String playlistId;
private String params;
private String musicVideoType;
public String getSingerHead() { public String getSingerHead() {
return SingerHead; return SingerHead;
} }
@ -44,4 +54,38 @@ public class ResponseSingle {
public void setDescription(String description) { public void setDescription(String description) {
Description = description; Description = description;
} }
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public void setPlaylistId(String playlistId) {
this.playlistId = playlistId;
}
public void setParams(String params) {
this.params = params;
}
public void setMusicVideoType(String musicVideoType) {
this.musicVideoType = musicVideoType;
}
public String getVideoId() {
return videoId;
}
public String getPlaylistId() {
return playlistId;
}
public String getParams() {
return params;
}
public String getMusicVideoType() {
return musicVideoType;
}
} }

View File

@ -35,14 +35,13 @@ public class JsonHelper {
.getJSONObject("responseContext"); .getJSONObject("responseContext");
JSONArray serviceTrackingParams = responseContext.getJSONArray("serviceTrackingParams"); JSONArray serviceTrackingParams = responseContext.getJSONArray("serviceTrackingParams");
String visitorData = responseContext.getString("visitorData"); String visitorData = responseContext.getString("visitorData");
CommonUtils.LogMsg("----------visitorData=" + visitorData); CommonUtils.LogMsg("---------参数-visitorData=" + visitorData);
responseHome.setBackgroundUrl(bgUrl); responseHome.setBackgroundUrl(bgUrl);
responseHome.setVisitorData(visitorData); responseHome.setVisitorData(visitorData);
getCommonHome(sectionListRenderer, responseHome); getCommonHome(sectionListRenderer, responseHome);
} catch (JSONException exception) { } catch (JSONException exception) {
CommonUtils.LogMsg("----------exception="); CommonUtils.LogMsg("----------exception=");
exception.printStackTrace(); exception.printStackTrace();
@ -89,8 +88,8 @@ public class JsonHelper {
String clickTrackingParams = nextContinuationData.getString("clickTrackingParams"); String clickTrackingParams = nextContinuationData.getString("clickTrackingParams");
String continuation = nextContinuationData.getString("continuation"); String continuation = nextContinuationData.getString("continuation");
CommonUtils.LogMsg("----------clickTrackingParams=" + clickTrackingParams); CommonUtils.LogMsg("---------参数---clickTrackingParams=" + clickTrackingParams);
CommonUtils.LogMsg("----------continuation=" + continuation); CommonUtils.LogMsg("---------参数--continuation=" + continuation);
responseHome.setClickTrackingParams(clickTrackingParams); responseHome.setClickTrackingParams(clickTrackingParams);
responseHome.setContinuation(continuation); responseHome.setContinuation(continuation);
@ -136,11 +135,31 @@ public class JsonHelper {
String SingerName = ""; String SingerName = "";
String Description = ""; String Description = "";
for (int g = 0; g < flexColumns.length(); g++) { for (int g = 0; g < flexColumns.length(); g++) {
String text = getJsonText(musicResponsiveListItemRenderer.getJSONArray("flexColumns") JSONObject jsonObject = musicResponsiveListItemRenderer.getJSONArray("flexColumns")
.getJSONObject(g) .getJSONObject(g)
.getJSONObject("musicResponsiveListItemFlexColumnRenderer") .getJSONObject("musicResponsiveListItemFlexColumnRenderer")
.getJSONObject("text")); .getJSONObject("text");
if (g == 0) SongTitle = text; String text = getJsonText(jsonObject);
if (g == 0) {
SongTitle = text;
JSONObject watchEndpoint = jsonObject.getJSONArray("runs")
.getJSONObject(0)
.getJSONObject("navigationEndpoint")
.getJSONObject("watchEndpoint");
String videoId = watchEndpoint.getString("videoId");
String playlistId = watchEndpoint.getString("playlistId");
String params = watchEndpoint.getString("params");
String musicVideoType = watchEndpoint.getJSONObject("watchEndpointMusicSupportedConfigs")
.getJSONObject("watchEndpointMusicConfig")
.getString("musicVideoType");
responseSingle.setVideoId(videoId);
responseSingle.setPlaylistId(playlistId);
responseSingle.setParams(params);
responseSingle.setMusicVideoType(musicVideoType);
}
if (g == 1) SingerName = text; if (g == 1) SingerName = text;
if (g == 2) Description = text; if (g == 2) Description = text;
} }
@ -158,13 +177,20 @@ public class JsonHelper {
String covert = getJsonUrl(musicTwoRowItemRenderer String covert = getJsonUrl(musicTwoRowItemRenderer
.getJSONObject("thumbnailRenderer")); .getJSONObject("thumbnailRenderer"));
String twoTitle = getJsonText(musicTwoRowItemRenderer.getJSONObject("title")); JSONObject title1 = musicTwoRowItemRenderer.getJSONObject("title");
String twoSubtitle = getJsonText(musicTwoRowItemRenderer.getJSONObject("subtitle")); String twoTitle = getJsonText(title1);
String twoSubtitle = getJsonTextNew(musicTwoRowItemRenderer.getJSONObject("subtitle"));
// String pageType = title1.getJSONObject("navigationEndpoint")
// .getJSONObject("browseEndpoint")
// .getJSONObject("browseEndpointContextSupportedConfigs")
// .getJSONObject("browseEndpointContextMusicConfig")
// .getString("pageType");
responseCategory.setCovert(covert); responseCategory.setCovert(covert);
responseCategory.setTwoTitle(twoTitle); responseCategory.setTwoTitle(twoTitle);
responseCategory.setTwoSubtitle(twoSubtitle); responseCategory.setTwoSubtitle(twoSubtitle);
categoryList.add(responseCategory); categoryList.add(responseCategory);
CommonUtils.LogMsg(" ----------2222222222----twoTitle=" + twoTitle + "-twoSubtitle=" + twoSubtitle + "---封面=" + covert); CommonUtils.LogMsg(" ----------2222222222----twoTitle=" + twoTitle + "-twoSubtitle=" + twoSubtitle );
} }
} }
@ -207,4 +233,20 @@ public class JsonHelper {
return ""; return "";
} }
} }
private static String getJsonTextNew(JSONObject jsonObject) {
StringBuilder text= new StringBuilder();
try {
JSONArray runs = jsonObject.getJSONArray("runs");
for (int i =0;i<runs.length();i++){
String text1 = runs.getJSONObject(i).getString("text");
text.append(text1);
}
} catch (JSONException exception) {
}
return text.toString();
}
} }

View File

@ -4,20 +4,23 @@ import io.reactivex.Observable;
import okhttp3.RequestBody; import okhttp3.RequestBody;
import okhttp3.ResponseBody; import okhttp3.ResponseBody;
import retrofit2.http.Body; import retrofit2.http.Body;
import retrofit2.http.Header;
import retrofit2.http.Headers; import retrofit2.http.Headers;
import retrofit2.http.POST; import retrofit2.http.POST;
import retrofit2.http.Query; import retrofit2.http.Query;
public interface MusicApi { public interface MusicApi {
//首页数据
@POST("youtubei/v1/browse?prettyPrint=false") @POST("youtubei/v1/browse?prettyPrint=false")
@Headers("X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8") @Headers("X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8")
Observable<ResponseBody> getHomeData(@Body RequestBody requestBody); Observable<ResponseBody> getHomeData(@Body RequestBody requestBody);
// "youtubei/v1/browse?ctoken=${baseHomePage.cToken}&continuation=${baseHomePage.continuation}&type=next&itct=${baseHomePage.itct}&prettyPrint=false"
//首页更多数据
@POST("youtubei/v1/browse") @POST("youtubei/v1/browse")
@Headers("X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8") @Headers("X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8")
Observable<ResponseBody> getHomeMoreData(@Query("ctoken") String token, Observable<ResponseBody> getHomeMoreData(@Query("ctoken") String token,
@ -27,8 +30,11 @@ public interface MusicApi {
@Query("prettyPrint") boolean prettyPrint,@Body RequestBody requestBody); @Query("prettyPrint") boolean prettyPrint,@Body RequestBody requestBody);
// @POST("youtubei/v1/browse")
// @Headers("X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8") // X-Goog-FieldMask: contents.singleColumnMusicWatchNextResultsRenderer.tabbedRenderer.watchNextTabbedResultsRenderer.tabs.tabRenderer.content.musicQueueRenderer.content.playlistPanelRenderer(continuations,contents(automixPreviewVideoRenderer,playlistPanelVideoRenderer(title,navigationEndpoint,longBylineText,shortBylineText,thumbnail,lengthText)))
// @FormUrlEncoded @POST("youtubei/v1/next?prettyPrint=false")
// Observable<ResponseBody> getHomeMoreData(@FieldMap Map<String,String> map); @Headers("X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8")
Observable<ResponseBody> getMusicPlayPage(@Header("X-Goog-FieldMask") String customHeader, @Body RequestBody requestBody);
} }

View File

@ -4,6 +4,7 @@ import com.google.gson.Gson;
import com.hi.music.player.api.RequestListener; import com.hi.music.player.api.RequestListener;
import com.hi.music.player.helper.CommonUtils; import com.hi.music.player.helper.CommonUtils;
import com.hi.music.player.javabean.requestbody.BodyHome; import com.hi.music.player.javabean.requestbody.BodyHome;
import com.hi.music.player.javabean.requestbody.BodyPlay;
import com.hi.music.player.javabean.response.ResponseHome; import com.hi.music.player.javabean.response.ResponseHome;
import org.json.JSONObject; import org.json.JSONObject;
@ -31,6 +32,9 @@ public class RetrofitManager {
public MediaType JSON = MediaType.get("application/json; charset=utf-8"); public MediaType JSON = MediaType.get("application/json; charset=utf-8");
private MusicApi musicApi; 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() { private RetrofitManager() {
musicApi = getRetrofit().create(MusicApi.class); musicApi = getRetrofit().create(MusicApi.class);
@ -73,7 +77,7 @@ public class RetrofitManager {
} }
public void getHomeData() { public void getHomeData(RequestListener<ResponseBody> requestListener) {
BodyHome bodyHome = new BodyHome(); BodyHome bodyHome = new BodyHome();
Gson gson = new Gson(); Gson gson = new Gson();
String s = gson.toJson(bodyHome); String s = gson.toJson(bodyHome);
@ -82,26 +86,10 @@ public class RetrofitManager {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(new ObserverWrapper<ResponseBody>(new RequestListener<ResponseBody>() { .subscribe(new ObserverWrapper<ResponseBody>(requestListener));
@Override
public void onFail(String errorMsg) {
}
@Override
public void onSuccess(ResponseBody data) {
JSONObject jsonObject = CommonUtils.toJsonObject(data);
if (jsonObject != null) {
ResponseHome responseHome = JsonHelper.ResolveHomeJson(jsonObject);
CommonUtils.LogMsg("");
}
}
}));
} }
public void getHomeMoreData(String continuation,String itct,String visitorData) { public void getHomeMoreData(String continuation,String itct,String visitorData,RequestListener<ResponseBody> requestListener) {
BodyHome bodyHome = new BodyHome(); BodyHome bodyHome = new BodyHome();
bodyHome.getContext().getClient().setVisitorData(visitorData); bodyHome.getContext().getClient().setVisitorData(visitorData);
Gson gson = new Gson(); Gson gson = new Gson();
@ -118,22 +106,23 @@ public class RetrofitManager {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(new ObserverWrapper<ResponseBody>(new RequestListener<ResponseBody>() { .subscribe(new ObserverWrapper<ResponseBody>(requestListener));
}
@Override
public void onFail(String errorMsg) {
} public void getNext(String params,String playlistId,String videoId,String musicVideoType,RequestListener<ResponseBody> requestListener) {
BodyPlay bodyPlay = new BodyPlay();
@Override bodyPlay.setParams(params);
public void onSuccess(ResponseBody data) { bodyPlay.setPlaylistId(playlistId);
JSONObject jsonObject = CommonUtils.toJsonObject(data); bodyPlay.setVideoId(videoId);
if (jsonObject != null) { bodyPlay.getWatchEndpointMusicSupportedConfigs().setMusicVideoType(musicVideoType);
ResponseHome responseHome = JsonHelper.ResolveHomeMoreJson(jsonObject); Gson gson = new Gson();
CommonUtils.LogMsg(""); 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));
} }
} }

View File

@ -5,10 +5,12 @@ import android.view.View;
import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator; import com.google.android.material.tabs.TabLayoutMediator;
import com.hi.music.player.MusicApplication;
import com.hi.music.player.R; import com.hi.music.player.R;
import com.hi.music.player.adapter.HomeViewPagerAdapter; import com.hi.music.player.adapter.HomeViewPagerAdapter;
import com.hi.music.player.databinding.ActivityHomeBinding; import com.hi.music.player.databinding.ActivityHomeBinding;
import com.hi.music.player.databinding.HomeTabCustomBinding; import com.hi.music.player.databinding.HomeTabCustomBinding;
import com.hi.music.player.helper.CommonUtils;
public class HomeActivity extends BaseActivity<ActivityHomeBinding> { public class HomeActivity extends BaseActivity<ActivityHomeBinding> {
@ -47,14 +49,13 @@ public class HomeActivity extends BaseActivity<ActivityHomeBinding> {
public void initView() { public void initView() {
int statusBarHeight = getStatusBarHeight(); int statusBarHeight = CommonUtils.getStatusBarHeight(MusicApplication.myApplication);
int navigationBarHeight = getNavigationBarHeight();
View root = vb.getRoot(); View root = vb.getRoot();
root.setPadding(0,statusBarHeight,0,0); root.setPadding(0,statusBarHeight,0,0);
HomeViewPagerAdapter adapter = new HomeViewPagerAdapter(this); HomeViewPagerAdapter adapter = new HomeViewPagerAdapter(this);
vb.homeViewPager.setAdapter(adapter); vb.homeViewPager.setAdapter(adapter);
vb.homeViewPager.setUserInputEnabled(false);
// 设置TabLayout的图标 // 设置TabLayout的图标
new TabLayoutMediator(vb.homeTabLayout, vb.homeViewPager, (tab, position) -> { new TabLayoutMediator(vb.homeTabLayout, vb.homeViewPager, (tab, position) -> {
@ -95,24 +96,8 @@ public class HomeActivity extends BaseActivity<ActivityHomeBinding> {
tabBinding.homeIcon.setImageResource(isSelected ? selectedIcons[position] : defaultIcons[position]); tabBinding.homeIcon.setImageResource(isSelected ? selectedIcons[position] : defaultIcons[position]);
} }
// 获取状态栏高度的方法
public int getStatusBarHeight() {
int statusBarHeight = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
return statusBarHeight;
}
// 获取导航栏高度的方法
public int getNavigationBarHeight() {
int navigationBarHeight = 0;
int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
navigationBarHeight = getResources().getDimensionPixelSize(resourceId);
}
return navigationBarHeight;
}
} }

View File

@ -20,7 +20,7 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
RetrofitManager.getInstance().getHomeData();
} }
}); });
@ -30,7 +30,7 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> {
String continuation = "4qmFsgKrAhIMRkVtdXNpY19ob21lGpoCQ0FONnpBRkhVSGswZFMxUVIzazBaMFJYYjFWQ1EyOUpRa05wVWpWa1JqbDNXVmRrYkZnelRuVlpXRUo2WVVjNU1GZ3lNVEZqTW14cVdETkNhRm95Vm1aamJWWnVZVmM1ZFZsWGQxTklNV3Q1V2tSUmRHRldUa2RoTUZKS1ZteEdSR0ZXVG5GbFIzaERWVlZvTVZORlVYUlVXR3hLVVcxellVOVZNVEZqTW14cVVrZHNlbGt5T1RKYVdFbzFWVWRHYmxwV1RteGpibHB3V1RKVmRGSXlWakJUUnpsMFdsWkNhRm95VlVGQlVVSTJZVU14UkZSblFVSldWazFCUVZaV1ZFRkJSVUpCWDNGamVEY3dTa0ZuWjBVJTNE"; String continuation = "4qmFsgKrAhIMRkVtdXNpY19ob21lGpoCQ0FONnpBRkhVSGswZFMxUVIzazBaMFJYYjFWQ1EyOUpRa05wVWpWa1JqbDNXVmRrYkZnelRuVlpXRUo2WVVjNU1GZ3lNVEZqTW14cVdETkNhRm95Vm1aamJWWnVZVmM1ZFZsWGQxTklNV3Q1V2tSUmRHRldUa2RoTUZKS1ZteEdSR0ZXVG5GbFIzaERWVlZvTVZORlVYUlVXR3hLVVcxellVOVZNVEZqTW14cVVrZHNlbGt5T1RKYVdFbzFWVWRHYmxwV1RteGpibHB3V1RKVmRGSXlWakJUUnpsMFdsWkNhRm95VlVGQlVVSTJZVU14UkZSblFVSldWazFCUVZaV1ZFRkJSVUpCWDNGamVEY3dTa0ZuWjBVJTNE";
String clickTrackingParams = "CBAQybcCIhMIw4eu48bLiAMVvoDkBh2lGTJl"; String clickTrackingParams = "CBAQybcCIhMIw4eu48bLiAMVvoDkBh2lGTJl";
String visitorData = "CgtFQThPOThGYzV0OCjDkqm3BjIKCgJVUxIEGgAgGg%3D%3D"; String visitorData = "CgtFQThPOThGYzV0OCjDkqm3BjIKCgJVUxIEGgAgGg%3D%3D";
RetrofitManager.getInstance().getHomeMoreData(continuation,clickTrackingParams,visitorData); // RetrofitManager.getInstance().getHomeMoreData(continuation,clickTrackingParams,visitorData);
} }
}); });

View File

@ -0,0 +1,47 @@
package com.hi.music.player.ui.activity;
import android.content.Intent;
import android.view.View;
import com.hi.music.player.databinding.ActivityPlayBinding;
import com.hi.music.player.helper.MyValue;
import com.hi.music.player.javabean.response.ResponseSingle;
import com.hi.music.player.ui.activity.viewmodel.VMPlay;
public class PlayActivity extends BaseActivity<ActivityPlayBinding> {
private ResponseSingle responseSingle;
private VMPlay vmPlay;
@Override
protected ActivityPlayBinding getViewBinding() {
return ActivityPlayBinding.inflate(getLayoutInflater());
}
@Override
protected void onCreateInit() {
Intent intent = getIntent();
responseSingle = (ResponseSingle) intent.getSerializableExtra(MyValue.KEY_PLAY_ACTIVITY_SINGER);
vmPlay = getActivityScopeViewModel(VMPlay.class);
vb.btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
vmPlay.getPlay(responseSingle);
}
});
}
@Override
public boolean isFullScreen() {
return false;
}
@Override
public boolean statusBarLight() {
return false;
}
}

View File

@ -0,0 +1,57 @@
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.response.ResponseHome;
import com.hi.music.player.javabean.response.ResponseSingle;
import com.hi.music.player.network.JsonHelper;
import com.hi.music.player.network.RetrofitManager;
import org.json.JSONObject;
import okhttp3.ResponseBody;
public class VMPlay extends ViewModel {
private MutableLiveData<ResponseHome> _data = new MutableLiveData<ResponseHome>();
public LiveData<ResponseHome> data = _data;
private String continuation, clickTrackingParams, visitorData;
public void getPlay(ResponseSingle responseSingle) {
String playlistId = responseSingle.getPlaylistId();
String videoId = responseSingle.getVideoId();
String params = responseSingle.getParams();
String musicVideoType = responseSingle.getMusicVideoType();
RetrofitManager.getInstance().getNext(params,playlistId,videoId,musicVideoType,new RequestListener<ResponseBody>() {
@Override
public void onFail(String errorMsg) {
_data.setValue(null);
}
@Override
public void onSuccess(ResponseBody data) {
JSONObject jsonObject = CommonUtils.toJsonObject(data);
if (jsonObject != null) {
// _data.setValue(responseHome);
} else {
_data.setValue(null);
}
}
});
}
}

View File

@ -1,9 +1,40 @@
package com.hi.music.player.ui.fragmnt; package com.hi.music.player.ui.fragmnt;
import com.hi.music.player.R; import android.content.Intent;
import com.hi.music.player.databinding.FragmentHomeBinding;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.hi.music.player.R;
import com.hi.music.player.adapter.AdapterHome;
import com.hi.music.player.api.ClickSingerListener;
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.ResponseHomeChild;
import com.hi.music.player.javabean.response.ResponseSingle;
import com.hi.music.player.ui.activity.PlayActivity;
import com.hi.music.player.ui.fragmnt.viewmodel.VMHome;
import java.util.ArrayList;
import java.util.List;
public class HomeFragment extends BaseFragment<FragmentHomeBinding> implements ClickSingerListener<ResponseSingle> {
private VMHome vmHome;
private AdapterHome adapterHome;
private int requestCount = 1;
private int totalPage = 2;
private List<ResponseHomeChild> childList = new ArrayList<>();
public class HomeFragment extends BaseFragment<FragmentHomeBinding> {
@Override @Override
protected FragmentHomeBinding getFragmentVb() { protected FragmentHomeBinding getFragmentVb() {
@ -13,10 +44,57 @@ public class HomeFragment extends BaseFragment<FragmentHomeBinding> {
@Override @Override
protected void initView() { protected void initView() {
// 在这里进行视图的初始化操作
//标题导航栏颜色设置 // //标题导航栏颜色设置
Vb.toolbar.setTitleTextColor(getResources().getColor(R.color.white)); // Vb.toolbar.setTitleTextColor(getResources().getColor(R.color.white));
AdapterHome adapterHome = new AdapterHome();
adapterHome.setSingleClickSingerListener(this::onClickSingerItem);
vmHome = getFragmentScopeViewModel(VMHome.class);
adapterHome.addLoadingFooter();
vmHome.getHome();
vmHome.data.observe(getViewLifecycleOwner(), new Observer<ResponseHome>() {
@Override
public void onChanged(ResponseHome responseHome) {
List<ResponseHomeChild> childList1 = responseHome.getChildList();
childList.addAll(childList1);
adapterHome.removeLoadingFooter();
adapterHome.addData(childList1);
}
});
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) {
CommonUtils.LogMsg("------loadmore--");
adapterHome.addLoadingFooter();
vmHome.getHomeMore();
}
requestCount++;
}
}
});
}
@Override
public void onClickSingerItem(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);
}
} }
} }

View File

@ -0,0 +1,78 @@
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.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(ResponseBody data) {
JSONObject jsonObject = CommonUtils.toJsonObject(data);
if (jsonObject != null) {
ResponseHome responseHome = JsonHelper.ResolveHomeJson(jsonObject);
continuation = responseHome.getContinuation();
clickTrackingParams = responseHome.getClickTrackingParams();
visitorData = responseHome.getVisitorData();
_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(ResponseBody data) {
JSONObject jsonObject = CommonUtils.toJsonObject(data);
if (jsonObject != null) {
ResponseHome responseHome = JsonHelper.ResolveHomeMoreJson(jsonObject);
continuation = responseHome.getContinuation();
clickTrackingParams = responseHome.getClickTrackingParams();
_data.setValue(responseHome);
} else {
_data.setValue(null);
}
}
});
}
}

View File

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

View File

@ -10,6 +10,7 @@
android:id="@+id/home_view_pager" android:id="@+id/home_view_pager"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/home_tab_layout" app:layout_constraintBottom_toTopOf="@+id/home_tab_layout"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.PlayActivity">
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,9 +1,9 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.fragmnt.HomeFragment"> tools:context=".ui.fragmnt.HomeFragment">
<!-- 顶部应用栏 --> <!-- 顶部应用栏 -->
@ -21,184 +21,11 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<!-- 滚动视图 --> <androidx.recyclerview.widget.RecyclerView
<androidx.core.widget.NestedScrollView android:id="@+id/recycler_song_of_the_day"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"> android:orientation="horizontal" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Song Of The Day --> </LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<TextView
android:id="@+id/tv_song_of_the_day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/song_of_the_day"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/iv_song_of_the_day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/right_arrow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_song_of_the_day"
android:layout_marginEnd="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_song_of_the_day"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
<!-- Recently Played -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<TextView
android:id="@+id/tv_recently_played"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/recently_played"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/iv_recently_played"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/right_arrow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_recently_played"
android:layout_marginEnd="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_recently_played"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
<!-- Top Artists -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<TextView
android:id="@+id/tv_top_artists"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/top_artists"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/iv_top_artists"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/right_arrow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_top_artists"
android:layout_marginEnd="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_top_artists"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
<!-- Trending in Shorts -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<TextView
android:id="@+id/tv_trending_shorts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/trending_in_shorts"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/iv_trending_shorts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/right_arrow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_trending_shorts"
android:layout_marginEnd="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_trending_shorts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
<!-- New Releases -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<TextView
android:id="@+id/tv_new_releases"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/new_releases"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/iv_new_releases"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/right_arrow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_new_releases"
android:layout_marginEnd="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_new_releases"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="5dp"
android:orientation="vertical">
<ImageView
android:id="@+id/header"
android:layout_width="169dp"
android:layout_height="169dp"
android:scaleType="fitXY"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/tv_title"
android:layout_width="169dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:layout_marginTop="10dp"
android:text="@string/app_name"
android:textColor="@color/text_color_1"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_subtitle"
android:layout_width="169dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:ellipsize="end"
android:maxLines="2"
android:text="@string/app_name"
android:textColor="@color/text_color_2"
android:textSize="12sp" />
</LinearLayout>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:id="@+id/pb_loading"
android:layout_marginBottom="10dp"
android:indeterminateTint="@color/white" />
</FrameLayout>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/head_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:textColor="@color/text_color_1"
android:paddingBottom="10dp"
android:paddingTop="15dp"
android:textSize="18sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_singer"
android:layout_width="match_parent"
android:layout_height="400dp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_category"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="5dp"
android:paddingEnd="5dp" />
</LinearLayout>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="80dp"
android:orientation="vertical">
<ImageView
android:id="@+id/header"
android:layout_width="66dp"
android:layout_height="66dp"
android:scaleType="fitXY"
android:layout_marginStart="14dp"
android:layout_centerVertical="true"
android:src="@mipmap/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="50dp"
android:paddingEnd="10dp"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/header"
android:orientation="vertical">
<TextView
android:id="@+id/tv_song_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/text_color_1"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_singer_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/app_name"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/text_color_1"
android:textSize="14sp" />
<!-- <TextView-->
<!-- android:id="@+id/tv_describe"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginTop="4dp"-->
<!-- android:maxLines="1"-->
<!-- android:ellipsize="end"-->
<!-- android:text="@string/app_name"-->
<!-- android:textColor="@color/text_color_1"-->
<!-- android:textSize="14sp" />-->
</LinearLayout>
</RelativeLayout>

View File

@ -2,4 +2,6 @@
<resources> <resources>
<color name="black">#FF000000</color> <color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<color name="text_color_1">#FFFFFF</color>
<color name="text_color_2">#DFD0D0</color>
</resources> </resources>