From e91bc3cd0831c7f5758d6389dc26f07419a7134b Mon Sep 17 00:00:00 2001 From: FongMi Date: Tue, 16 Aug 2022 13:31:04 +0800 Subject: [PATCH] Redesign parse and support parse type = 1 --- .../com/fongmi/android/tv/bean/Result.java | 10 ++ .../fongmi/android/tv/player/ParseTask.java | 108 ++++++++++++++++++ .../com/fongmi/android/tv/player/Players.java | 82 +++---------- .../android/tv/ui/custom/CustomWebView.java | 21 ++-- .../com/fongmi/android/tv/utils/Json.java | 9 ++ 5 files changed, 153 insertions(+), 77 deletions(-) create mode 100644 app/src/main/java/com/fongmi/android/tv/player/ParseTask.java diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Result.java b/app/src/main/java/com/fongmi/android/tv/bean/Result.java index c418e0210..b8c89f8f5 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Result.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Result.java @@ -4,6 +4,7 @@ import android.text.TextUtils; import androidx.annotation.NonNull; +import com.fongmi.android.tv.utils.Json; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializationContext; @@ -11,6 +12,7 @@ import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; import com.google.gson.annotations.SerializedName; import com.google.gson.reflect.TypeToken; @@ -22,8 +24,10 @@ import org.simpleframework.xml.core.Persister; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; @Root(name = "rss", strict = false) public class Result { @@ -139,6 +143,12 @@ public class Result { this.url = url; } + public Map getHeaders() { + HashMap headers = new HashMap<>(); + if (getHeader().isEmpty()) return headers; + return Json.toMap(JsonParser.parseString(getHeader())); + } + @NonNull @Override public String toString() { diff --git a/app/src/main/java/com/fongmi/android/tv/player/ParseTask.java b/app/src/main/java/com/fongmi/android/tv/player/ParseTask.java new file mode 100644 index 000000000..c5228a7ae --- /dev/null +++ b/app/src/main/java/com/fongmi/android/tv/player/ParseTask.java @@ -0,0 +1,108 @@ +package com.fongmi.android.tv.player; + +import android.os.Handler; +import android.os.Looper; + +import com.fongmi.android.tv.api.ApiConfig; +import com.fongmi.android.tv.bean.Parse; +import com.fongmi.android.tv.bean.Result; +import com.fongmi.android.tv.net.OKHttp; +import com.fongmi.android.tv.utils.Json; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import okhttp3.Headers; +import okhttp3.Response; + +public class ParseTask { + + private final Handler handler; + private ExecutorService executor; + private Callback callback; + private Parse parse; + + public static ParseTask create(Callback callback) { + return new ParseTask(callback); + } + + public ParseTask(Callback callback) { + this.executor = Executors.newSingleThreadExecutor(); + this.handler = new Handler(Looper.getMainLooper()); + this.callback = callback; + } + + public void run(Result result) { + boolean useParse = (result.getPlayUrl().isEmpty() && ApiConfig.get().getFlags().contains(result.getFlag())) || result.getJx().equals("1"); + setParse(result.getPlayUrl() + result.getUrl(), useParse); + executor.submit(this::doInBackground); + } + + private void setParse(String url, boolean useParse) { + if (useParse) parse = ApiConfig.get().getParse(); + if (url.startsWith("json:")) parse = Parse.get(1, url.substring(5)); + if (url.startsWith("parse:")) parse = ApiConfig.get().getParse(url.substring(6)); + if (parse == null) parse = Parse.get(0, url); + } + + private void doInBackground() { + switch (parse.getType()) { + case 0: //嗅探 + handler.post(() -> Players.get().web().start(parse.getUrl(), callback)); + break; + case 1: //Json + jsonParse(); + break; + case 2: //Json 擴展 + + break; + case 3: //聚合 + + break; + } + } + + private void jsonParse() { + try { + Headers headers = new Headers.Builder().build(); + if (parse.hasHeader()) headers = Headers.of(Json.toMap(parse.getHeader())); + Response response = OKHttp.newCall(parse.getUrl(), headers).execute(); + JsonObject object = JsonParser.parseString(response.body().string()).getAsJsonObject(); + HashMap header = new HashMap<>(); + for (String key : object.keySet()) if (key.equalsIgnoreCase("user-agent") || key.equalsIgnoreCase("referer")) header.put(key, object.get(key).getAsString()); + onParseSuccess(header, object.get("url").getAsString()); + } catch (Exception e) { + e.printStackTrace(); + onParseError(); + } + } + + private void onParseSuccess(Map headers, String url) { + handler.post(() -> { + if (callback != null) callback.onParseSuccess(headers, url); + }); + } + + private void onParseError() { + handler.post(() -> { + if (callback != null) callback.onParseError(); + }); + } + + public void cancel() { + if (executor != null) executor.shutdownNow(); + executor = null; + callback = null; + } + + public interface Callback { + + void onParseSuccess(Map headers, String url); + + void onParseError(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fongmi/android/tv/player/Players.java b/app/src/main/java/com/fongmi/android/tv/player/Players.java index b16cfaa5e..ccbc02e18 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/Players.java +++ b/app/src/main/java/com/fongmi/android/tv/player/Players.java @@ -4,32 +4,19 @@ import androidx.annotation.NonNull; import com.fongmi.android.tv.App; import com.fongmi.android.tv.R; -import com.fongmi.android.tv.api.ApiConfig; -import com.fongmi.android.tv.bean.Parse; import com.fongmi.android.tv.bean.Result; import com.fongmi.android.tv.event.PlayerEvent; -import com.fongmi.android.tv.net.Callback; -import com.fongmi.android.tv.net.OKHttp; import com.fongmi.android.tv.ui.custom.CustomWebView; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.util.Util; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import java.io.IOException; import java.util.Formatter; -import java.util.HashMap; import java.util.Locale; import java.util.Map; -import okhttp3.Call; -import okhttp3.Headers; -import okhttp3.Response; - -public class Players implements Player.Listener { +public class Players implements Player.Listener, ParseTask.Callback { private CustomWebView webView; private StringBuilder builder; @@ -57,6 +44,10 @@ public class Players implements Player.Listener { return exoPlayer; } + public CustomWebView web() { + return webView; + } + public String getKey() { return key; } @@ -116,58 +107,9 @@ public class Players implements Player.Listener { if (result.getUrl().isEmpty()) { PlayerEvent.error(R.string.error_play_load); } else if (result.getParse().equals("1") || result.getJx().equals("1")) { - startParse(result); + ParseTask.create(this).run(result); } else { - setMediaSource(getHeaders(result), result.getPlayUrl() + result.getUrl()); - } - } - - private HashMap getHeaders(Result result) { - HashMap headers = new HashMap<>(); - if (result.getHeader().isEmpty()) return headers; - return getHeaders(JsonParser.parseString(result.getHeader())); - } - - private HashMap getHeaders(JsonElement element) { - HashMap headers = new HashMap<>(); - if (!element.isJsonObject()) return headers; - JsonObject object = element.getAsJsonObject(); - for (String key : object.keySet()) headers.put(key, object.get(key).getAsString()); - return headers; - } - - private Parse getParse(String playUrl, boolean useParse) { - if (useParse) return ApiConfig.get().getParse(); - if (playUrl.startsWith("json:")) return Parse.get(1, playUrl.substring(5)); - if (playUrl.startsWith("parse:")) { - Parse parse = ApiConfig.get().getParse(playUrl.substring(6)); - if (parse != null) return parse; - } - return Parse.get(0, playUrl); - } - - private void startParse(Result result) { - boolean useParse = (result.getPlayUrl().isEmpty() && ApiConfig.get().getFlags().contains(result.getFlag())) || result.getJx().equals("1"); - Parse parse = getParse(result.getPlayUrl(), useParse); - if (parse.getType() == 0) { - webView.start(parse.getUrl() + result.getUrl()); - } else if (parse.getType() == 1) { - Headers headers = new Headers.Builder().build(); - if (parse.hasHeader()) headers = Headers.of(getHeaders(parse.getHeader())); - OKHttp.newCall(parse.getUrl() + result.getUrl(), headers).enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { - } - - @Override - public void onFailure(@NonNull Call call, @NonNull IOException e) { - - } - }); - } else if (parse.getType() == 2) { - - } else if (parse.getType() == 3) { - + setMediaSource(result.getHeaders(), result.getPlayUrl() + result.getUrl()); } } @@ -213,6 +155,16 @@ public class Players implements Player.Listener { } } + @Override + public void onParseSuccess(Map headers, String url) { + setMediaSource(headers, url); + } + + @Override + public void onParseError() { + PlayerEvent.error(R.string.error_play_parse); + } + @Override public void onPlayerError(@NonNull PlaybackException error) { PlayerEvent.error(R.string.error_play_format); diff --git a/app/src/main/java/com/fongmi/android/tv/ui/custom/CustomWebView.java b/app/src/main/java/com/fongmi/android/tv/ui/custom/CustomWebView.java index a2a954512..a3bc31784 100644 --- a/app/src/main/java/com/fongmi/android/tv/ui/custom/CustomWebView.java +++ b/app/src/main/java/com/fongmi/android/tv/ui/custom/CustomWebView.java @@ -15,10 +15,8 @@ import android.webkit.WebViewClient; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.fongmi.android.tv.R; import com.fongmi.android.tv.api.ApiConfig; -import com.fongmi.android.tv.event.PlayerEvent; -import com.fongmi.android.tv.player.Players; +import com.fongmi.android.tv.player.ParseTask; import com.fongmi.android.tv.utils.Utils; import java.io.ByteArrayInputStream; @@ -29,6 +27,7 @@ import java.util.Map; public class CustomWebView extends WebView { + private ParseTask.Callback callback; private WebResourceResponse empty; private List keys; private Handler handler; @@ -58,7 +57,8 @@ public class CustomWebView extends WebView { setWebViewClient(webViewClient()); } - public void start(String url) { + public void start(String url, ParseTask.Callback callback) { + this.callback = callback; stopLoading(); loadUrl(url); retry = 0; @@ -75,7 +75,7 @@ public class CustomWebView extends WebView { handler.removeCallbacks(mTimer); handler.postDelayed(mTimer, 5000); Map headers = request.getRequestHeaders(); - if (Utils.isVideoFormat(url) || headers.containsKey("Range")) post(get(headers), url); + if (Utils.isVideoFormat(url) || headers.containsKey("Range")) post(headers, url); return super.shouldInterceptRequest(view, request); } @@ -100,23 +100,20 @@ public class CustomWebView extends WebView { } }; - private Map get(Map headers) { + private void post(Map headers, String url) { Map news = new HashMap<>(); for (String key : headers.keySet()) if (keys.contains(key.toLowerCase())) news.put(key, headers.get(key)); - return news; - } - - private void post(Map headers, String url) { handler.removeCallbacks(mTimer); handler.post(() -> { + callback.onParseSuccess(news, url); stop(false); - Players.get().setMediaSource(headers, url); }); } public void stop(boolean error) { stopLoading(); loadUrl("about:blank"); - if (error) PlayerEvent.error(R.string.error_play_parse); + handler.removeCallbacks(mTimer); + if (error) handler.post(() -> callback.onParseError()); } } diff --git a/app/src/main/java/com/fongmi/android/tv/utils/Json.java b/app/src/main/java/com/fongmi/android/tv/utils/Json.java index 8948ff9be..d9d8e96e3 100644 --- a/app/src/main/java/com/fongmi/android/tv/utils/Json.java +++ b/app/src/main/java/com/fongmi/android/tv/utils/Json.java @@ -4,6 +4,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; public class Json { @@ -20,4 +21,12 @@ public class Json { else for (JsonElement opt : obj.getAsJsonArray(key)) result.add(opt.getAsString()); return result; } + + public static HashMap toMap(JsonElement element) { + HashMap map = new HashMap<>(); + if (!element.isJsonObject()) return map; + JsonObject object = element.getAsJsonObject(); + for (String key : object.keySet()) map.put(key, object.get(key).getAsString()); + return map; + } }