From 5725e1f4fecfd2828718f68688f4994f2ceca42c Mon Sep 17 00:00:00 2001 From: FongMi Date: Tue, 19 Jul 2022 23:04:40 +0800 Subject: [PATCH] Add play controller - part 4 --- app/build.gradle | 1 + .../com/fongmi/bear/model/SiteViewModel.java | 21 ++++++-- .../java/com/fongmi/bear/player/Players.java | 11 ++++ .../bear/ui/activity/DetailActivity.java | 7 ++- .../fongmi/bear/ui/activity/PlayActivity.java | 53 ++++++++++++++----- .../java/com/fongmi/bear/utils/Prefers.java | 12 +++++ .../java/com/fongmi/bear/utils/ResUtil.java | 5 ++ app/src/main/res/layout/activity_detail.xml | 4 +- app/src/main/res/layout/activity_play.xml | 2 +- app/src/main/res/layout/view_controller.xml | 15 +++--- app/src/main/res/values-zh-rCN/strings.xml | 8 +++ app/src/main/res/values-zh-rTW/strings.xml | 8 +++ app/src/main/res/values/colors.xml | 10 ---- app/src/main/res/values/strings.xml | 8 +++ gradle.properties | 3 +- 15 files changed, 129 insertions(+), 39 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 730473600..749a9aa8e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,6 +41,7 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.room:room-runtime:2.4.2' + implementation 'com.github.bassaer:materialdesigncolors:1.0.0' implementation 'com.github.bumptech.glide:glide:4.13.2' implementation 'com.google.android.material:material:1.6.1' implementation 'com.google.android.exoplayer:exoplayer:2.18.0' diff --git a/app/src/main/java/com/fongmi/bear/model/SiteViewModel.java b/app/src/main/java/com/fongmi/bear/model/SiteViewModel.java index decdb6031..953e78bb3 100644 --- a/app/src/main/java/com/fongmi/bear/model/SiteViewModel.java +++ b/app/src/main/java/com/fongmi/bear/model/SiteViewModel.java @@ -27,7 +27,6 @@ public class SiteViewModel extends ViewModel { public ExecutorService service; public SiteViewModel() { - this.service = Executors.newFixedThreadPool(2); this.result = new MutableLiveData<>(); this.player = new MutableLiveData<>(); } @@ -87,22 +86,29 @@ public class SiteViewModel extends ViewModel { }); } + private void initService(boolean close) { + if (service != null && close) service.shutdownNow(); + service = Executors.newFixedThreadPool(2); + } + private void postResult(Callable callable) { + initService(false); service.execute(() -> { try { - result.postValue(service.submit(callable).get(10, TimeUnit.SECONDS)); + if (!Thread.interrupted()) result.postValue(service.submit(callable).get(10, TimeUnit.SECONDS)); } catch (Exception e) { - result.postValue(new Result()); + if (!Thread.interrupted()) result.postValue(new Result()); } }); } private void postPlayer(Callable callable) { + initService(true); service.execute(() -> { try { - player.postValue(service.submit(callable).get(10, TimeUnit.SECONDS)); + if (!Thread.interrupted()) player.postValue(service.submit(callable).get(10, TimeUnit.SECONDS)); } catch (Exception e) { - player.postValue(null); + if (!Thread.interrupted()) player.postValue(null); } }); } @@ -123,4 +129,9 @@ public class SiteViewModel extends ViewModel { } return items; } + + @Override + protected void onCleared() { + if (service != null) service.shutdownNow(); + } } diff --git a/app/src/main/java/com/fongmi/bear/player/Players.java b/app/src/main/java/com/fongmi/bear/player/Players.java index 4b44c98f9..48907a261 100644 --- a/app/src/main/java/com/fongmi/bear/player/Players.java +++ b/app/src/main/java/com/fongmi/bear/player/Players.java @@ -44,6 +44,16 @@ public class Players implements Player.Listener { return exoPlayer; } + public String getSpeed() { + return String.valueOf(exoPlayer.getPlaybackParameters().speed); + } + + public String addSpeed() { + float speed = exoPlayer.getPlaybackParameters().speed; + exoPlayer.setPlaybackSpeed(speed = speed >= 3 ? 0.75f : speed + 0.25f); + return String.valueOf(speed); + } + public void setMediaSource(JsonObject object) { HashMap headers = new HashMap<>(); String parse = object.get("parse").getAsString(); @@ -89,6 +99,7 @@ public class Players implements Player.Listener { if (exoPlayer != null) { exoPlayer.stop(); exoPlayer.seekTo(0); + exoPlayer.setPlaybackSpeed(1.0f); } } diff --git a/app/src/main/java/com/fongmi/bear/ui/activity/DetailActivity.java b/app/src/main/java/com/fongmi/bear/ui/activity/DetailActivity.java index c86f2e2d6..d98551c28 100644 --- a/app/src/main/java/com/fongmi/bear/ui/activity/DetailActivity.java +++ b/app/src/main/java/com/fongmi/bear/ui/activity/DetailActivity.java @@ -25,6 +25,7 @@ import com.fongmi.bear.player.Players; import com.fongmi.bear.ui.presenter.EpisodePresenter; import com.fongmi.bear.ui.presenter.FlagPresenter; import com.fongmi.bear.ui.presenter.GroupPresenter; +import com.fongmi.bear.utils.Prefers; import com.fongmi.bear.utils.ResUtil; import com.google.android.exoplayer2.Player; @@ -68,6 +69,7 @@ public class DetailActivity extends BaseActivity { protected void initView() { mBinding.progressLayout.showProgress(); mBinding.video.setPlayer(Players.get().callback(this).exo()); + mBinding.video.setResizeMode(Prefers.getScale()); setRecyclerView(); setViewModel(); getDetail(); @@ -121,7 +123,9 @@ public class DetailActivity extends BaseActivity { private void setViewModel() { mSiteViewModel = new ViewModelProvider(this).get(SiteViewModel.class); - mSiteViewModel.player.observe(this, object -> Players.get().setMediaSource(object)); + mSiteViewModel.player.observe(this, object -> { + if (object != null) Players.get().setMediaSource(object); + }); mSiteViewModel.result.observe(this, result -> { if (result.getList().isEmpty()) mBinding.progressLayout.showErrorText(); else setDetail(result.getList().get(0)); @@ -186,6 +190,7 @@ public class DetailActivity extends BaseActivity { @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); + mBinding.video.setResizeMode(Prefers.getScale()); mBinding.video.setPlayer(Players.get().exo()); } diff --git a/app/src/main/java/com/fongmi/bear/ui/activity/PlayActivity.java b/app/src/main/java/com/fongmi/bear/ui/activity/PlayActivity.java index 15a6833bc..9e157432b 100644 --- a/app/src/main/java/com/fongmi/bear/ui/activity/PlayActivity.java +++ b/app/src/main/java/com/fongmi/bear/ui/activity/PlayActivity.java @@ -11,12 +11,14 @@ import androidx.viewbinding.ViewBinding; import com.fongmi.bear.R; import com.fongmi.bear.bean.Vod; import com.fongmi.bear.databinding.ActivityPlayBinding; +import com.fongmi.bear.databinding.ViewControllerBinding; import com.fongmi.bear.event.PlayerEvent; import com.fongmi.bear.impl.KeyDownImpl; import com.fongmi.bear.model.SiteViewModel; import com.fongmi.bear.player.Players; import com.fongmi.bear.utils.KeyDown; import com.fongmi.bear.utils.Notify; +import com.fongmi.bear.utils.Prefers; import com.fongmi.bear.utils.ResUtil; import com.fongmi.bear.utils.Utils; import com.google.android.exoplayer2.Player; @@ -27,6 +29,7 @@ import org.greenrobot.eventbus.ThreadMode; public class PlayActivity extends BaseActivity implements KeyDownImpl { + private ViewControllerBinding mControl; private ActivityPlayBinding mBinding; private SiteViewModel mSiteViewModel; private Vod.Flag mVodFlag; @@ -52,7 +55,13 @@ public class PlayActivity extends BaseActivity implements KeyDownImpl { protected void initView() { mKeyDown = KeyDown.create(this); mVodFlag = Vod.Flag.objectFrom(getFlag()); + mControl = ViewControllerBinding.bind(mBinding.video.findViewById(R.id.control)); + mControl.scale.setText(ResUtil.getStringArray(R.array.select_scale)[Prefers.getScale()]); mBinding.video.setPlayer(Players.get().callback(this).exo()); + mBinding.video.setControllerHideOnTouch(false); + mBinding.video.setControllerShowTimeoutMs(0); + mBinding.video.setResizeMode(Prefers.getScale()); + mControl.speed.setText(Players.get().getSpeed()); setViewModel(); findCurrent(); } @@ -60,22 +69,18 @@ public class PlayActivity extends BaseActivity implements KeyDownImpl { @Override protected void initEvent() { EventBus.getDefault().register(this); - mBinding.video.findViewById(R.id.next).setOnClickListener(view -> { - int max = mVodFlag.getEpisodes().size() - 1; - mCurrent = ++mCurrent > max ? max : mCurrent; - if (mVodFlag.getEpisodes().get(mCurrent).isActivated()) Notify.show(R.string.error_play_next); - else getPlayer(); - }); - mBinding.video.findViewById(R.id.prev).setOnClickListener(view -> { - mCurrent = --mCurrent < 0 ? 0 : mCurrent; - if (mVodFlag.getEpisodes().get(mCurrent).isActivated()) Notify.show(R.string.error_play_prev); - else getPlayer(); - }); + mControl.next.setOnClickListener(view -> onNext()); + mControl.prev.setOnClickListener(view -> onPrev()); + mControl.replay.setOnClickListener(view -> getPlayer()); + mControl.speed.setOnClickListener(view -> mControl.speed.setText(Players.get().addSpeed())); + mControl.scale.setOnClickListener(view -> onScale()); } private void setViewModel() { mSiteViewModel = new ViewModelProvider(this).get(SiteViewModel.class); - mSiteViewModel.player.observe(this, object -> Players.get().setMediaSource(object)); + mSiteViewModel.player.observe(this, object -> { + if (object != null) Players.get().setMediaSource(object); + }); } private void findCurrent() { @@ -88,11 +93,31 @@ public class PlayActivity extends BaseActivity implements KeyDownImpl { } private void getPlayer() { - Vod.Flag.Episode episode = mVodFlag.getEpisodes().get(mCurrent); - mVodFlag.setActivated(episode); mBinding.progress.getRoot().setVisibility(View.VISIBLE); + Vod.Flag.Episode episode = mVodFlag.getEpisodes().get(mCurrent); mSiteViewModel.playerContent(mVodFlag.getFlag(), episode.getUrl()); Notify.show(ResUtil.getString(R.string.play_ready, episode.getName())); + mVodFlag.setActivated(episode); + } + + private void onNext() { + int max = mVodFlag.getEpisodes().size() - 1; + mCurrent = ++mCurrent > max ? max : mCurrent; + if (mVodFlag.getEpisodes().get(mCurrent).isActivated()) Notify.show(R.string.error_play_next); + else getPlayer(); + } + + private void onPrev() { + mCurrent = --mCurrent < 0 ? 0 : mCurrent; + if (mVodFlag.getEpisodes().get(mCurrent).isActivated()) Notify.show(R.string.error_play_prev); + else getPlayer(); + } + + private void onScale() { + int scale = mBinding.video.getResizeMode(); + mBinding.video.setResizeMode(scale = scale >= 4 ? 0 : scale + 1); + mControl.scale.setText(ResUtil.getStringArray(R.array.select_scale)[scale]); + Prefers.putScale(scale); } @Subscribe(threadMode = ThreadMode.MAIN) diff --git a/app/src/main/java/com/fongmi/bear/utils/Prefers.java b/app/src/main/java/com/fongmi/bear/utils/Prefers.java index c08dbb3a1..b4afbc744 100644 --- a/app/src/main/java/com/fongmi/bear/utils/Prefers.java +++ b/app/src/main/java/com/fongmi/bear/utils/Prefers.java @@ -20,6 +20,10 @@ public class Prefers { return getPrefers().getString(key, defaultValue); } + public static int getInt(String key) { + return getPrefers().getInt(key, 0); + } + public static void put(String key, Object obj) { if (obj == null) return; if (obj instanceof String) { @@ -50,4 +54,12 @@ public class Prefers { public static void putHome(String home) { Prefers.put("home", home); } + + public static int getScale() { + return Prefers.getInt("scale"); + } + + public static void putScale(int scale) { + Prefers.put("scale", scale); + } } diff --git a/app/src/main/java/com/fongmi/bear/utils/ResUtil.java b/app/src/main/java/com/fongmi/bear/utils/ResUtil.java index 65ef1456f..a5ac0ac9e 100644 --- a/app/src/main/java/com/fongmi/bear/utils/ResUtil.java +++ b/app/src/main/java/com/fongmi/bear/utils/ResUtil.java @@ -2,6 +2,7 @@ package com.fongmi.bear.utils; import android.util.DisplayMetrics; +import androidx.annotation.ArrayRes; import androidx.annotation.StringRes; import com.fongmi.bear.App; @@ -27,4 +28,8 @@ public class ResUtil { public static String getString(@StringRes int resId, Object... formatArgs) { return App.get().getString(resId, formatArgs); } + + public static CharSequence[] getStringArray(@ArrayRes int resId) { + return App.get().getResources().getStringArray(resId); + } } diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index a6de3d861..8fbdfbef9 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -15,6 +15,7 @@ android:layout_marginTop="24dp" android:layout_marginEnd="24dp" android:layout_marginBottom="12dp" + android:background="@color/black" android:focusable="true" android:focusableInTouchMode="true" android:foreground="@drawable/selector_video"> @@ -23,7 +24,8 @@ android:id="@+id/video" android:layout_width="match_parent" android:layout_height="match_parent" - app:resize_mode="fill" + android:background="@color/black" + app:resize_mode="fit" app:use_controller="false" /> + app:resize_mode="fit" /> + android:textColor="@color/white" + tools:text="1.0" /> + android:textColor="@color/white" + tools:text="預設" /> @@ -121,7 +124,7 @@ android:layout_weight="1" android:nextFocusUp="@+id/next" app:buffered_color="@color/grey_700" - app:played_color="@color/grey_900" + app:played_color="@color/blue_700" app:scrubber_color="@color/blue_500" app:unplayed_color="@color/grey_500" /> diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index bc582525d..5f2345451 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -49,4 +49,12 @@ 已经是最后一集了! 已经是第一集了! + + 预设 + 宽度 + 高度 + 填充 + 缩放 + + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 3b11075dd..37a0e02eb 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -49,4 +49,12 @@ 已經是最後一集了! 已經是第一集了! + + 預設 + 寬度 + 高度 + 填充 + 縮放 + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 7474ccd1a..d62e59668 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -2,16 +2,6 @@ @color/black @color/black - - #000000 - #FFFFFF - - #2196F3 - #E0E0E0 - #9E9E9E - #616161 - #212121 - #66BB6A #00000000 #1A000000 #33000000 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b540e5088..104f60989 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -49,4 +49,12 @@ It\'s the last episode! It\'s the first episode! + + Default + Width + Height + Fill + Zoom + + \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index dab7c28bf..4e59a36c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects @@ -15,6 +15,7 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 # Android operating system, and which are packaged with your app"s APK # https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true +android.enableJetifier=true # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library