独立py和java打包版本

pull/144/head
于俊 1 year ago
parent 611bf5dbc8
commit 9d38d66185
  1. 26
      app/build.gradle
  2. 5
      app/proguard-python.pro
  3. 8
      app/proguard-rules.pro
  4. 14
      app/src/main/java/com/github/catvod/crawler/python/IPyLoader.java
  5. 11
      app/src/main/java/com/github/tvbox/osc/api/ApiConfig.java
  6. 13
      app/src/main/java/com/github/tvbox/osc/ui/activity/LivePlayActivity.java
  7. 42
      app/src/normal/java/com/github/catvod/crawler/pyLoader.java
  8. 57
      app/src/python/java/com/github/catvod/crawler/pyLoader.java

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

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

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

@ -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<String, String> params, String key, String api, String ext);
Object[] proxyInvoke(Map<String, String> params);
}

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

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

@ -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<String, String> 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<String, String> params) {
Log.i("PyLoader", "normal flavor: proxyInvoke(params) 调用,但不支持 Python 功能。");
return null;
}
}

@ -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<String, Spider> 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<String,String> params,String key,String api,String ext) {
@Override
public Object[] proxyInvoke(Map<String, String> 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<String,String> params) {
@Override
public Object[] proxyInvoke(Map<String, String> 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<String,String> param) {
public Object[] proxyLocal(Map<String, String> 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<PyObject> 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);
Loading…
Cancel
Save