playContent 接口补齐 json 解析支持 已测试XB XP SP

pull/1/head
Cuke 4 years ago
parent 608bc24c5b
commit c6ee7d7429
  1. 1
      app/src/main/java/com/github/tvbox/osc/ui/activity/LivePlayActivity.java
  2. 68
      app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java
  3. 4
      app/src/main/java/com/github/tvbox/osc/ui/activity/ProjectionPlayActivity.java
  4. 189
      app/src/main/java/com/github/tvbox/osc/ui/dialog/ParseDialog.java
  5. 27
      app/src/main/java/com/github/tvbox/osc/util/DefaultConfig.java
  6. 49
      app/src/main/java/com/github/tvbox/osc/viewmodel/SourceViewModel.java
  7. 2
      app/src/main/res/layout/activity_play.xml

@ -247,6 +247,7 @@ public class LivePlayActivity extends BaseActivity {
}
});
} else {
showSuccess();
initList(list);
}
}

@ -5,6 +5,9 @@ import android.os.Bundle;
import android.view.KeyEvent;
import android.widget.Toast;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import com.dueeeke.videocontroller.component.GestureView;
import com.dueeeke.videoplayer.player.VideoView;
import com.github.tvbox.osc.R;
@ -16,9 +19,11 @@ import com.github.tvbox.osc.player.controller.BoxVodControlView;
import com.github.tvbox.osc.ui.dialog.ParseDialog;
import com.github.tvbox.osc.util.HawkConfig;
import com.github.tvbox.osc.util.PlayerHelper;
import com.github.tvbox.osc.viewmodel.SourceViewModel;
import com.orhanobut.hawk.Hawk;
import org.greenrobot.eventbus.EventBus;
import org.json.JSONObject;
import java.util.Map;
@ -30,6 +35,7 @@ import java.util.Map;
public class PlayActivity extends BaseActivity {
private VideoView mVideoView;
private BoxVideoController controller;
private SourceViewModel sourceViewModel;
@Override
protected int getLayoutResID() {
@ -39,10 +45,12 @@ public class PlayActivity extends BaseActivity {
@Override
protected void init() {
initView();
initViewModel();
initData();
}
private void initView() {
setLoadSir(findViewById(R.id.rootLayout));
mVideoView = findViewById(R.id.mVideoView);
PlayerHelper.updateCfg(mVideoView);
// ViewGroup.LayoutParams layoutParams = mVideoView.getLayoutParams();
@ -96,6 +104,39 @@ public class PlayActivity extends BaseActivity {
mVideoView.setVideoController(controller);
}
private void initViewModel() {
sourceViewModel = new ViewModelProvider(this).get(SourceViewModel.class);
sourceViewModel.playResult.observe(this, new Observer<JSONObject>() {
@Override
public void onChanged(JSONObject object) {
showSuccess();
if (object != null && object.optString("key", "").equals(parseKey)) {
parseDialog.parse(sourceKey, object, new ParseDialog.ParseCallback() {
@Override
public void success(String playUrl, Map<String, String> headers) {
if (mVideoView != null) {
mVideoView.release();
if (headers != null) {
mVideoView.setUrl(playUrl, headers);
} else {
mVideoView.setUrl(playUrl);
}
mVideoView.start();
}
tryDismissParse();
}
@Override
public void fail() {
// PlayActivity.this.finish();
// tryDismissParse();
}
});
}
}
});
}
private void initData() {
Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
@ -216,6 +257,9 @@ public class PlayActivity extends BaseActivity {
}
}
private volatile String parseKey = null;
public void play() {
VodInfo.VodSeries vs = mVodInfo.seriesMap.get(mVodInfo.playFlag).get(mVodInfo.playIndex);
EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_REFRESH, mVodInfo.playIndex));
@ -233,26 +277,8 @@ public class PlayActivity extends BaseActivity {
parseDialog.show();
parseDialog.parse(sourceKey, mVodInfo.playFlag, vs.url, new ParseDialog.ParseCallback() {
@Override
public void success(String playUrl, Map<String, String> headers) {
if (mVideoView != null) {
mVideoView.release();
if (headers != null) {
mVideoView.setUrl(playUrl, headers);
} else {
mVideoView.setUrl(playUrl);
}
mVideoView.start();
}
tryDismissParse();
}
@Override
public void fail() {
PlayActivity.this.finish();
tryDismissParse();
}
});
parseKey = vs.url;
showLoading();
sourceViewModel.getPlay(sourceKey, mVodInfo.playFlag, vs.url);
}
}

@ -113,7 +113,7 @@ public class ProjectionPlayActivity extends BaseActivity {
parseDialog.show();
parseDialog.parse("", "", html, new ParseDialog.ParseCallback() {
/* parseDialog.parse("", "", html, new ParseDialog.ParseCallback() {
@Override
public void success(String playUrl, Map<String, String> headers) {
controller.boxTVRefreshInfo(playUrl);
@ -130,7 +130,7 @@ public class ProjectionPlayActivity extends BaseActivity {
ProjectionPlayActivity.this.finish();
tryDismissParse();
}
});
});*/
}
}

@ -4,11 +4,9 @@ import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.os.Handler;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@ -33,7 +31,6 @@ import com.chad.library.adapter.base.BaseQuickAdapter;
import com.github.tvbox.osc.R;
import com.github.tvbox.osc.api.ApiConfig;
import com.github.tvbox.osc.bean.ParseBean;
import com.github.tvbox.osc.bean.SourceBean;
import com.github.tvbox.osc.ui.adapter.ParseDialogAdapter;
import com.github.tvbox.osc.util.AdBlocker;
import com.github.tvbox.osc.util.DefaultConfig;
@ -42,10 +39,14 @@ import com.github.tvbox.osc.util.HawkConfig;
import com.github.tvbox.osc.util.LOG;
import com.github.tvbox.osc.util.XWalkUtils;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.AbsCallback;
import com.lzy.okgo.model.Response;
import com.orhanobut.hawk.Hawk;
import com.owen.tvrecyclerview.widget.TvRecyclerView;
import com.owen.tvrecyclerview.widget.V7GridLayoutManager;
import org.json.JSONException;
import org.json.JSONObject;
import org.xwalk.core.XWalkResourceClient;
import org.xwalk.core.XWalkSettings;
import org.xwalk.core.XWalkUIClient;
@ -56,6 +57,7 @@ import org.xwalk.core.XWalkWebResourceResponse;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -84,6 +86,7 @@ public class ParseDialog {
private Runnable mParseTimeOut = new Runnable() {
@Override
public void run() {
OkGo.getInstance().cancelTag("json_jx");
Toast.makeText(mContext, "解析超时,请尝试切换解析重试!", Toast.LENGTH_SHORT).show();
}
};
@ -152,15 +155,37 @@ public class ParseDialog {
void fail();
}
public void parse(String sourceKey, String flag, String url, ParseCallback callback) {
Uri uir = Uri.parse(url);
String urlPath = uir.getPath();
String format = DefaultConfig.getFileSuffix(urlPath);
SourceBean sb = ApiConfig.get().getSource(sourceKey);
if (DefaultConfig.isVideoFormat(format)) {
callback.success(url, null);
} else { // 解析咯
initParse(sourceKey, flag, url, callback);
public void parse(String sourceKey, JSONObject info, ParseCallback callback) {
try {
boolean parse = info.optString("parse", "1").equals("1");
boolean jx = info.optString("jx", "0").equals("1");
String playUrl = info.optString("playUrl", "");
String flag = info.optString("flag");
String url = info.getString("url");
HashMap<String, String> headers = null;
if (info.has("header")) {
try {
JSONObject hds = new JSONObject(info.getString("header"));
Iterator<String> keys = hds.keys();
while (keys.hasNext()) {
String key = keys.next();
if (headers == null) {
headers = new HashMap<>();
}
headers.put(key, hds.getString(key));
}
} catch (Throwable th) {
}
}
if (parse || jx) {
boolean userJxList = (playUrl.isEmpty() && ApiConfig.get().getVipParseFlags().contains(flag)) || jx;
initParse(flag, userJxList, playUrl, url, callback);
} else {
callback.success(playUrl + url, headers);
}
} catch (Throwable th) {
callback.fail();
}
}
@ -169,7 +194,7 @@ public class ParseDialog {
private WebView mSysWebView;
private SysWebClient mSysWebClient;
private void initParse(String sourceKey, String flag, String url, ParseCallback callback) {
private void initParse(String flag, boolean userJx, String playUrl, String url, ParseCallback callback) {
mParseTip.setText("资源解析中,请稍后");
if (mSysWebView == null && mX5WebView == null) {
boolean useSystemWebView = Hawk.get(HawkConfig.PARSE_WEBVIEW, true);
@ -178,29 +203,29 @@ public class ParseDialog {
@Override
public void success() {
initWebView(false);
initParseBean(sourceKey, flag, url, callback);
initParseBean(flag, userJx, playUrl, url, callback);
}
@Override
public void fail() {
Toast.makeText(mContext, "XWalkView不兼容,已替换为系统自带WebView", Toast.LENGTH_LONG).show();
initWebView(true);
initParseBean(sourceKey, flag, url, callback);
initParseBean(flag, userJx, playUrl, url, callback);
}
@Override
public void ignore() {
Toast.makeText(mContext, "XWalkView运行组件未下载,已替换为系统自带WebView", Toast.LENGTH_LONG).show();
initWebView(true);
initParseBean(sourceKey, flag, url, callback);
initParseBean(flag, userJx, playUrl, url, callback);
}
});
} else {
initWebView(true);
initParseBean(sourceKey, flag, url, callback);
initParseBean(flag, userJx, playUrl, url, callback);
}
} else {
initParseBean(sourceKey, flag, url, callback);
initParseBean(flag, userJx, playUrl, url, callback);
}
}
@ -214,29 +239,107 @@ public class ParseDialog {
}
}
private void loadUrl(String url, ParseCallback callback) {
if (mSysWebClient != null) {
mSysWebClient.setCallback(callback);
}
if (mX5WebClient != null) {
mX5WebClient.setCallback(callback);
}
if (mX5WebView != null) {
mX5WebView.stopLoading();
mX5WebView.clearCache(true);
mX5WebView.loadUrl(url);
}
if (mSysWebView != null) {
mSysWebView.stopLoading();
mSysWebView.clearCache(true);
mSysWebView.loadUrl(url);
JSONObject jsonParse(String input, String json) throws JSONException {
JSONObject jsonPlayData = new JSONObject(json);
String url = jsonPlayData.getString("url");
String msg = jsonPlayData.optString("msg", "");
if (url.startsWith("//")) {
url = "https:" + url;
}
if (!url.startsWith("http")) {
return null;
}
JSONObject headers = new JSONObject();
String ua = jsonPlayData.optString("user-agent", "");
if (ua.trim().length() > 0) {
headers.put("User-Agent", " " + ua);
}
String referer = jsonPlayData.optString("referer", "");
if (referer.trim().length() > 0) {
headers.put("Referer", " " + referer);
}
JSONObject taskResult = new JSONObject();
taskResult.put("header", headers);
taskResult.put("url", url);
return taskResult;
}
private void doJsonJx(String jx, String url, ParseCallback callback) {
OkGo.<String>get(jx + url)
.tag("json_jx")
.execute(new AbsCallback<String>() {
@Override
public String convertResponse(okhttp3.Response response) throws Throwable {
if (response.body() != null) {
return response.body().string();
} else {
throw new IllegalStateException("网络请求错误");
}
}
@Override
public void onSuccess(Response<String> response) {
String json = response.body();
try {
JSONObject rs = jsonParse(url, json);
HashMap<String, String> headers = null;
if (rs.has("header")) {
try {
JSONObject hds = rs.getJSONObject("header");
Iterator<String> keys = hds.keys();
while (keys.hasNext()) {
String key = keys.next();
if (headers == null) {
headers = new HashMap<>();
}
headers.put(key, hds.getString(key));
}
} catch (Throwable th) {
}
}
callback.success(rs.getString("url"), headers);
} catch (JSONException e) {
e.printStackTrace();
callback.fail();
}
}
@Override
public void onError(Response<String> response) {
super.onError(response);
callback.fail();
}
});
}
private void loadUrl(ParseBean pb, String url, ParseCallback callback) {
if (pb == null || pb.getType() == 0) {
if (mSysWebClient != null) {
mSysWebClient.setCallback(callback);
}
if (mX5WebClient != null) {
mX5WebClient.setCallback(callback);
}
if (mX5WebView != null) {
mX5WebView.stopLoading();
mX5WebView.clearCache(true);
mX5WebView.loadUrl(url);
}
if (mSysWebView != null) {
mSysWebView.stopLoading();
mSysWebView.clearCache(true);
mSysWebView.loadUrl(url);
}
} else if (pb.getType() == 1) { // json 解析
doJsonJx(pb.getUrl(), url, callback);
}
mHandler.removeCallbacks(mParseTimeOut);
mHandler.postDelayed(mGridFocus, 200);
mHandler.postDelayed(mParseTimeOut, 30000);
}
private void initParseBean(String sourceKey, String flag, final String url, ParseCallback callback) {
private void initParseBean(String flag, boolean userJx, String playUrl, final String url, ParseCallback callback) {
if (mGridView == null) {
mGridView = findViewById(R.id.mGridView);
parseAdapter = new ParseDialogAdapter();
@ -253,7 +356,7 @@ public class ParseDialog {
ApiConfig.get().setDefaultParse(parseBean);
parseAdapter.notifyItemChanged(position);
loadFound = false;
loadUrl(parseBean.getUrl() + url, callback);
loadUrl(parseBean, url, callback);
}
});
mGridView.setOnInBorderKeyEventListener(new TvRecyclerView.OnInBorderKeyEventListener() {
@ -264,30 +367,30 @@ public class ParseDialog {
});
}
int focusParseIdx = 0;
SourceBean sb = ApiConfig.get().getSource(sourceKey);
String parseUrl = "";
if (ApiConfig.get().getVipParseFlags().contains(flag) || TextUtils.isEmpty(flag)) {
ParseBean parseBean = null;
if (userJx) {
parseBeans.addAll(ApiConfig.get().getParseBeanList());
ParseBean parseBean = ApiConfig.get().getDefaultParse();
parseBean = ApiConfig.get().getDefaultParse();
parseUrl = parseBean.getUrl();
focusParseIdx = parseBeans.indexOf(parseBean);
} else {
parseUrl = sb == null ? "" : sb.getPlayerUrl();
parseUrl = playUrl;
focusParseIdx = 0;
}
loadFound = false;
parseAdapter.setNewData(parseBeans);
mGridView.setSelection(focusParseIdx);
final String fullParseUrl = parseUrl + url;
if (parseBeans.size() > 0) {
ParseBean finalParseBean = parseBean;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
loadUrl(fullParseUrl, callback);
loadUrl(finalParseBean, url, callback);
}
}, 3000);
} else {
loadUrl(fullParseUrl, callback);
loadUrl(null, parseUrl + url, callback);
}
}

@ -14,11 +14,10 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
/**
* @author pj567
@ -96,30 +95,22 @@ public class DefaultConfig {
return start > -1 ? fileName.substring(0, start) : fileName;
}
public static boolean isVideoFormat(String urlOri) {
String url = urlOri.toLowerCase();
private static final Pattern snifferMatch = Pattern.compile("http((?!http).){26,}?\\.(m3u8|mp4)\\?.*|http((?!http).){26,}\\.(m3u8|mp4)|http((?!http).){26,}?/m3u8\\?pt=m3u8.*|http((?!http).)*?default\\.ixigua\\.com/.*|http((?!http).)*?cdn-tos[^\\?]*|http((?!http).)*?/obj/tos[^\\?]*|http.*?/player/m3u8play\\.php\\?url=.*|http.*?/player/.*?[pP]lay\\.php\\?url=.*|http.*?/playlist/m3u8/\\?vid=.*|http.*?\\.php\\?type=m3u8&.*|http.*?/download.aspx\\?.*|http.*?/api/up_api.php\\?.*|https.*?\\.66yk\\.cn.*|http((?!http).)*?netease\\.com/file/.*");
public static boolean isVideoFormat(String url) {
if (url.contains("=http") || url.contains("=https") || url.contains("=https%3a%2f") || url.contains("=http%3a%2f")) {
return false;
}
Iterator<String> keys = videoFormatList.keySet().iterator();
while (keys.hasNext()) {
String format = keys.next();
if (url.contains(format)) {
LOG.i("isVideoFormat url:" + urlOri);
return true;
if (snifferMatch.matcher(url).find()) {
if (url.contains("cdn-tos") && (url.contains(".js") || url.contains(".css"))) {
return false;
}
return true;
}
return false;
}
private static final HashMap videoFormatList = new HashMap<String, List<String>>() {{
put(".m3u8", Arrays.asList("application/octet-stream", "application/vnd.apple.mpegurl", "application/mpegurl", "application/x-mpegurl", "audio/mpegurl", "audio/x-mpegurl"));
put(".mp4", Arrays.asList("video/mp4", "application/mp4", "video/h264"));
put(".flv", Arrays.asList("video/x-flv"));
put(".f4v", Arrays.asList("video/x-f4v"));
put(".mpeg", Arrays.asList("video/vnd.mpegurl"));
}};
public static String safeJsonString(JsonObject obj, String key, String defaultVal) {
try {

@ -12,6 +12,7 @@ import com.github.tvbox.osc.bean.AbsXml;
import com.github.tvbox.osc.bean.Movie;
import com.github.tvbox.osc.bean.SourceBean;
import com.github.tvbox.osc.event.RefreshEvent;
import com.github.tvbox.osc.util.DefaultConfig;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lzy.okgo.OkGo;
@ -21,6 +22,7 @@ import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import org.greenrobot.eventbus.EventBus;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
@ -39,6 +41,7 @@ public class SourceViewModel extends ViewModel {
public MutableLiveData<AbsXml> searchResult;
public MutableLiveData<AbsXml> quickSearchResult;
public MutableLiveData<AbsXml> detailResult;
public MutableLiveData<JSONObject> playResult;
public SourceViewModel() {
sortResult = new MutableLiveData<>();
@ -46,6 +49,7 @@ public class SourceViewModel extends ViewModel {
searchResult = new MutableLiveData<>();
quickSearchResult = new MutableLiveData<>();
detailResult = new MutableLiveData<>();
playResult = new MutableLiveData<>();
}
public static final ExecutorService spThreadPool = Executors.newFixedThreadPool(3);
@ -295,6 +299,51 @@ public class SourceViewModel extends ViewModel {
}
}
public void getPlay(String sourceKey, String playFlag, String url) {
SourceBean sourceBean = ApiConfig.get().getSource(sourceKey);
int type = sourceBean.getType();
if (type == 3) {
spThreadPool.execute(new Runnable() {
@Override
public void run() {
Spider sp = ApiConfig.get().getCSP(sourceBean);
String json = sp.playerContent(playFlag, url, ApiConfig.get().getVipParseFlags());
try {
JSONObject result = new JSONObject(json);
result.put("key", url);
if (!result.has("flag"))
result.put("flag", playFlag);
playResult.postValue(result);
} catch (Throwable th) {
th.printStackTrace();
playResult.postValue(null);
}
}
});
} else if (type == 0 || type == 1) {
JSONObject result = new JSONObject();
try {
result.put("key", url);
String playUrl = sourceBean.getPlayerUrl().trim();
if (DefaultConfig.isVideoFormat(url)) {
result.put("parse", 0);
result.put("url", url);
} else {
result.put("parse", 1);
result.put("url", url);
}
result.put("playUrl", playUrl);
result.put("flag", playFlag);
playResult.postValue(result);
} catch (Throwable th) {
th.printStackTrace();
playResult.postValue(null);
}
} else {
quickSearchResult.postValue(null);
}
}
private void sortJson(MutableLiveData<AbsSortXml> result, String json) {
try {
AbsSortJson sortJson = new Gson().fromJson(json, new TypeToken<AbsSortJson>() {

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout android:id="@+id/rootLayout" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

Loading…
Cancel
Save