diff --git a/app/build.gradle b/app/build.gradle index bf235775c..91ebb8242 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "com.fongmi.android.tv" minSdk 21 targetSdk 32 - versionCode 23 - versionName "1.2.3" + versionCode 25 + versionName "1.2.5" ndk { abiFilters "armeabi-v7a", "arm64-v8a" } } diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java index 57c544793..741a17ed9 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java @@ -331,8 +331,8 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen mBinding.video.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)); mHandler.postDelayed(() -> getPlayerView().setUseController(true), 250); mBinding.flag.setSelectedPosition(mCurrent); - Players.get().play(); mFullscreen = true; + onPlay(0); } private void exitFullscreen() { @@ -570,6 +570,19 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen stopTimer(); } + private void onPause(boolean visible) { + mBinding.widget.exoPosition.setText(Players.get().getTime(0)); + mBinding.widget.exoDuration.setText(mControl.exoDuration.getText()); + mBinding.widget.title.setVisibility(visible ? View.VISIBLE : View.GONE); + mBinding.widget.center.setVisibility(visible ? View.VISIBLE : View.GONE); + Players.get().pause(); + } + + private void onPlay(int delay) { + mHandler.postDelayed(mHideCenter, delay); + Players.get().play(); + } + @Override public boolean dispatchKeyEvent(KeyEvent event) { if (mFullscreen && !getPlayerView().isControllerFullyVisible() && mKeyDown.hasEvent(event)) return mKeyDown.onKeyDown(event); @@ -586,10 +599,9 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen @Override public void onSeekTo(int time) { - mHandler.postDelayed(mHideCenter, 500); Players.get().seekTo(time); - Players.get().play(); mKeyDown.resetTime(); + onPlay(500); } @Override @@ -600,29 +612,20 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen @Override public void onKeyCenter() { - if (Players.get().isPlaying()) { - Players.get().pause(); - mBinding.widget.title.setVisibility(View.VISIBLE); - mBinding.widget.center.setVisibility(View.VISIBLE); - mBinding.widget.exoPosition.setText(Players.get().getTime(0)); - mBinding.widget.exoDuration.setText(mControl.exoDuration.getText()); - } else { - Players.get().play(); - mBinding.widget.title.setVisibility(View.GONE); - mBinding.widget.center.setVisibility(View.GONE); - } + if (Players.get().isPlaying()) onPause(true); + else onPlay(0); } @Override protected void onPause() { super.onPause(); - Players.get().pause(); + onPause(false); } @Override protected void onResume() { super.onResume(); - Players.get().play(); + onPlay(0); } @Override @@ -632,13 +635,12 @@ public class DetailActivity extends BaseActivity implements CustomKeyDown.Listen } else if (mFullscreen) { exitFullscreen(); } else { + destroy(); super.onBackPressed(); } } - @Override - protected void onDestroy() { - super.onDestroy(); + private void destroy() { stopTimer(); updateHistory(); Players.get().stop(); diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java index c1ace4c9c..55a23b180 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java @@ -276,13 +276,12 @@ public class HomeActivity extends BaseActivity implements CustomTitleView.Listen Notify.show(R.string.app_exit); mHandler.postDelayed(() -> mConfirmExit = false, 1000); } else { + destroy(); super.onBackPressed(); } } - @Override - protected void onDestroy() { - super.onDestroy(); + private void destroy() { Server.get().stop(); Clock.get().release(); Players.get().release(); diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VodActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VodActivity.java index a34b7fc08..99d9fa49b 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VodActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VodActivity.java @@ -25,6 +25,7 @@ import com.fongmi.android.tv.databinding.ActivityVodBinding; import com.fongmi.android.tv.ui.fragment.VodFragment; import com.fongmi.android.tv.ui.presenter.TypePresenter; import com.fongmi.android.tv.utils.ResUtil; +import com.google.gson.Gson; import java.util.ArrayList; import java.util.Collections; @@ -110,10 +111,9 @@ public class VodActivity extends BaseActivity { } private void updateFilter(Class item) { - if (item.getFilter() != null) { - getFragment().toggleFilter(item.toggleFilter().getFilter()); - mAdapter.notifyArrayItemRangeChanged(0, mAdapter.size()); - } + if (item.getFilter() == null) return; + getFragment().toggleFilter(item.toggleFilter().getFilter()); + mAdapter.notifyArrayItemRangeChanged(0, mAdapter.size()); } @Override @@ -127,6 +127,7 @@ public class VodActivity extends BaseActivity { public void onBackPressed() { Class item = mResult.getTypes().get(mBinding.pager.getCurrentItem()); if (item.getFilter() != null && item.getFilter()) updateFilter(item); + else if (getFragment().canGoBack()) getFragment().goBack(); else super.onBackPressed(); } @@ -143,7 +144,9 @@ public class VodActivity extends BaseActivity { @NonNull @Override public Fragment getItem(int position) { - return VodFragment.newInstance(mResult.getTypes().get(position).getTypeId(), mResult.getFilters().get(mResult.getTypes().get(position).getTypeId())); + Class type = mResult.getTypes().get(position); + String filter = new Gson().toJson(mResult.getFilters().get(type.getTypeId())); + return VodFragment.newInstance(type.getTypeId(), filter, type.getTypeFlag().equals("1")); } @Override diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/VodFragment.java b/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/VodFragment.java index 65cd7d317..ad9901612 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/VodFragment.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/fragment/VodFragment.java @@ -27,7 +27,6 @@ import com.fongmi.android.tv.ui.presenter.FilterPresenter; import com.fongmi.android.tv.ui.presenter.VodPresenter; import com.fongmi.android.tv.utils.ResUtil; import com.google.common.collect.Lists; -import com.google.gson.Gson; import java.util.ArrayList; import java.util.HashMap; @@ -43,6 +42,7 @@ public class VodFragment extends BaseFragment implements CustomScroller.Callback private SiteViewModel mViewModel; private CustomScroller mScroller; private List mFilters; + private List mTypeIds; private String getTypeId() { return getArguments().getString("typeId"); @@ -52,10 +52,15 @@ public class VodFragment extends BaseFragment implements CustomScroller.Callback return getArguments().getString("filter"); } - public static VodFragment newInstance(String typeId, List filter) { + private boolean isFolder() { + return getArguments().getBoolean("folder"); + } + + public static VodFragment newInstance(String typeId, String filter, boolean folder) { Bundle args = new Bundle(); args.putString("typeId", typeId); - args.putString("filter", new Gson().toJson(filter)); + args.putString("filter", filter); + args.putBoolean("folder", folder); VodFragment fragment = new VodFragment(); fragment.setArguments(args); return fragment; @@ -69,6 +74,7 @@ public class VodFragment extends BaseFragment implements CustomScroller.Callback @Override protected void initView() { mFilters = Filter.arrayFrom(getFilter()); + mTypeIds = new ArrayList<>(); mExtend = new HashMap<>(); setRecyclerView(); setViewModel(); @@ -104,19 +110,21 @@ public class VodFragment extends BaseFragment implements CustomScroller.Callback private void getVideo() { mScroller.reset(); - getVideo("1"); + getVideo(getTypeId(), "1"); } private void checkPage() { - if (mScroller.getPage() != 1 || mAdapter.size() >= 4) return; + if (mScroller.getPage() != 1 || mAdapter.size() >= 4 || isFolder()) return; mScroller.addPage(); - getVideo("2"); + getVideo(getTypeId(), "2"); } - private void getVideo(String page) { + private void getVideo(String typeId, String page) { + if (page.equals("1")) mLast = null; + if (isFolder()) mTypeIds.add(typeId); boolean clear = page.equals("1") && mAdapter.size() > mFilters.size(); if (clear) mAdapter.removeItems(mFilters.size(), mAdapter.size() - mFilters.size()); - mViewModel.categoryContent(getTypeId(), page, true, mExtend); + mViewModel.categoryContent(typeId, page, true, mExtend); } private boolean checkLastSize(List items) { @@ -161,9 +169,20 @@ public class VodFragment extends BaseFragment implements CustomScroller.Callback } } + public boolean canGoBack() { + return mTypeIds.size() > 1; + } + + public void goBack() { + String typeId = mTypeIds.get(mTypeIds.size() - 2); + mTypeIds = mTypeIds.subList(0, mTypeIds.size() - 2); + getVideo(typeId, "1"); + } + @Override public void onItemClick(Vod item) { - if (item.getVodId().startsWith("msearch:")) onLongClick(item); + if (item.getVodTag().equals("folder")) getVideo(item.getVodId(), "1"); + else if (item.getVodId().startsWith("msearch:")) onLongClick(item); else DetailActivity.start(getActivity(), item.getVodId()); } @@ -175,8 +194,9 @@ public class VodFragment extends BaseFragment implements CustomScroller.Callback @Override public void onLoadMore(String page) { + if (isFolder()) return; mScroller.setLoading(true); - getVideo(page); + getVideo(getTypeId(), page); } @Override diff --git a/app/src/leanback/res/layout/adapter_config.xml b/app/src/leanback/res/layout/adapter_config.xml index 5c0941d1e..215387ba1 100644 --- a/app/src/leanback/res/layout/adapter_config.xml +++ b/app/src/leanback/res/layout/adapter_config.xml @@ -15,8 +15,6 @@ android:focusable="true" android:focusableInTouchMode="true" android:gravity="center" - android:marqueeRepeatLimit="marquee_forever" - android:scrollHorizontally="true" android:singleLine="true" android:textColor="@color/white" android:textSize="18sp" diff --git a/app/src/leanback/res/layout/adapter_part.xml b/app/src/leanback/res/layout/adapter_part.xml index ff072bbda..a16ef744a 100644 --- a/app/src/leanback/res/layout/adapter_part.xml +++ b/app/src/leanback/res/layout/adapter_part.xml @@ -5,10 +5,12 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/selector_item" + android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:gravity="center" android:nextFocusUp="@id/group" + android:singleLine="true" android:textColor="@color/white" android:textSize="16sp" tools:text="分詞" /> \ No newline at end of file diff --git a/app/src/leanback/res/layout/adapter_search_history.xml b/app/src/leanback/res/layout/adapter_search_history.xml index 5c1663f19..5116149b1 100644 --- a/app/src/leanback/res/layout/adapter_search_history.xml +++ b/app/src/leanback/res/layout/adapter_search_history.xml @@ -8,8 +8,6 @@ android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" - android:marqueeRepeatLimit="marquee_forever" - android:scrollHorizontally="true" android:singleLine="true" android:textColor="@color/white" android:textSize="16sp" diff --git a/app/src/leanback/res/layout/adapter_search_word.xml b/app/src/leanback/res/layout/adapter_search_word.xml index 15b456142..47e894dec 100644 --- a/app/src/leanback/res/layout/adapter_search_word.xml +++ b/app/src/leanback/res/layout/adapter_search_word.xml @@ -8,8 +8,6 @@ android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" - android:marqueeRepeatLimit="marquee_forever" - android:scrollHorizontally="true" android:singleLine="true" android:textColor="@color/white" android:textSize="16sp" diff --git a/app/src/leanback/res/layout/adapter_site.xml b/app/src/leanback/res/layout/adapter_site.xml index e0618a7cf..5a71019ed 100644 --- a/app/src/leanback/res/layout/adapter_site.xml +++ b/app/src/leanback/res/layout/adapter_site.xml @@ -15,8 +15,6 @@ android:focusable="true" android:focusableInTouchMode="true" android:gravity="center" - android:marqueeRepeatLimit="marquee_forever" - android:scrollHorizontally="true" android:singleLine="true" android:textColor="@color/white" android:textSize="18sp" diff --git a/app/src/leanback/res/layout/adapter_vod.xml b/app/src/leanback/res/layout/adapter_vod.xml index 038e4ceac..c346e0650 100644 --- a/app/src/leanback/res/layout/adapter_vod.xml +++ b/app/src/leanback/res/layout/adapter_vod.xml @@ -80,9 +80,7 @@ android:background="@drawable/shape_vod_name" android:ellipsize="marquee" android:gravity="center" - android:marqueeRepeatLimit="marquee_forever" android:padding="6dp" - android:scrollHorizontally="true" android:singleLine="true" android:textColor="@color/white" android:textSize="16sp" diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Class.java b/app/src/main/java/com/fongmi/android/tv/bean/Class.java index a14cabd2c..cf9c52da2 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Class.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Class.java @@ -1,5 +1,7 @@ package com.fongmi.android.tv.bean; +import android.text.TextUtils; + import com.fongmi.android.tv.R; import com.google.gson.annotations.SerializedName; @@ -18,6 +20,9 @@ public class Class { @SerializedName("type_name") private String typeName; + @SerializedName("type_flag") + private String typeFlag; + private Boolean filter; public String getTypeId() { @@ -28,6 +33,10 @@ public class Class { return typeName; } + public String getTypeFlag() { + return TextUtils.isEmpty(typeFlag) ? "" : typeFlag; + } + public void setFilter(Boolean filter) { this.filter = filter; } diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Hot.java b/app/src/main/java/com/fongmi/android/tv/bean/Hot.java index 6554448a1..229d59a20 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Hot.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Hot.java @@ -4,6 +4,7 @@ import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class Hot { @@ -16,9 +17,13 @@ public class Hot { } public static List get(String str) { - List items = new ArrayList<>(); - for (Data.Item item : objectFrom(str).getData().getItemList()) items.add(item.getTitle()); - return items; + try { + List items = new ArrayList<>(); + for (Data.Item item : objectFrom(str).getData().getItemList()) items.add(item.getTitle()); + return items; + } catch (Exception e) { + return Collections.emptyList(); + } } private Data getData() { diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Suggest.java b/app/src/main/java/com/fongmi/android/tv/bean/Suggest.java index 5df73b0a2..de74d7edd 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Suggest.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Suggest.java @@ -4,6 +4,7 @@ import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class Suggest { @@ -16,9 +17,13 @@ public class Suggest { } public static List get(String str) { - List items = new ArrayList<>(); - for (Data item : objectFrom(str).getData()) items.add(item.getName()); - return items; + try { + List items = new ArrayList<>(); + for (Data item : objectFrom(str).getData()) items.add(item.getName()); + return items; + } catch (Exception e) { + return Collections.emptyList(); + } } private List getData() { diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Vod.java b/app/src/main/java/com/fongmi/android/tv/bean/Vod.java index 53f96628b..bac69120b 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Vod.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Vod.java @@ -72,6 +72,9 @@ public class Vod { @SerializedName("vod_play_url") private String vodPlayUrl; + @SerializedName("vod_tag") + private String vodTag; + @Path("dl") @ElementList(entry = "dd", required = false, inline = true) private List vodFlags; @@ -132,6 +135,10 @@ public class Vod { return TextUtils.isEmpty(vodPlayUrl) ? "" : vodPlayUrl; } + public String getVodTag() { + return TextUtils.isEmpty(vodTag) ? "" : vodTag; + } + public List getVodFlags() { return vodFlags = vodFlags == null ? new ArrayList<>() : vodFlags; } diff --git a/app/src/main/java/com/fongmi/android/tv/player/Players.java b/app/src/main/java/com/fongmi/android/tv/player/Players.java index 9c49f391f..05a21d50e 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/Players.java +++ b/app/src/main/java/com/fongmi/android/tv/player/Players.java @@ -74,18 +74,18 @@ public class Players implements Player.Listener, ParseTask.Callback { } public String getSpeed() { - return String.format(Locale.getDefault(), "%.2f", exoPlayer.getPlaybackParameters().speed); + return String.format(Locale.getDefault(), "%.2f", exo().getPlaybackParameters().speed); } public void addSpeed() { - float speed = exoPlayer.getPlaybackParameters().speed; + float speed = exo().getPlaybackParameters().speed; float addon = speed >= 2 ? 1f : 0.25f; speed = speed >= 5 ? 0.5f : speed + addon; - exoPlayer.setPlaybackSpeed(speed); + exo().setPlaybackSpeed(speed); } public void resetSpeed() { - exoPlayer.setPlaybackSpeed(1f); + exo().setPlaybackSpeed(1f); } public String getTime(long time) { @@ -100,27 +100,27 @@ public class Players implements Player.Listener, ParseTask.Callback { } public long getCurrentPosition() { - return exoPlayer.getCurrentPosition(); + return exo().getCurrentPosition(); } public long getDuration() { - return exoPlayer.getDuration(); + return exo().getDuration(); } public void seekTo(int time) { - exoPlayer.seekTo(getCurrentPosition() + time); + exo().seekTo(getCurrentPosition() + time); } public void seekTo(long time) { - exoPlayer.seekTo(time); + exo().seekTo(time); } public boolean isPlaying() { - return exoPlayer.isPlaying(); + return exo().isPlaying(); } public boolean isIdle() { - return exoPlayer.getPlaybackState() == Player.STATE_IDLE; + return exo().getPlaybackState() == Player.STATE_IDLE; } public boolean canNext() { @@ -139,39 +139,33 @@ public class Players implements Player.Listener, ParseTask.Callback { } private void setMediaSource(Result result) { - exoPlayer.setMediaSource(ExoUtil.getSource(result)); + exo().setMediaSource(ExoUtil.getSource(result)); PlayerEvent.state(0); - exoPlayer.prepare(); + exo().prepare(); + exo().play(); } private void setMediaSource(Map headers, String url) { - exoPlayer.setMediaSource(ExoUtil.getSource(headers, url)); + exo().setMediaSource(ExoUtil.getSource(headers, url)); PlayerEvent.state(0); - exoPlayer.prepare(); + exo().prepare(); + exo().play(); } public void pause() { - if (exoPlayer != null) { - exoPlayer.pause(); - } + exo().pause(); } public void stop() { this.retry = 0; - if (exoPlayer != null) { - exoPlayer.stop(); - exoPlayer.clearMediaItems(); - exoPlayer.setPlaybackSpeed(1.0f); - } - if (webView != null) { - webView.stop(false); - } + exo().stop(); + exo().clearMediaItems(); + exo().setPlaybackSpeed(1.0f); + if (webView != null) webView.stop(false); } public void play() { - if (exoPlayer != null) { - exoPlayer.play(); - } + exo().play(); } public void release() {