Merge branch 'fongmi' into release

release
FongMi 1 month ago
commit 116ab38f11
  1. 8
      app/build.gradle
  2. 6
      app/src/leanback/java/com/fongmi/android/tv/bean/Cache.java
  3. 2
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
  4. 2
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
  5. 79
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
  6. 2
      app/src/leanback/java/com/fongmi/android/tv/ui/fragment/TypeFragment.java
  7. 24
      app/src/main/java/com/fongmi/android/tv/bean/Cate.java
  8. 9
      app/src/main/java/com/fongmi/android/tv/bean/Channel.java
  9. 29
      app/src/main/java/com/fongmi/android/tv/bean/Class.java
  10. 2
      app/src/main/java/com/fongmi/android/tv/bean/Collect.java
  11. 5
      app/src/main/java/com/fongmi/android/tv/bean/Device.java
  12. 8
      app/src/main/java/com/fongmi/android/tv/bean/EpgData.java
  13. 6
      app/src/main/java/com/fongmi/android/tv/bean/Episode.java
  14. 13
      app/src/main/java/com/fongmi/android/tv/bean/Filter.java
  15. 13
      app/src/main/java/com/fongmi/android/tv/bean/Flag.java
  16. 5
      app/src/main/java/com/fongmi/android/tv/bean/History.java
  17. 5
      app/src/main/java/com/fongmi/android/tv/bean/Keep.java
  18. 5
      app/src/main/java/com/fongmi/android/tv/bean/Parse.java
  19. 14
      app/src/main/java/com/fongmi/android/tv/bean/Result.java
  20. 5
      app/src/main/java/com/fongmi/android/tv/bean/Site.java
  21. 12
      app/src/main/java/com/fongmi/android/tv/bean/Value.java
  22. 54
      app/src/main/java/com/fongmi/android/tv/bean/Vod.java
  23. 2
      app/src/main/java/com/fongmi/android/tv/player/exo/ExoUtil.java
  24. 3
      app/src/main/java/com/fongmi/android/tv/server/process/Action.java
  25. 3
      app/src/main/java/com/fongmi/android/tv/utils/ImgUtil.java
  26. 3
      app/src/main/java/com/fongmi/android/tv/utils/OkGlideModule.java
  27. 5
      app/src/main/java/com/fongmi/android/tv/utils/Util.java
  28. 2
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
  29. 80
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
  30. 9
      app/src/mobile/java/com/fongmi/android/tv/ui/adapter/FlagAdapter.java
  31. 2
      build.gradle
  32. 35
      quickjs/src/main/java/com/fongmi/quickjs/utils/Crypto.java

@ -16,8 +16,8 @@ android {
minSdk 24
//noinspection ExpiredTargetSdkVersion
targetSdk 28
versionCode 513
versionName "5.1.3"
versionCode 519
versionName "5.1.9"
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString(), "eventBusIndex": "com.fongmi.android.tv.event.EventIndex"]
@ -123,7 +123,7 @@ dependencies {
implementation 'com.github.bumptech.glide:avif-integration:' + glideVersion
implementation 'com.github.bumptech.glide:okhttp3-integration:' + glideVersion
implementation 'com.github.jahirfiquitiva:TextDrawable:1.0.3'
implementation 'com.github.teamnewpipe:NewPipeExtractor:v0.25.0'
implementation 'com.github.teamnewpipe:NewPipeExtractor:v0.25.2'
implementation 'com.google.android.material:material:1.13.0'
implementation 'com.guolindev.permissionx:permissionx:1.8.1'
implementation 'javax.servlet:javax.servlet-api:3.1.0'
@ -135,7 +135,7 @@ dependencies {
implementation 'org.greenrobot:eventbus:3.3.1'
implementation 'org.nanohttpd:nanohttpd:2.3.1'
implementation('org.simpleframework:simple-xml:2.7.1') { exclude group: 'stax', module: 'stax-api' exclude group: 'xpp3', module: 'xpp3' }
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.30'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.31'
leanbackImplementation 'androidx.leanback:leanback:1.2.0'
leanbackImplementation 'com.github.JessYanCoding:AndroidAutoSize:1.2.1'
mobileImplementation 'androidx.biometric:biometric:1.1.0'

@ -35,6 +35,12 @@ public class Cache {
return filters == null ? Collections.emptyList() : filters;
}
public static List<Filter> copy(String typeId) {
List<Filter> filters = get().cache.get(typeId);
if (filters == null) return Collections.emptyList();
return filters.stream().map(Filter::copy).toList();
}
public static Cache clear() {
get().cache.clear();
return get();

@ -519,7 +519,7 @@ public class CastActivity extends BaseActivity implements CustomKeyDownVod.Liste
@Override
protected void onPause() {
super.onPause();
if (isRedirect()) onPaused();
if (isRedirect()) mPlayers.stop();
}
@Override

@ -1032,7 +1032,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick
@Override
protected void onPause() {
super.onPause();
if (isRedirect()) onPaused();
if (isRedirect()) mPlayers.stop();
}
@Override

@ -96,6 +96,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.stream.IntStream;
public class VideoActivity extends BaseActivity implements CustomKeyDownVod.Listener, TrackDialog.Listener, ArrayPresenter.OnClickListener, Clock.Callback {
@ -441,27 +442,32 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
}
private void setDetail(Vod item) {
item.checkPic(getPic());
item.checkName(getName());
mBinding.progressLayout.showContent();
mBinding.video.setTag(item.getPic(getPic()));
mBinding.name.setText(item.getName(getName()));
setText(mBinding.remark, 0, item.getRemarks());
setText(mBinding.year, R.string.detail_year, item.getYear());
setText(mBinding.area, R.string.detail_area, item.getArea());
setText(mBinding.type, R.string.detail_type, item.getTypeName());
setText(mBinding.site, R.string.detail_site, getSite().getName());
setText(mBinding.actor, R.string.detail_actor, item.getActor());
setText(mBinding.content, R.string.detail_content, item.getContent());
setText(mBinding.director, R.string.detail_director, item.getDirector());
mBinding.name.setText(item.getName());
mFlagAdapter.setItems(item.getFlags(), null);
mBinding.content.setMaxLines(getMaxLines());
mBinding.video.requestFocus();
App.removeCallbacks(mR4);
checkHistory(item);
checkFlag(item);
checkKeepImg();
setText(item);
updateKeep();
}
private void setText(Vod item) {
setText(mBinding.year, R.string.detail_year, item.getYear());
setText(mBinding.area, R.string.detail_area, item.getArea());
setText(mBinding.type, R.string.detail_type, item.getTypeName());
setText(mBinding.site, R.string.detail_site, getSite().getName());
setText(mBinding.content, R.string.detail_content, item.getContent());
setText(mBinding.director, R.string.detail_director, item.getDirector());
setText(mBinding.actor, R.string.detail_actor, item.getActor());
setText(mBinding.remark, 0, item.getRemarks());
mBinding.content.setMaxLines(getMaxLines());
}
private int getMaxLines() {
int lines = 1;
if (isGone(mBinding.actor)) ++lines;
@ -471,6 +477,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
}
private void setText(TextView view, int resId, String text) {
if (TextUtils.isEmpty(text) && !TextUtils.isEmpty(view.getText())) return;
view.setText(getSpan(resId, text), TextView.BufferType.SPANNABLE);
view.setVisibility(text.isEmpty() ? View.GONE : View.VISIBLE);
view.setLinkTextColor(MDColor.YELLOW_500);
@ -518,9 +525,9 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
private void setPlayer(Result result) {
result.getUrl().set(mQualityAdapter.getPosition());
if (!result.getArtwork().isEmpty()) setArtwork(result.getArtwork());
if (result.hasArtwork()) setArtwork(result.getArtwork());
if (result.hasPosition()) mHistory.setPosition(result.getPosition());
if (!result.getDesc().isEmpty()) setText(mBinding.content, R.string.detail_content, result.getDesc());
if (result.hasDesc()) setText(mBinding.content, R.string.detail_content, result.getDesc());
setUseParse(VodConfig.hasParse() && ((result.getPlayUrl().isEmpty() && VodConfig.get().getFlags().contains(result.getFlag())) || result.getJx() == 1));
mPlayers.start(result, isUseParse(), getSite().isChangeable() ? getSite().getTimeout() : -1);
mBinding.control.parse.setVisibility(isUseParse() ? View.VISIBLE : View.GONE);
@ -913,12 +920,14 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
App.post(mR2, 500);
}
private void setArtwork() {
setArtwork(mHistory.getVodPic());
private void setArtwork(String url) {
mHistory.setVodPic(url);
setMetadata();
setArtwork();
}
private void setArtwork(String url) {
ImgUtil.load(this, url, new CustomTarget<>() {
private void setArtwork() {
ImgUtil.load(this, mHistory.getVodPic(), new CustomTarget<>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
mBinding.exo.setDefaultArtwork(resource);
@ -1012,17 +1021,29 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
}
private void updateVod(Vod item) {
mHistory.setVodPic(item.getPic());
mHistory.setVodName(item.getName());
mBinding.name.setText(item.getName());
mBinding.widget.title.setText(item.getName());
setText(mBinding.content, R.string.detail_content, item.getContent());
setText(mBinding.director, R.string.detail_director, item.getDirector());
mBinding.content.setMaxLines(getMaxLines());
setPartAdapter();
updateKeep();
setArtwork();
setMetadata();
boolean id = !item.getId().isEmpty();
boolean pic = !item.getPic().isEmpty();
boolean name = !item.getName().isEmpty();
if (id) getIntent().putExtra("id", item.getId());
if (id) mHistory.setKey(getHistoryKey());
if (pic) mHistory.setVodPic(item.getPic());
if (name) mHistory.setVodName(item.getName());
if (name) mBinding.name.setText(item.getName());
if (name) mBinding.widget.title.setText(item.getName());
updateFlag(getFlag(), item.getFlags());
if (pic || name) setMetadata();
if (pic || name) updateKeep();
if (name) setPartAdapter();
if (pic) setArtwork();
setText(item);
}
private void updateFlag(Flag activated, List<Flag> items) {
items.forEach(item -> IntStream.range(0, mFlagAdapter.size()).mapToObj(i -> (Flag) mFlagAdapter.get(i))
.filter(item::equals).findFirst().ifPresentOrElse(target -> {
target.mergeEpisodes(item.getEpisodes(), mHistory.isRevSort());
if (target.equals(activated)) setEpisodeAdapter(target.getEpisodes());
}, () -> mFlagAdapter.add(item)));
}
@Override
@ -1397,7 +1418,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
@Override
protected void onPause() {
super.onPause();
if (isRedirect()) onPaused();
if (isRedirect()) mPlayers.stop();
}
@Override

@ -90,7 +90,7 @@ public class TypeFragment extends BaseFragment implements CustomScroller.Callbac
}
private List<Filter> getFilter() {
return Cache.get(getTypeId());
return Cache.copy(getTypeId());
}
private Site getSite() {

@ -8,22 +8,22 @@ import com.google.gson.annotations.SerializedName;
public class Cate implements Parcelable {
@SerializedName("land")
private int land;
private Integer land;
@SerializedName("circle")
private int circle;
private Integer circle;
@SerializedName("ratio")
private float ratio;
private Float ratio;
public int getLand() {
return land;
return land == null ? 0 : land;
}
public int getCircle() {
return circle;
return circle == null ? 0 : circle;
}
public float getRatio() {
return ratio;
return ratio == null ? 0 : ratio;
}
public Style getStyle() {
@ -37,15 +37,15 @@ public class Cate implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.land);
dest.writeInt(this.circle);
dest.writeFloat(this.ratio);
dest.writeValue(this.land);
dest.writeValue(this.circle);
dest.writeValue(this.ratio);
}
protected Cate(Parcel in) {
this.land = in.readInt();
this.circle = in.readInt();
this.ratio = in.readFloat();
this.land = (Integer) in.readValue(Integer.class.getClassLoader());
this.circle = (Integer) in.readValue(Integer.class.getClassLoader());
this.ratio = (Float) in.readValue(Float.class.getClassLoader());
}
public static final Creator<Cate> CREATOR = new Creator<>() {

@ -22,6 +22,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
public class Channel {
@ -385,16 +386,16 @@ public class Channel {
if (!(obj instanceof Channel it)) return false;
String name1 = getName(), name2 = it.getName();
String number1 = getNumber(), number2 = it.getNumber();
if (!name1.isEmpty() && !name2.isEmpty()) return name1.equals(name2);
if (!number1.isEmpty() && !number2.isEmpty()) return number1.equals(number2);
if (!name1.isEmpty() && !name2.isEmpty()) return Objects.equals(name1, name2);
if (!number1.isEmpty() && !number2.isEmpty()) return Objects.equals(number1, number2);
return false;
}
@Override
public int hashCode() {
String name = getName(), number = getNumber();
if (!name.isEmpty()) return name.hashCode();
if (!number.isEmpty()) return number.hashCode();
if (!name.isEmpty()) return Objects.hash(name);
if (!number.isEmpty()) return Objects.hash(number);
return 0;
}
}

@ -17,6 +17,7 @@ import org.simpleframework.xml.Text;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@Root(strict = false)
public class Class implements Parcelable, Diffable<Class> {
@ -36,13 +37,13 @@ public class Class implements Parcelable, Diffable<Class> {
private List<Filter> filters;
@SerializedName("land")
private int land;
private Integer land;
@SerializedName("circle")
private int circle;
private Integer circle;
@SerializedName("ratio")
private float ratio;
private Float ratio;
private boolean filter;
private boolean activated;
@ -87,15 +88,15 @@ public class Class implements Parcelable, Diffable<Class> {
}
public int getLand() {
return land;
return land == null ? 0 : land;
}
public int getCircle() {
return circle;
return circle == null ? 0 : circle;
}
public float getRatio() {
return ratio;
return ratio == null ? 0 : ratio;
}
public void setFilter(boolean filter) {
@ -135,12 +136,12 @@ public class Class implements Parcelable, Diffable<Class> {
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof Class it)) return false;
return getTypeId().equals(it.getTypeId());
return Objects.equals(getTypeId(), it.getTypeId());
}
@Override
public int hashCode() {
return getTypeId().hashCode();
return Objects.hash(getTypeId());
}
@Override
@ -154,9 +155,9 @@ public class Class implements Parcelable, Diffable<Class> {
dest.writeString(this.typeName);
dest.writeString(this.typeFlag);
dest.writeByte(this.filter ? (byte) 1 : (byte) 0);
dest.writeInt(this.land);
dest.writeInt(this.circle);
dest.writeFloat(this.ratio);
dest.writeValue(this.land);
dest.writeValue(this.circle);
dest.writeValue(this.ratio);
dest.writeByte(this.activated ? (byte) 1 : (byte) 0);
}
@ -165,9 +166,9 @@ public class Class implements Parcelable, Diffable<Class> {
this.typeName = in.readString();
this.typeFlag = in.readString();
this.filter = in.readByte() != 0;
this.land = in.readInt();
this.circle = in.readInt();
this.ratio = in.readFloat();
this.land = (Integer) in.readValue(Integer.class.getClassLoader());
this.circle = (Integer) in.readValue(Integer.class.getClassLoader());
this.ratio = (Float) in.readValue(Float.class.getClassLoader());
this.activated = in.readByte() != 0;
}

@ -63,7 +63,7 @@ public class Collect implements Parcelable, Diffable<Collect> {
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof Collect it)) return false;
return getSite().equals(it.getSite());
return Objects.equals(getSite(), it.getSite());
}
@Override

@ -20,6 +20,7 @@ import com.google.gson.annotations.SerializedName;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
@Entity(indices = @Index(value = {"uuid", "name"}, unique = true))
public class Device implements Diffable<Device>, Comparable<Device> {
@ -167,12 +168,12 @@ public class Device implements Diffable<Device>, Comparable<Device> {
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof Device it)) return false;
return getUuid().equals(it.getUuid());
return Objects.equals(getUuid(), it.getUuid());
}
@Override
public int hashCode() {
return getUuid().hashCode();
return Objects.hash(getUuid());
}
@NonNull

@ -10,6 +10,7 @@ import com.github.catvod.utils.Trans;
import com.google.gson.annotations.SerializedName;
import java.util.Calendar;
import java.util.Objects;
public class EpgData {
@ -111,14 +112,11 @@ public class EpgData {
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof EpgData it)) return false;
return getTitle().equals(it.getTitle()) && getEnd().equals(it.getEnd()) && getStart().equals(it.getStart());
return Objects.equals(getTitle(), it.getTitle()) && Objects.equals(getEnd(), it.getEnd()) && Objects.equals(getStart(), it.getStart());
}
@Override
public int hashCode() {
int result = getTitle().hashCode();
result = 31 * result + getEnd().hashCode();
result = 31 * result + getStart().hashCode();
return result;
return Objects.hash(getTitle(), getEnd(), getStart());
}
}

@ -11,6 +11,8 @@ import com.fongmi.android.tv.utils.Util;
import com.github.catvod.utils.Trans;
import com.google.gson.annotations.SerializedName;
import java.util.Objects;
public class Episode implements Parcelable, Diffable<Episode> {
@SerializedName("name")
@ -111,12 +113,12 @@ public class Episode implements Parcelable, Diffable<Episode> {
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof Episode it)) return false;
return getName().equals(it.getName());
return Objects.equals(getName(), it.getName());
}
@Override
public int hashCode() {
return getName().hashCode();
return Objects.hash(getName());
}
@Override

@ -38,6 +38,9 @@ public class Filter implements Parcelable {
return items == null ? Collections.emptyList() : items;
}
public Filter() {
}
public String getKey() {
return key;
}
@ -64,6 +67,16 @@ public class Filter implements Parcelable {
return this;
}
public Filter copy() {
Filter copy = new Filter();
copy.key = this.key;
copy.name = this.name;
copy.init = this.init;
copy.value = new ArrayList<>();
getValue().forEach(item -> copy.value.add(item.copy()));
return copy;
}
public Filter trans() {
if (Trans.pass()) return this;
getValue().forEach(Value::trans);

@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
public class Flag implements Parcelable, Diffable<Flag> {
@ -125,6 +126,14 @@ public class Flag implements Parcelable, Diffable<Flag> {
}
}
public void mergeEpisodes(List<Episode> items, boolean rev) {
for (Episode item : items) {
if (episodes.contains(item)) continue;
if (rev) episodes.add(0, item);
else episodes.add(item);
}
}
public Flag trans() {
if (Trans.pass()) return this;
this.show = Trans.s2t(flag);
@ -135,12 +144,12 @@ public class Flag implements Parcelable, Diffable<Flag> {
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof Flag it)) return false;
return getFlag().equals(it.getFlag());
return Objects.equals(getFlag(), it.getFlag());
}
@Override
public int hashCode() {
return getFlag().hashCode();
return Objects.hash(getFlag());
}
@NonNull

@ -21,6 +21,7 @@ import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@Entity
@ -344,12 +345,12 @@ public class History implements Diffable<History> {
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof History it)) return false;
return getKey().equals(it.getKey());
return Objects.equals(getKey(), it.getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
return Objects.hash(getKey());
}
@NonNull

@ -15,6 +15,7 @@ import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@Entity
public class Keep implements Diffable<Keep> {
@ -163,12 +164,12 @@ public class Keep implements Diffable<Keep> {
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof Keep it)) return false;
return getKey().equals(it.getKey());
return Objects.equals(getKey(), it.getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
return Objects.hash(getKey());
}
@Override

@ -20,6 +20,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class Parse implements Diffable<Parse> {
@ -131,12 +132,12 @@ public class Parse implements Diffable<Parse> {
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof Parse it)) return false;
return getName().equals(it.getName());
return Objects.equals(getName(), it.getName());
}
@Override
public int hashCode() {
return getName().hashCode();
return Objects.hash(getName());
}
@Override

@ -83,6 +83,8 @@ public class Result implements Parcelable {
private String click;
@SerializedName("key")
private String key;
@SerializedName("lrc")
private String lrc;
@SerializedName("position")
private Long position;
@SerializedName("pagecount")
@ -269,6 +271,10 @@ public class Result implements Parcelable {
this.key = key;
}
public String getLrc() {
return TextUtils.isEmpty(lrc) ? "" : lrc;
}
public Long getPosition() {
return position;
}
@ -305,10 +311,18 @@ public class Result implements Parcelable {
return !getMsg().isEmpty();
}
public boolean hasArtwork() {
return !getArtwork().isEmpty();
}
public boolean hasPosition() {
return getPosition() != null;
}
public boolean hasDesc() {
return !getDesc().isEmpty();
}
public String getRealUrl() {
return getPlayUrl() + getUrl().v();
}

@ -28,6 +28,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@Entity
@ -319,12 +320,12 @@ public class Site implements Parcelable {
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof Site it)) return false;
return getKey().equals(it.getKey());
return Objects.equals(getKey(), it.getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
return Objects.hash(getKey());
}
@Override

@ -10,6 +10,8 @@ import com.fongmi.android.tv.impl.Diffable;
import com.github.catvod.utils.Trans;
import com.google.gson.annotations.SerializedName;
import java.util.Objects;
public class Value implements Parcelable, Diffable<Value> {
@SerializedName("n")
@ -62,6 +64,12 @@ public class Value implements Parcelable, Diffable<Value> {
else activated = equal;
}
public Value copy() {
Value copy = new Value(n, v);
copy.activated = this.activated;
return copy;
}
public Value trans() {
this.n = Trans.s2t(n);
return this;
@ -71,12 +79,12 @@ public class Value implements Parcelable, Diffable<Value> {
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof Value it)) return false;
return getV().equals(it.getV());
return Objects.equals(getV(), it.getV());
}
@Override
public int hashCode() {
return getV().hashCode();
return Objects.hash(getV());
}
@Override

@ -6,6 +6,7 @@ import android.text.Html;
import android.text.TextUtils;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.fongmi.android.tv.App;
@ -90,13 +91,13 @@ public class Vod implements Parcelable, Diffable<Vod> {
private Style style;
@SerializedName("land")
private int land;
private Integer land;
@SerializedName("circle")
private int circle;
private Integer circle;
@SerializedName("ratio")
private float ratio;
private Float ratio;
@Path("dl")
@ElementList(entry = "dd", required = false, inline = true)
@ -104,6 +105,11 @@ public class Vod implements Parcelable, Diffable<Vod> {
private Site site;
public static Vod objectFrom(String str) {
Vod vod = App.gson().fromJson(str, Vod.class);
return vod == null ? new Vod() : vod.trans().setFlags();
}
public static List<Vod> arrayFrom(String str) {
Type listType = new TypeToken<List<Vod>>() {}.getType();
List<Vod> items = App.gson().fromJson(str, listType);
@ -206,15 +212,15 @@ public class Vod implements Parcelable, Diffable<Vod> {
}
public int getLand() {
return land;
return land == null ? 0 : land;
}
public int getCircle() {
return circle;
return circle == null ? 0 : circle;
}
public float getRatio() {
return ratio;
return ratio == null ? 0 : ratio;
}
public List<Flag> getFlags() {
@ -265,18 +271,16 @@ public class Vod implements Parcelable, Diffable<Vod> {
return !getAction().isEmpty();
}
public Style getStyle(Style style) {
return getStyle() != null ? getStyle() : style != null ? style : Style.rect();
}
public String getPic(String pic) {
public void checkPic(String pic) {
if (getPic().isEmpty()) setPic(pic);
return getPic();
}
public String getName(String name) {
public void checkName(String name) {
if (getName().isEmpty()) setName(name);
return getName();
}
public Style getStyle(Style style) {
return getStyle() != null ? getStyle() : style != null ? style : Style.rect();
}
public Vod setFlags() {
@ -299,16 +303,22 @@ public class Vod implements Parcelable, Diffable<Vod> {
return this;
}
@NonNull
@Override
public String toString() {
return App.gson().toJson(this);
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) return true;
if (!(obj instanceof Vod it)) return false;
return !getId().isEmpty() && !it.getId().isEmpty() ? getId().equals(it.getId()) : getName().equals(it.getName());
return !getId().isEmpty() && !it.getId().isEmpty() ? Objects.equals(getId(), it.getId()) : Objects.equals(getName(), it.getName());
}
@Override
public int hashCode() {
return !getId().isEmpty() ? getId().hashCode() : getName().hashCode();
return !getId().isEmpty() ? Objects.hash(getId()) : Objects.hash(getName());
}
@Override
@ -332,9 +342,9 @@ public class Vod implements Parcelable, Diffable<Vod> {
dest.writeString(this.vodPlayUrl);
dest.writeString(this.vodTag);
dest.writeString(this.action);
dest.writeInt(this.land);
dest.writeInt(this.circle);
dest.writeFloat(this.ratio);
dest.writeValue(this.land);
dest.writeValue(this.circle);
dest.writeValue(this.ratio);
dest.writeParcelable(this.cate, flags);
dest.writeParcelable(this.style, flags);
dest.writeTypedList(this.vodFlags);
@ -356,9 +366,9 @@ public class Vod implements Parcelable, Diffable<Vod> {
this.vodPlayUrl = in.readString();
this.vodTag = in.readString();
this.action = in.readString();
this.land = in.readInt();
this.circle = in.readInt();
this.ratio = in.readFloat();
this.land = (Integer) in.readValue(Integer.class.getClassLoader());
this.circle = (Integer) in.readValue(Integer.class.getClassLoader());
this.ratio = (Float) in.readValue(Float.class.getClassLoader());
this.cate = in.readParcelable(Cate.class.getClassLoader());
this.style = in.readParcelable(Style.class.getClassLoader());
this.vodFlags = in.createTypedArrayList(Flag.CREATOR);

@ -67,8 +67,8 @@ public class ExoUtil {
public static void setSubtitleView(PlayerView exo) {
exo.getSubtitleView().setStyle(getCaptionStyle());
exo.getSubtitleView().setApplyEmbeddedStyles(true);
exo.getSubtitleView().setApplyEmbeddedFontSizes(false);
exo.getSubtitleView().setApplyEmbeddedStyles(!Setting.isCaption());
if (Setting.getSubtitleTextSize() != 0) exo.getSubtitleView().setFractionalTextSize(Setting.getSubtitleTextSize());
}

@ -9,6 +9,7 @@ import com.fongmi.android.tv.bean.Config;
import com.fongmi.android.tv.bean.Device;
import com.fongmi.android.tv.bean.History;
import com.fongmi.android.tv.bean.Keep;
import com.fongmi.android.tv.bean.Vod;
import com.fongmi.android.tv.event.ActionEvent;
import com.fongmi.android.tv.event.CastEvent;
import com.fongmi.android.tv.event.RefreshEvent;
@ -81,11 +82,13 @@ public class Action implements Process {
private void onRefresh(Map<String, String> params) {
String type = params.get("type");
String path = params.get("path");
String json = params.get("json");
if ("live".equals(type)) RefreshEvent.live();
else if ("detail".equals(type)) RefreshEvent.detail();
else if ("player".equals(type)) RefreshEvent.player();
else if ("danmaku".equals(type)) RefreshEvent.danmaku(path);
else if ("subtitle".equals(type)) RefreshEvent.subtitle(path);
else if ("vod".equals(type)) RefreshEvent.vod(Vod.objectFrom(json));
}
private void onControl(Map<String, String> params) {

@ -16,7 +16,6 @@ import androidx.annotation.Nullable;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.load.model.LazyHeaders;
@ -72,7 +71,7 @@ public class ImgUtil {
if (!vod) view.setVisibility(TextUtils.isEmpty(url) ? View.GONE : View.VISIBLE);
if (TextUtils.isEmpty(url) || failed.contains(url)) view.setImageDrawable(getTextDrawable(text, vod));
else try {
RequestBuilder<Drawable> builder = Glide.with(view).load(getUrl(url)).diskCacheStrategy(DiskCacheStrategy.RESOURCE).listener(getListener(text, url, view, vod));
RequestBuilder<Drawable> builder = Glide.with(view).load(getUrl(url)).listener(getListener(text, url, view, vod));
if (vod) builder.centerCrop().into(view);
else builder.fitCenter().into(view);
} catch (Throwable e) {

@ -12,6 +12,7 @@ import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.AppGlideModule;
import com.fongmi.android.tv.BuildConfig;
import com.github.catvod.net.OkHttp;
import java.io.InputStream;
@ -21,7 +22,7 @@ public class OkGlideModule extends AppGlideModule {
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
builder.setLogLevel(Log.ERROR);
builder.setLogLevel(BuildConfig.DEBUG ? Log.DEBUG : Log.ERROR);
}
@Override

@ -120,9 +120,10 @@ public class Util {
}
public static String clean(String text) {
if (!text.contains("<")) return text;
StringBuilder sb = new StringBuilder();
text = Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY).toString().replace("\u00A0", "").replace("\u3000", "");
for (String line : text.split("\\r?\\n")) if (!line.isEmpty()) sb.append(line.trim()).append("\n");
text = Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY).toString().replace("\u00A0", " ").replace("\u3000", " ");
for (String line : text.split("\\r?\\n")) sb.append(line.trim()).append("\n");
return substring(sb.toString());
}

@ -1134,7 +1134,7 @@ public class LiveActivity extends BaseActivity implements CustomKeyDown.Listener
@Override
protected void onPause() {
super.onPause();
if (isRedirect()) onPaused();
if (isRedirect()) mPlayers.stop();
}
@Override

@ -473,31 +473,41 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
}
private void setDetail(Vod item) {
item.checkPic(getPic());
item.checkName(getName());
mBinding.progressLayout.showContent();
mBinding.video.setTag(item.getPic(getPic()));
mBinding.name.setText(item.getName(getName()));
setText(mBinding.remark, 0, item.getRemarks());
setText(mBinding.content, 0, item.getContent());
setText(mBinding.site, R.string.detail_site, getSite().getName());
setText(mBinding.actor, R.string.detail_actor, item.getActor());
setText(mBinding.director, R.string.detail_director, item.getDirector());
mBinding.contentLayout.setVisibility(mBinding.content.getVisibility());
mBinding.name.setText(item.getName());
mFlagAdapter.addAll(item.getFlags());
setOther(mBinding.other, item);
App.removeCallbacks(mR4);
checkHistory(item);
checkFlag(item);
checkKeepImg();
setText(item);
updateKeep();
}
private void setText(Vod item) {
setText(mBinding.site, R.string.detail_site, getSite().getName());
setText(mBinding.director, R.string.detail_director, item.getDirector());
setText(mBinding.actor, R.string.detail_actor, item.getActor());
setText(mBinding.content, 0, item.getContent());
setText(mBinding.remark, 0, item.getRemarks());
setOther(mBinding.other, item);
}
private void setText(TextView view, int resId, String text) {
if (TextUtils.isEmpty(text) && !TextUtils.isEmpty(view.getText())) return;
view.setText(getSpan(resId, text), TextView.BufferType.SPANNABLE);
view.setVisibility(text.isEmpty() ? View.GONE : View.VISIBLE);
if (view == mBinding.content) setContentVisible();
view.setLinkTextColor(MDColor.YELLOW_500);
CustomMovement.bind(view);
}
private void setContentVisible() {
mBinding.contentLayout.setVisibility(mBinding.content.getVisibility());
}
private SpannableStringBuilder getSpan(int resId, String text) {
if (resId > 0) text = getString(resId, text);
Map<String, String> map = new HashMap<>();
@ -548,9 +558,9 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
private void setPlayer(Result result) {
result.getUrl().set(mQualityAdapter.getPosition());
if (!result.getArtwork().isEmpty()) setArtwork(result.getArtwork());
if (result.hasArtwork()) setArtwork(result.getArtwork());
if (result.hasPosition()) mHistory.setPosition(result.getPosition());
if (!result.getDesc().isEmpty()) setText(mBinding.content, R.string.detail_content, result.getDesc());
if (result.hasDesc()) setText(mBinding.content, 0, result.getDesc());
setUseParse(VodConfig.hasParse() && ((result.getPlayUrl().isEmpty() && VodConfig.get().getFlags().contains(result.getFlag())) || result.getJx() == 1));
if (mControlDialog != null && mControlDialog.isVisible()) mControlDialog.setParseVisible(isUseParse());
mBinding.control.parse.setVisibility(isFullscreen() && isUseParse() ? View.VISIBLE : View.GONE);
@ -1001,12 +1011,14 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
App.post(mR1, Constant.INTERVAL_HIDE);
}
private void setArtwork() {
setArtwork(mHistory.getVodPic());
private void setArtwork(String url) {
mHistory.setVodPic(url);
setMetadata();
setArtwork();
}
private void setArtwork(String url) {
ImgUtil.load(this, url, new CustomTarget<>() {
private void setArtwork() {
ImgUtil.load(this, mHistory.getVodPic(), new CustomTarget<>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
mBinding.exo.setDefaultArtwork(resource);
@ -1110,16 +1122,28 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
}
private void updateVod(Vod item) {
mHistory.setVodPic(item.getPic());
mHistory.setVodName(item.getName());
mBinding.name.setText(item.getName());
mBinding.control.title.setText(item.getName());
setText(mBinding.content, 0, item.getContent());
setText(mBinding.director, R.string.detail_director, item.getDirector());
mBinding.contentLayout.setVisibility(mBinding.content.getVisibility());
updateKeep();
setArtwork();
setMetadata();
boolean id = !item.getId().isEmpty();
boolean pic = !item.getPic().isEmpty();
boolean name = !item.getName().isEmpty();
if (id) getIntent().putExtra("id", item.getId());
if (id) mHistory.setKey(getHistoryKey());
if (pic) mHistory.setVodPic(item.getPic());
if (name) mHistory.setVodName(item.getName());
if (name) mBinding.name.setText(item.getName());
if (name) mBinding.control.title.setText(item.getName());
updateFlag(getFlag(), item.getFlags());
if (pic || name) setMetadata();
if (pic || name) updateKeep();
if (pic) setArtwork();
setText(item);
}
private void updateFlag(Flag activated, List<Flag> items) {
items.forEach(item -> mFlagAdapter.getItems().stream()
.filter(item::equals).findFirst().ifPresentOrElse(target -> {
target.mergeEpisodes(item.getEpisodes(), mHistory.isRevSort());
if (target.equals(activated)) setEpisodeAdapter(target.getEpisodes());
}, () -> mFlagAdapter.add(item)));
}
@Override
@ -1434,7 +1458,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
}
public void setRotate(boolean rotate) {
this.rotate = rotate;;
this.rotate = rotate;
if (fullscreen && !rotate) setPadding(mBinding.control.getRoot());
else noPadding(mBinding.control.getRoot());
}
@ -1465,7 +1489,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
@Override
public void onCasted() {
onPaused();
mPlayers.stop();
}
@Override
@ -1631,7 +1655,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
@Override
protected void onPause() {
super.onPause();
if (isRedirect()) onPaused();
if (isRedirect()) mPlayers.stop();
}
@Override

@ -35,6 +35,11 @@ public class FlagAdapter extends RecyclerView.Adapter<FlagAdapter.ViewHolder> {
notifyDataSetChanged();
}
public void add(Flag item) {
mItems.add(item);
notifyItemInserted(mItems.size() - 1);
}
public int getPosition() {
for (int i = 0; i < mItems.size(); i++) if (mItems.get(i).isActivated()) return i;
return 0;
@ -44,6 +49,10 @@ public class FlagAdapter extends RecyclerView.Adapter<FlagAdapter.ViewHolder> {
return mItems.get(position);
}
public List<Flag> getItems() {
return mItems;
}
public Flag getActivated() {
return mItems.get(getPosition());
}

@ -11,6 +11,6 @@ tasks.register('clean', Delete) {
project.ext {
gsonVersion = '2.13.2'
glideVersion = '5.0.5'
media3Version = '1.9.0'
media3Version = '1.9.2'
okhttpVersion = '5.3.2'
}

@ -7,9 +7,6 @@ import com.github.catvod.utils.Util;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
@ -50,21 +47,13 @@ public class Crypto {
public static String rsa(String mode, boolean pub, boolean encrypt, String input, boolean inBase64, String key, boolean outBase64) {
try {
Key rsaKey = generateKey(pub, key);
int len = getModulusLength(rsaKey);
byte[] outBytes = new byte[0];
byte[] inBytes = inBase64 ? Base64.decode(input.replaceAll("_", "/").replaceAll("-", "+"), Base64.DEFAULT) : input.getBytes(StandardCharsets.UTF_8);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
String tranformation = "RSA/ECB/PKCS1Padding";
if ("RSA/PKCS1".equals(mode)) tranformation = "RSA/ECB/PKCS1Padding";
else if ("RSA/None/NoPadding".equals(mode)) tranformation = "RSA/None/NoPadding";
Cipher cipher = Cipher.getInstance(tranformation);
cipher.init(encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, rsaKey);
int blockLen = encrypt ? len / 8 - 11 : len / 8;
int bufIdx = 0;
while (bufIdx < inBytes.length) {
int bufEndIdx = Math.min(bufIdx + blockLen, inBytes.length);
byte[] tmpInBytes = new byte[bufEndIdx - bufIdx];
System.arraycopy(inBytes, bufIdx, tmpInBytes, 0, tmpInBytes.length);
byte[] tmpBytes = cipher.doFinal(tmpInBytes);
bufIdx = bufEndIdx;
outBytes = concatArrays(outBytes, tmpBytes);
}
byte[] outBytes = cipher.doFinal(inBytes);
return outBase64 ? Base64.encodeToString(outBytes, Base64.NO_WRAP) : new String(outBytes, StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
@ -77,18 +66,4 @@ public class Crypto {
else key = key.replaceAll(System.lineSeparator(), "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "");
return pub ? KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.decode(key, Base64.DEFAULT))) : KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.decode(key, Base64.DEFAULT)));
}
private static int getModulusLength(Key key) {
if (key instanceof PublicKey) return ((RSAPublicKey) key).getModulus().bitLength();
else return ((RSAPrivateKey) key).getModulus().bitLength();
}
private static byte[] concatArrays(byte[] a, byte[] b) {
int aLen = a.length;
int bLen = b.length;
byte[] result = new byte[aLen + bLen];
System.arraycopy(a, 0, result, 0, aLen);
System.arraycopy(b, 0, result, aLen, bLen);
return result;
}
}

Loading…
Cancel
Save