From 9d38d66185622a2a406b248fdefbed02a7e5d06b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E4=BF=8A?= <215613905@qq.com> Date: Wed, 26 Mar 2025 18:01:33 +0800 Subject: [PATCH] =?UTF-8?q?=E7=8B=AC=E7=AB=8Bpy=E5=92=8Cjava=E6=89=93?= =?UTF-8?q?=E5=8C=85=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 26 ++++++++- app/proguard-python.pro | 5 ++ app/proguard-rules.pro | 8 +-- .../catvod/crawler/python/IPyLoader.java | 14 +++++ .../com/github/tvbox/osc/api/ApiConfig.java | 11 ++-- .../osc/ui/activity/LivePlayActivity.java | 13 +++-- .../com/github/catvod/crawler/pyLoader.java | 42 ++++++++++++++ .../com/github/catvod/crawler/pyLoader.java} | 57 ++++++++++--------- 8 files changed, 132 insertions(+), 44 deletions(-) create mode 100644 app/proguard-python.pro create mode 100644 app/src/main/java/com/github/catvod/crawler/python/IPyLoader.java create mode 100644 app/src/normal/java/com/github/catvod/crawler/pyLoader.java rename app/src/{main/java/com/github/catvod/crawler/PyLoader.java => python/java/com/github/catvod/crawler/pyLoader.java} (74%) diff --git a/app/build.gradle b/app/build.gradle index 60049a53..6e79a3fb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -22,9 +22,21 @@ android { exclude 'META-INF/DEPENDENCIES' } + flavorDimensions "mode" + productFlavors { + normal { + dimension "mode" + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + python { + dimension "mode" + // 配置Python打包特有的设置(如有需要) + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', 'proguard-python.pro' + } + } + buildTypes { debug { - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' minifyEnabled false ndk { @@ -32,7 +44,6 @@ android { } } release { - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' minifyEnabled true ndk { @@ -40,6 +51,14 @@ android { } } } + applicationVariants.configureEach { variant -> + variant.outputs.configureEach { output -> + def flavorNames = variant.productFlavors.collect { it.name }.join('-') + // 构建自定义文件名 + def fileName = "TVBox_${variant.buildType.name}-${flavorNames}.apk" + outputFileName = fileName + } + } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -108,7 +127,8 @@ dependencies { implementation 'com.github.hedzr:android-file-chooser:v1.2.0-final' implementation 'commons-io:commons-io:2.11.0' implementation 'com.googlecode.juniversalchardet:juniversalchardet:1.0.3' - implementation(name:'pyramid',ext:'aar') +// implementation(name:'pyramid',ext:'aar') + pythonImplementation(name:'pyramid', ext:'aar') implementation(name:'xwalk_shared_library-23.53.589.4',ext:'aar') //支持http3 implementation ('com.google.net.cronet:cronet-okhttp:0.1.0') diff --git a/app/proguard-python.pro b/app/proguard-python.pro new file mode 100644 index 00000000..45adcb7b --- /dev/null +++ b/app/proguard-python.pro @@ -0,0 +1,5 @@ +# Python支持 +-keep public class com.undcover.freedom.pyramid.** { *; } +-dontwarn com.undcover.freedom.pyramid.** +-keep public class com.chaquo.python.** { *; } +-dontwarn com.chaquo.python.** diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index c293abf1..c535ce9a 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -216,7 +216,7 @@ -keep class org.chromium.net.**{*;} # Python支持 --keep public class com.undcover.freedom.pyramid.** { *; } --dontwarn com.undcover.freedom.pyramid.** --keep public class com.chaquo.python.** { *; } --dontwarn com.chaquo.python.** +#-keep public class com.undcover.freedom.pyramid.** { *; } +#-dontwarn com.undcover.freedom.pyramid.** +#-keep public class com.chaquo.python.** { *; } +#-dontwarn com.chaquo.python.** diff --git a/app/src/main/java/com/github/catvod/crawler/python/IPyLoader.java b/app/src/main/java/com/github/catvod/crawler/python/IPyLoader.java new file mode 100644 index 00000000..5815ef55 --- /dev/null +++ b/app/src/main/java/com/github/catvod/crawler/python/IPyLoader.java @@ -0,0 +1,14 @@ +package com.github.catvod.crawler.python; + +import com.github.catvod.crawler.Spider; + +import java.util.Map; + +public interface IPyLoader { + void clear(); + void setConfig(String jsonStr); + void setRecentPyKey(String pyApi); + Spider getSpider(String key, String cls, String ext); + Object[] proxyInvoke(Map params, String key, String api, String ext); + Object[] proxyInvoke(Map params); +} \ No newline at end of file diff --git a/app/src/main/java/com/github/tvbox/osc/api/ApiConfig.java b/app/src/main/java/com/github/tvbox/osc/api/ApiConfig.java index 0fff032f..4aca702b 100644 --- a/app/src/main/java/com/github/tvbox/osc/api/ApiConfig.java +++ b/app/src/main/java/com/github/tvbox/osc/api/ApiConfig.java @@ -7,8 +7,9 @@ import android.util.Base64; import com.github.catvod.crawler.JarLoader; import com.github.catvod.crawler.JsLoader; -import com.github.catvod.crawler.PyLoader; +import com.github.catvod.crawler.pyLoader; import com.github.catvod.crawler.Spider; +import com.github.catvod.crawler.python.IPyLoader; import com.github.tvbox.osc.base.App; import com.github.tvbox.osc.bean.LiveChannelGroup; import com.github.tvbox.osc.bean.IJKCode; @@ -77,7 +78,7 @@ public class ApiConfig { private final JarLoader jarLoader = new JarLoader(); private final JsLoader jsLoader = new JsLoader(); - private final PyLoader pyLoader = new PyLoader(); + private final IPyLoader pyLoader = new pyLoader(); private final Gson gson; private final String userAgent = "okhttp/3.15"; @@ -264,7 +265,7 @@ public class ApiConfig { public void onSuccess(Response response) { try { String json = response.body(); - LOG.i("echo-ConfigJson"+json); +// LOG.i("echo-ConfigJson"+json); parseJson(apiUrl, json); FileUtils.saveCache(cache,json); callback.success(); @@ -892,7 +893,7 @@ public class ApiConfig { if (sourceBean.getApi().endsWith(".js") || sourceBean.getApi().contains(".js?")){ return jsLoader.getSpider(sourceBean.getKey(), sourceBean.getApi(), sourceBean.getExt(), sourceBean.getJar()); } - else if (sourceBean.getKey().startsWith("py_")) { + else if (sourceBean.getApi().contains(".py")) { return pyLoader.getSpider(sourceBean.getKey(), sourceBean.getApi(), sourceBean.getExt()); } else return jarLoader.getSpider(sourceBean.getKey(), sourceBean.getApi(), sourceBean.getExt(), sourceBean.getJar()); @@ -912,7 +913,7 @@ public class ApiConfig { return jarLoader.proxyInvoke(param); } }else { - if (sourceBean.getKey().startsWith("py_")) { + if (sourceBean.getApi().contains(".py")) { return pyLoader.proxyInvoke(param); }else { return jarLoader.proxyInvoke(param); diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/LivePlayActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/LivePlayActivity.java index 58a3f5f2..4199f8d9 100644 --- a/app/src/main/java/com/github/tvbox/osc/ui/activity/LivePlayActivity.java +++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/LivePlayActivity.java @@ -946,9 +946,10 @@ public class LivePlayActivity extends BaseActivity { }else if(livesOBJ.has("api")){ py_jar=livesOBJ.has("api")?livesOBJ.get("api").getAsString():""; -// String ext = livesOBJ.has("ext")?livesOBJ.get("ext").getAsJsonObject().toString():"{}"; -// LOG.i("echo-ext:"+ext); - py_jar=py_jar+"?extend="+(livesOBJ.has("ext")?livesOBJ.get("ext").getAsJsonObject().toString():"{}"); + String ext = livesOBJ.has("ext")?livesOBJ.get("ext").getAsJsonObject().toString():"{}"; + String encodedParam = URLEncoder.encode(ext); + LOG.i("echo-ext:"+ext); + py_jar=py_jar+"?extend="+(livesOBJ.has("ext")?encodedParam:"{}"); } ApiConfig.get().setLiveJar(py_jar); } @@ -1884,7 +1885,7 @@ public class LivePlayActivity extends BaseActivity { }); String sortJson = null; try { - sortJson = future.get(10, TimeUnit.SECONDS); + sortJson = future.get(6, TimeUnit.SECONDS); } catch (TimeoutException e) { e.printStackTrace(); future.cancel(true); @@ -1893,10 +1894,10 @@ public class LivePlayActivity extends BaseActivity { } finally { // 将字符串转换为 JSONObject try { + assert sortJson != null; JSONObject jsonObject = new JSONObject(sortJson); sortJson = jsonObject.getString("liveList"); } catch (JSONException e) { - Toast.makeText(App.getInstance(), "加载错误,请重试", Toast.LENGTH_SHORT).show(); JsonArray live_groups=Hawk.get(HawkConfig.LIVE_GROUP_LIST,new JsonArray()); Hawk.put(HawkConfig.LIVE_GROUP_INDEX,Hawk.get(HawkConfig.LIVE_GROUP_INDEX,0)+1); if(Hawk.get(HawkConfig.LIVE_GROUP_INDEX,0)>live_groups.size()-1){ @@ -1905,6 +1906,8 @@ public class LivePlayActivity extends BaseActivity { mHandler.post(new Runnable() { @Override public void run() { + Toast.makeText(App.getInstance(), "加载错误,请重试", Toast.LENGTH_SHORT).show(); + jumpActivity(HomeActivity.class); } }); diff --git a/app/src/normal/java/com/github/catvod/crawler/pyLoader.java b/app/src/normal/java/com/github/catvod/crawler/pyLoader.java new file mode 100644 index 00000000..415fc04a --- /dev/null +++ b/app/src/normal/java/com/github/catvod/crawler/pyLoader.java @@ -0,0 +1,42 @@ +package com.github.catvod.crawler; + +import android.util.Log; +import com.github.catvod.crawler.python.IPyLoader; + +import java.util.Map; + +public class pyLoader implements IPyLoader { + + @Override + public void clear() { + Log.i("PyLoader", "normal flavor: clear() 调用,但不支持 Python 功能。"); + } + + @Override + public void setConfig(String jsonStr) { + Log.i("PyLoader", "normal flavor: setConfig() 调用,但不支持 Python 功能。"); + } + + @Override + public void setRecentPyKey(String pyApi) { + Log.i("PyLoader", "normal flavor: setRecentPyKey() 调用,但不支持 Python 功能。"); + } + + @Override + public Spider getSpider(String key, String cls, String ext) { + Log.i("PyLoader", "normal flavor: getSpider() 调用,但不支持 Python 功能。"); + return new SpiderNull(); + } + + @Override + public Object[] proxyInvoke(Map params, String key, String api, String ext) { + Log.i("PyLoader", "normal flavor: proxyInvoke(params, key, api, ext) 调用,但不支持 Python 功能。"); + return null; + } + + @Override + public Object[] proxyInvoke(Map params) { + Log.i("PyLoader", "normal flavor: proxyInvoke(params) 调用,但不支持 Python 功能。"); + return null; + } +} diff --git a/app/src/main/java/com/github/catvod/crawler/PyLoader.java b/app/src/python/java/com/github/catvod/crawler/pyLoader.java similarity index 74% rename from app/src/main/java/com/github/catvod/crawler/PyLoader.java rename to app/src/python/java/com/github/catvod/crawler/pyLoader.java index 0028c674..ca3d6844 100644 --- a/app/src/main/java/com/github/catvod/crawler/PyLoader.java +++ b/app/src/python/java/com/github/catvod/crawler/pyLoader.java @@ -1,49 +1,56 @@ +// 文件: app/src/python/java/com/github/catvod/crawler/python/PyLoader.java package com.github.catvod.crawler; import android.util.Log; - import com.chaquo.python.PyObject; +import com.github.catvod.crawler.python.IPyLoader; import com.github.tvbox.osc.base.App; import com.github.tvbox.osc.util.LOG; import com.github.tvbox.osc.util.MD5; import com.undcover.freedom.pyramid.PythonLoader; import com.undcover.freedom.pyramid.PythonSpider; - import java.io.ByteArrayInputStream; import java.io.InputStream; import java.lang.reflect.Field; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -public class PyLoader { + +public class pyLoader implements IPyLoader { private final PythonLoader pythonLoader = PythonLoader.getInstance().setApplication(App.getInstance()); private static final ConcurrentHashMap spiders = new ConcurrentHashMap<>(); - private String lastConfig = null; // 记录上次的配置 + + @Override public void clear() { spiders.clear(); } + + @Override public void setConfig(String jsonStr) { if (jsonStr != null && !jsonStr.equals(lastConfig)) { - Log.i("PyLoader","echo-setConfig 初始化json "); + Log.i("PyLoader", "echo-setConfig 初始化json "); pythonLoader.setConfig(jsonStr); lastConfig = jsonStr; } } private String recentPyApi; + @Override public void setRecentPyKey(String pyApi) { - recentPyApi=pyApi; + recentPyApi = pyApi; } + + @Override public Spider getSpider(String key, String cls, String ext) { - if (spiders.containsKey(key)){ - Log.i("PyLoader","echo-getSpider spider缓存: " + key); + if (spiders.containsKey(key)) { + Log.i("PyLoader", "echo-getSpider spider缓存: " + key); return spiders.get(key); } try { - Spider sp = pythonLoader.getSpider(key, getPyUrl(cls,ext)); + Spider sp = pythonLoader.getSpider(key, getPyUrl(cls, ext)); spiders.put(key, sp); - Log.i("PyLoader","echo-getSpider 加载spider: " + key); + Log.i("PyLoader", "echo-getSpider 加载spider: " + key); return sp; } catch (Throwable th) { th.printStackTrace(); @@ -51,28 +58,29 @@ public class PyLoader { return new SpiderNull(); } - public Object[] proxyInvoke(Map params,String key,String api,String ext) { + @Override + public Object[] proxyInvoke(Map params, String key, String api, String ext) { try { String doStr = params.get("do"); assert doStr != null; - if (doStr.equals("ck") || doStr.equals("live"))return pythonLoader.proxyLocal("", "", params); - return (Object[]) pythonLoader.proxyLocal(key, getPyUrl(api,ext), params); + if (doStr.equals("ck") || doStr.equals("live")) + return pythonLoader.proxyLocal("", "", params); + return (Object[]) pythonLoader.proxyLocal(key, getPyUrl(api, ext), params); } catch (Throwable th) { th.printStackTrace(); } return null; } - public Object[] proxyInvoke(Map params) { + @Override + public Object[] proxyInvoke(Map params) { try { - LOG.i("echo-recentPyApi"+recentPyApi); -// return (Object[])pythonLoader.proxyLocal(MD5.string2MD5(recentPyApi), recentPyApi, params); + LOG.i("echo-recentPyApi" + recentPyApi); PythonSpider originalSpider = (PythonSpider) pythonLoader.getSpider(MD5.string2MD5(recentPyApi), recentPyApi); PythonSpiderWrapper wrapper = new PythonSpiderWrapper(originalSpider); - // LOG.i("echo-list:---"+wrapper.liveContent(recentPyApi)); return wrapper.proxyLocal(params); } catch (Throwable th) { - LOG.i("echo-Throwable:---"+th.getMessage()); + LOG.i("echo-Throwable:---" + th.getMessage()); th.printStackTrace(); } return null; @@ -85,14 +93,14 @@ public class PyLoader { this.spider = spider; } - public Object[] proxyLocal(Map param) { + public Object[] proxyLocal(Map param) { try { - // 使用反射获取私有字段 app + // 反射获取私有字段 app Field appField = PythonSpider.class.getDeclaredField("app"); appField.setAccessible(true); PyObject app = (PyObject) appField.get(spider); - // 使用反射获取私有字段 pySpider + // 反射获取私有字段 pySpider Field pySpiderField = PythonSpider.class.getDeclaredField("pySpider"); pySpiderField.setAccessible(true); PyObject pySpider = (PyObject) pySpiderField.get(spider); @@ -101,18 +109,14 @@ public class PyLoader { assert app != null; List poList = app.callAttr("localProxy", new Object[]{pySpider, spider.map2json(param).toString()}).asList(); - // 提取前三个元素 int code = poList.get(0).toInt(); String type = poList.get(1).toString(); String action = poList.get(2).toString(); -// LOG.i("echo-action:---"+action); InputStream stream = new ByteArrayInputStream(action.getBytes("utf8")); - // 如果存在第四个元素,则将其转换为 Map,否则设为 null Object extra = null; if (poList.size() > 3) { extra = poList.get(3).toJava(Map.class); } - return new Object[]{code, type, stream, extra}; } catch (Exception e) { e.printStackTrace(); @@ -121,8 +125,7 @@ public class PyLoader { } } - private String getPyUrl(String api,String ext) - { + private String getPyUrl(String api, String ext) { StringBuilder urlBuilder = new StringBuilder(api); if (!ext.isEmpty()) { urlBuilder.append(api.contains("?") ? "&" : "?").append("extend=").append(ext);