Add play controller - part 4

pull/3/head
FongMi 4 years ago
parent 3df1701a33
commit 5725e1f4fe
  1. 1
      app/build.gradle
  2. 21
      app/src/main/java/com/fongmi/bear/model/SiteViewModel.java
  3. 11
      app/src/main/java/com/fongmi/bear/player/Players.java
  4. 7
      app/src/main/java/com/fongmi/bear/ui/activity/DetailActivity.java
  5. 53
      app/src/main/java/com/fongmi/bear/ui/activity/PlayActivity.java
  6. 12
      app/src/main/java/com/fongmi/bear/utils/Prefers.java
  7. 5
      app/src/main/java/com/fongmi/bear/utils/ResUtil.java
  8. 4
      app/src/main/res/layout/activity_detail.xml
  9. 2
      app/src/main/res/layout/activity_play.xml
  10. 15
      app/src/main/res/layout/view_controller.xml
  11. 8
      app/src/main/res/values-zh-rCN/strings.xml
  12. 8
      app/src/main/res/values-zh-rTW/strings.xml
  13. 10
      app/src/main/res/values/colors.xml
  14. 8
      app/src/main/res/values/strings.xml
  15. 3
      gradle.properties

@ -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'

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

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

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

@ -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)

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

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

@ -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" />
<include

@ -12,7 +12,7 @@
android:layout_height="match_parent"
app:auto_show="false"
app:controller_layout_id="@layout/view_controller"
app:resize_mode="fill" />
app:resize_mode="fit" />
<include
android:id="@+id/progress"

@ -2,7 +2,7 @@
<LinearLayout 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:id="@+id/exo_controller"
android:id="@+id/control"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
@ -49,6 +49,7 @@
android:textColor="@color/white" />
<TextView
android:id="@+id/replay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
@ -67,14 +68,15 @@
android:textSize="16sp" />
<TextView
android:id="@+id/speed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:background="@drawable/selector_text"
android:focusable="true"
android:focusableInTouchMode="true"
android:text="x1.0"
android:textColor="@color/white" />
android:textColor="@color/white"
tools:text="1.0" />
<TextView
android:layout_width="wrap_content"
@ -85,14 +87,15 @@
android:textSize="16sp" />
<TextView
android:id="@+id/scale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:background="@drawable/selector_text"
android:focusable="true"
android:focusableInTouchMode="true"
android:text="預設"
android:textColor="@color/white" />
android:textColor="@color/white"
tools:text="預設" />
</LinearLayout>
@ -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" />

@ -49,4 +49,12 @@
<string name="error_play_next">已经是最后一集了!</string>
<string name="error_play_prev">已经是第一集了!</string>
<string-array name="select_scale">
<item>预设</item>
<item>宽度</item>
<item>高度</item>
<item>填充</item>
<item>缩放</item>
</string-array>
</resources>

@ -49,4 +49,12 @@
<string name="error_play_next">已經是最後一集了!</string>
<string name="error_play_prev">已經是第一集了!</string>
<string-array name="select_scale">
<item>預設</item>
<item>寬度</item>
<item>高度</item>
<item>填充</item>
<item>縮放</item>
</string-array>
</resources>

@ -2,16 +2,6 @@
<color name="primary">@color/black</color>
<color name="primaryDark">@color/black</color>
<color name="black">#000000</color>
<color name="white">#FFFFFF</color>
<color name="blue_500">#2196F3</color>
<color name="grey_300">#E0E0E0</color>
<color name="grey_500">#9E9E9E</color>
<color name="grey_700">#616161</color>
<color name="grey_900">#212121</color>
<color name="green_400">#66BB6A</color>
<color name="transparent">#00000000</color>
<color name="black_10">#1A000000</color>
<color name="black_20">#33000000</color>

@ -49,4 +49,12 @@
<string name="error_play_next">It\'s the last episode!</string>
<string name="error_play_prev">It\'s the first episode!</string>
<string-array name="select_scale">
<item>Default</item>
<item>Width</item>
<item>Height</item>
<item>Fill</item>
<item>Zoom</item>
</string-array>
</resources>

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

Loading…
Cancel
Save