FongMi 1 month ago
parent 5da7900697
commit a947fa5f0d
  1. 22
      app/src/leanback/java/com/fongmi/android/tv/ui/base/BaseActivity.java
  2. 25
      app/src/main/java/com/fongmi/android/tv/api/config/BaseConfig.java
  3. 39
      app/src/main/java/com/fongmi/android/tv/api/config/LiveConfig.java
  4. 41
      app/src/main/java/com/fongmi/android/tv/api/config/VodConfig.java
  5. 10
      app/src/main/java/com/fongmi/android/tv/api/config/WallConfig.java
  6. 47
      app/src/main/java/com/fongmi/android/tv/api/loader/BaseLoader.java
  7. 17
      app/src/main/java/com/fongmi/android/tv/api/loader/JarLoader.java
  8. 3
      app/src/main/java/com/fongmi/android/tv/api/loader/JsLoader.java
  9. 3
      app/src/main/java/com/fongmi/android/tv/api/loader/PyLoader.java
  10. 21
      app/src/mobile/java/com/fongmi/android/tv/ui/base/BaseActivity.java

@ -4,12 +4,9 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
@ -30,8 +27,6 @@ import me.jessyan.autosize.AutoSizeCompat;
public abstract class BaseActivity extends AppCompatActivity {
private OnBackInvokedCallback callback;
protected abstract ViewBinding getBinding();
@Override
@ -79,16 +74,12 @@ public abstract class BaseActivity extends AppCompatActivity {
}
private void setBackCallback() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getOnBackInvokedDispatcher().registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT, callback = this::onBackInvoked);
} else {
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
onBackInvoked();
}
});
}
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
onBackInvoked();
}
});
}
private Resources hackResources(Resources resources) {
@ -129,6 +120,5 @@ public abstract class BaseActivity extends AppCompatActivity {
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(callback);
}
}

@ -9,9 +9,12 @@ import com.fongmi.android.tv.event.ConfigEvent;
import com.fongmi.android.tv.impl.Callback;
import com.fongmi.android.tv.server.Server;
import com.fongmi.android.tv.utils.Notify;
import com.github.catvod.bean.Header;
import com.github.catvod.bean.Proxy;
import com.github.catvod.net.OkHttp;
import java.io.InterruptedIOException;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
@ -22,10 +25,10 @@ abstract class BaseConfig {
public static final int WALL = 2;
private final AtomicInteger taskId = new AtomicInteger(0);
private Future<?> future;
protected Config config;
protected boolean sync;
protected Config config;
private volatile Future<?> future;
protected abstract String getTag();
@ -45,12 +48,17 @@ abstract class BaseConfig {
return config == null ? defaultConfig() : config;
}
public static String getUrl(BaseConfig instance) {
return instance.getConfig().getUrl();
protected void setHeaders(List<Header> headers) {
OkHttp.responseInterceptor().addAll(headers);
}
protected void setProxy(List<Proxy> proxy) {
OkHttp.authenticator().addAll(proxy);
OkHttp.selector().addAll(proxy);
}
public static String getDesc(BaseConfig instance) {
return instance.getConfig().getDesc();
protected void setHosts(List<String> hosts) {
OkHttp.dns().addAll(hosts);
}
public void load(Callback callback) {
@ -81,6 +89,9 @@ abstract class BaseConfig {
}
protected boolean isCanceled(Throwable e) {
return "Canceled".equals(e.getMessage()) || e instanceof InterruptedException || e instanceof InterruptedIOException || e.getCause() instanceof InterruptedIOException;
if ("Canceled".equals(e.getMessage())) return true;
if (e instanceof InterruptedException) return true;
if (e instanceof InterruptedIOException) return true;
return e.getCause() instanceof InterruptedIOException;
}
}

@ -1,5 +1,7 @@
package com.fongmi.android.tv.api.config;
import android.text.TextUtils;
import com.fongmi.android.tv.Setting;
import com.fongmi.android.tv.api.Decoder;
import com.fongmi.android.tv.api.LiveParser;
@ -17,7 +19,6 @@ import com.fongmi.android.tv.impl.Callback;
import com.fongmi.android.tv.utils.UrlUtil;
import com.github.catvod.bean.Header;
import com.github.catvod.bean.Proxy;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Json;
import com.google.gson.JsonObject;
@ -38,10 +39,6 @@ public class LiveConfig extends BaseConfig {
private List<Rule> rules;
private List<String> ads;
private static class Loader {
static volatile LiveConfig INSTANCE = new LiveConfig();
}
public static LiveConfig get() {
return Loader.INSTANCE;
}
@ -71,8 +68,7 @@ public class LiveConfig extends BaseConfig {
}
public static boolean hasUrl() {
String url = getUrl();
return url != null && !url.isEmpty();
return !TextUtils.isEmpty(getUrl());
}
public static void load(Config config, Callback callback) {
@ -147,6 +143,7 @@ public class LiveConfig extends BaseConfig {
List<Depot> items = Depot.arrayFrom(object.getAsJsonArray("urls").toString());
List<Config> configs = new ArrayList<>();
for (Depot item : items) configs.add(Config.find(item, LIVE));
if (configs.isEmpty()) throw new Exception("Depot urls is empty");
load(this.config = configs.get(0));
Config.delete(config.getUrl());
}
@ -206,8 +203,9 @@ public class LiveConfig extends BaseConfig {
}
public int[] findByChannelNumber(String number, List<Group> items) {
int num = Integer.parseInt(number);
for (int i = 0; i < items.size(); i++) {
int j = items.get(i).find(Integer.parseInt(number));
int j = items.get(i).find(num);
if (j != -1) return new int[]{i, j};
}
return new int[]{-1, -1};
@ -229,19 +227,6 @@ public class LiveConfig extends BaseConfig {
this.rules = rules;
}
private void setHeaders(List<Header> headers) {
OkHttp.responseInterceptor().addAll(headers);
}
private void setProxy(List<Proxy> proxy) {
OkHttp.authenticator().addAll(proxy);
OkHttp.selector().addAll(proxy);
}
private void setHosts(List<String> hosts) {
OkHttp.dns().addAll(hosts);
}
public List<String> getAds() {
return ads == null ? Collections.emptyList() : ads;
}
@ -254,14 +239,14 @@ public class LiveConfig extends BaseConfig {
return home == null ? new Live() : home;
}
public Live getLive(String key) {
return getLives().stream().filter(item -> item.getName().equals(key)).findFirst().orElse(new Live());
}
public void setHome(Live home) {
setHome(getConfig(), home, true);
}
public Live getLive(String key) {
return getLives().stream().filter(item -> item.getName().equals(key)).findFirst().orElse(new Live());
}
private void setHome(Config config, Live live, boolean save) {
home = live;
home.setActivated(true);
@ -270,4 +255,8 @@ public class LiveConfig extends BaseConfig {
getLives().forEach(item -> item.setActivated(home));
if (!save && (home.isBoot() || Setting.isBootLive())) ConfigEvent.boot();
}
private static class Loader {
static volatile LiveConfig INSTANCE = new LiveConfig();
}
}

@ -17,7 +17,6 @@ import com.fongmi.android.tv.utils.UrlUtil;
import com.github.catvod.bean.Doh;
import com.github.catvod.bean.Header;
import com.github.catvod.bean.Proxy;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Json;
import com.google.gson.JsonObject;
@ -42,10 +41,6 @@ public class VodConfig extends BaseConfig {
private List<String> flags;
private List<Parse> parses;
private static class Loader {
static volatile VodConfig INSTANCE = new VodConfig();
}
public static VodConfig get() {
return Loader.INSTANCE;
}
@ -133,6 +128,7 @@ public class VodConfig extends BaseConfig {
List<Depot> items = Depot.arrayFrom(object.getAsJsonArray("urls").toString());
List<Config> configs = new ArrayList<>();
for (Depot item : items) configs.add(Config.find(item, VOD));
if (configs.isEmpty()) throw new Exception("Depot urls is empty");
load(this.config = configs.get(0));
Config.delete(config.getUrl());
}
@ -233,15 +229,6 @@ public class VodConfig extends BaseConfig {
return filter.isEmpty() ? items : filter;
}
private void setHeaders(List<Header> headers) {
OkHttp.responseInterceptor().addAll(headers);
}
private void setProxy(List<Proxy> proxy) {
OkHttp.authenticator().addAll(proxy);
OkHttp.selector().addAll(proxy);
}
public List<String> getFlags() {
return flags == null ? Collections.emptyList() : flags;
}
@ -250,10 +237,6 @@ public class VodConfig extends BaseConfig {
this.flags = flags;
}
private void setHosts(List<String> hosts) {
OkHttp.dns().addAll(hosts);
}
public List<String> getAds() {
return ads == null ? Collections.emptyList() : ads;
}
@ -266,10 +249,19 @@ public class VodConfig extends BaseConfig {
return parse == null ? new Parse() : parse;
}
public void setParse(Parse parse) {
setParse(getConfig(), parse, true);
}
public Site getHome() {
return home == null ? new Site() : home;
}
public void setHome(Site site) {
setHome(getConfig(), site, true);
RefreshEvent.home();
}
public String getWall() {
return TextUtils.isEmpty(wall) ? "" : wall;
}
@ -282,10 +274,6 @@ public class VodConfig extends BaseConfig {
return getSites().stream().filter(item -> item.getKey().equals(key)).findFirst().orElse(new Site());
}
public void setParse(Parse parse) {
setParse(getConfig(), parse, true);
}
private void setParse(Config config, Parse parse, boolean save) {
this.parse = parse;
this.parse.setActivated(true);
@ -294,11 +282,6 @@ public class VodConfig extends BaseConfig {
if (save) config.save();
}
public void setHome(Site site) {
setHome(getConfig(), site, true);
RefreshEvent.home();
}
private void setHome(Config config, Site site, boolean save) {
home = site;
home.setActivated(true);
@ -306,4 +289,8 @@ public class VodConfig extends BaseConfig {
if (save) config.save();
getSites().forEach(item -> item.setActivated(home));
}
private static class Loader {
static volatile VodConfig INSTANCE = new VodConfig();
}
}

@ -25,10 +25,6 @@ public class WallConfig extends BaseConfig {
private static final String TAG = WallConfig.class.getSimpleName();
private static class Loader {
static volatile WallConfig INSTANCE = new WallConfig();
}
public static WallConfig get() {
return Loader.INSTANCE;
}
@ -101,6 +97,8 @@ public class WallConfig extends BaseConfig {
Bitmap bitmap = Glide.with(App.get()).asBitmap().frame(0).load(file).override(ResUtil.getScreenWidth(), ResUtil.getScreenHeight()).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).submit().get();
try (FileOutputStream fos = new FileOutputStream(FileUtil.getWallCache())) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} finally {
bitmap.recycle();
}
}
@ -123,4 +121,8 @@ public class WallConfig extends BaseConfig {
return false;
}
}
private static class Loader {
static volatile WallConfig INSTANCE = new WallConfig();
}
}

@ -25,18 +25,26 @@ public class BaseLoader {
private final PyLoader pyLoader;
private final JsLoader jsLoader;
private static class Loader {
static volatile BaseLoader INSTANCE = new BaseLoader();
private BaseLoader() {
jarLoader = new JarLoader();
pyLoader = new PyLoader();
jsLoader = new JsLoader();
}
public static BaseLoader get() {
return Loader.INSTANCE;
}
private BaseLoader() {
jarLoader = new JarLoader();
pyLoader = new PyLoader();
jsLoader = new JsLoader();
private static boolean isJs(String api) {
return api.contains(".js");
}
private static boolean isPy(String api) {
return api.contains(".py");
}
private static boolean isCsp(String api) {
return api.startsWith("csp_");
}
public void clear() {
@ -48,12 +56,9 @@ public class BaseLoader {
}
public Spider getSpider(String key, String api, String ext, String jar) {
boolean js = api.contains(".js");
boolean py = api.contains(".py");
boolean csp = api.startsWith("csp_");
if (py) return pyLoader.getSpider(key, api, ext);
else if (js) return jsLoader.getSpider(key, api, ext, jar);
else if (csp) return jarLoader.getSpider(key, api, ext, jar);
if (isPy(api)) return pyLoader.getSpider(key, api, ext);
else if (isJs(api)) return jsLoader.getSpider(key, api, ext, jar);
else if (isCsp(api)) return jarLoader.getSpider(key, api, ext, jar);
else return new SpiderNull();
}
@ -66,12 +71,9 @@ public class BaseLoader {
}
public void setRecent(String key, String api, String jar) {
boolean js = api.contains(".js");
boolean py = api.contains(".py");
boolean csp = api.startsWith("csp_");
if (js) jsLoader.setRecent(key);
else if (py) pyLoader.setRecent(key);
else if (csp) jarLoader.setRecent(Util.md5(jar));
if (isJs(api)) jsLoader.setRecent(key);
else if (isPy(api)) pyLoader.setRecent(key);
else if (isCsp(api)) jarLoader.setRecent(Util.md5(jar));
}
public Object[] proxy(Map<String, String> params) throws Exception {
@ -83,8 +85,9 @@ public class BaseLoader {
public void parseJar(String jar, boolean recent) {
if (TextUtils.isEmpty(jar)) return;
jarLoader.parseJar(Util.md5(jar), jar);
if (recent) jarLoader.setRecent(Util.md5(jar));
String key = Util.md5(jar);
jarLoader.parseJar(key, jar);
if (recent) jarLoader.setRecent(key);
}
public DexClassLoader dex(String jar) {
@ -98,4 +101,8 @@ public class BaseLoader {
public JSONObject jsonExtMix(String flag, String key, String name, LinkedHashMap<String, HashMap<String, String>> jxs, String url) throws Throwable {
return jarLoader.jsonExtMix(flag, key, name, jxs, url);
}
private static class Loader {
static volatile BaseLoader INSTANCE = new BaseLoader();
}
}

@ -29,7 +29,7 @@ public class JarLoader {
private final ConcurrentHashMap<String, Method> methods;
private final ConcurrentHashMap<String, Spider> spiders;
private final ConcurrentHashMap<String, Object> locks;
private String recent;
private volatile String recent;
public JarLoader() {
loaders = new ConcurrentHashMap<>();
@ -44,6 +44,7 @@ public class JarLoader {
methods.clear();
spiders.clear();
locks.clear();
recent = null;
}
public void setRecent(String recent) {
@ -117,7 +118,9 @@ public class JarLoader {
return spiders.computeIfAbsent(spKey, k -> {
try {
parseJar(jaKey, jar);
Spider spider = (Spider) loaders.get(jaKey).loadClass("com.github.catvod.spider." + api.split("csp_")[1]).newInstance();
DexClassLoader loader = loaders.get(jaKey);
if (loader == null) return new SpiderNull();
Spider spider = (Spider) loader.loadClass("com.github.catvod.spider." + api.split("csp_")[1]).newInstance();
spider.siteKey = key;
spider.init(App.get(), ext);
return spider;
@ -128,14 +131,20 @@ public class JarLoader {
});
}
private DexClassLoader requireRecentLoader() {
DexClassLoader loader = loaders.get(recent);
if (loader == null) throw new IllegalStateException("No jar loaded for recent key: " + recent);
return loader;
}
public JSONObject jsonExt(String key, LinkedHashMap<String, String> jxs, String url) throws Throwable {
Class<?> clz = loaders.get(recent).loadClass("com.github.catvod.parser.Json" + key);
Class<?> clz = requireRecentLoader().loadClass("com.github.catvod.parser.Json" + key);
Method method = clz.getMethod("parse", LinkedHashMap.class, String.class);
return (JSONObject) method.invoke(null, jxs, url);
}
public JSONObject jsonExtMix(String flag, String key, String name, LinkedHashMap<String, HashMap<String, String>> jxs, String url) throws Throwable {
Class<?> clz = loaders.get(recent).loadClass("com.github.catvod.parser.Mix" + key);
Class<?> clz = requireRecentLoader().loadClass("com.github.catvod.parser.Mix" + key);
Method method = clz.getMethod("parse", LinkedHashMap.class, String.class, String.class, String.class);
return (JSONObject) method.invoke(null, jxs, name, flag, url);
}

@ -13,7 +13,7 @@ public class JsLoader {
private final ConcurrentHashMap<String, Spider> spiders;
private final Loader loader;
private String recent;
private volatile String recent;
public JsLoader() {
spiders = new ConcurrentHashMap<>();
@ -24,6 +24,7 @@ public class JsLoader {
spiders.values().forEach(Spider::destroy);
Module.get().clear();
spiders.clear();
recent = null;
}
public void setRecent(String recent) {

@ -12,7 +12,7 @@ public class PyLoader {
private final ConcurrentHashMap<String, Spider> spiders;
private final Loader loader;
private String recent;
private volatile String recent;
public PyLoader() {
spiders = new ConcurrentHashMap<>();
@ -22,6 +22,7 @@ public class PyLoader {
public void clear() {
spiders.values().forEach(Spider::destroy);
spiders.clear();
recent = null;
}
public void setRecent(String recent) {

@ -8,8 +8,6 @@ import android.os.Bundle;
import android.view.DisplayCutout;
import android.view.View;
import android.view.ViewGroup;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import androidx.activity.EdgeToEdge;
import androidx.activity.OnBackPressedCallback;
@ -27,8 +25,6 @@ import org.greenrobot.eventbus.ThreadMode;
public abstract class BaseActivity extends AppCompatActivity {
private OnBackInvokedCallback callback;
protected abstract ViewBinding getBinding();
@Override
@ -92,16 +88,12 @@ public abstract class BaseActivity extends AppCompatActivity {
}
private void setBackCallback() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getOnBackInvokedDispatcher().registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT, callback = this::onBackInvoked);
} else {
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
onBackInvoked();
}
});
}
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
onBackInvoked();
}
});
}
private void enableEdgeToEdge() {
@ -124,6 +116,5 @@ public abstract class BaseActivity extends AppCompatActivity {
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(callback);
}
}

Loading…
Cancel
Save