diff --git a/app/libs/hook-release.aar b/app/libs/hook-release.aar index 976bdca94..179856a41 100644 Binary files a/app/libs/hook-release.aar and b/app/libs/hook-release.aar differ diff --git a/app/src/main/java/com/fongmi/android/tv/App.java b/app/src/main/java/com/fongmi/android/tv/App.java index 20b8b564e..1834079c7 100644 --- a/app/src/main/java/com/fongmi/android/tv/App.java +++ b/app/src/main/java/com/fongmi/android/tv/App.java @@ -13,6 +13,7 @@ import androidx.annotation.Nullable; import androidx.core.os.HandlerCompat; import com.fongmi.android.tv.utils.Notify; +import com.fongmi.android.tv.utils.WebViewUtil; import com.fongmi.hook.Chromium; import com.fongmi.hook.Hook; import com.github.catvod.Init; @@ -72,7 +73,7 @@ public class App extends Application implements Application.ActivityLifecycleCal @Override public String getPackageName() { - return hook != null ? hook.getPackageName() : sniff && Chromium.find() ? Chromium.spoofedPackageName(this) : getBaseContext().getPackageName(); + return hook != null ? hook.getPackageName() : sniff && Chromium.find() ? WebViewUtil.spoof() : getBaseContext().getPackageName(); } @Override diff --git a/app/src/main/java/com/fongmi/android/tv/api/EpgParser.java b/app/src/main/java/com/fongmi/android/tv/api/EpgParser.java index a7a7b1060..e7006346f 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/EpgParser.java +++ b/app/src/main/java/com/fongmi/android/tv/api/EpgParser.java @@ -9,6 +9,7 @@ import com.fongmi.android.tv.bean.Live; import com.fongmi.android.tv.bean.Tv; import com.fongmi.android.tv.utils.Download; import com.fongmi.android.tv.utils.FileUtil; +import com.fongmi.android.tv.utils.Util; import com.github.catvod.utils.Path; import com.github.catvod.utils.Trans; @@ -43,7 +44,7 @@ public class EpgParser { public static Epg getEpg(String xml, String key) throws Exception { Tv tv = new Persister().read(Tv.class, xml, false); - Epg epg = Epg.create(key, formatDate.format(parse(formatFull, tv.getDate()))); + Epg epg = Epg.create(key, formatDate.format(Util.parse(formatFull, tv.getDate()))); tv.getProgramme().forEach(programme -> epg.getList().add(getEpgData(programme))); return epg; } @@ -91,10 +92,10 @@ public class EpgParser { String xmlChannelId = programme.getChannel(); Channel targetChannel = findTargetChannel(xmlChannelId, liveChannelMap, data.map); if (targetChannel == null) continue; - Date startDate = parse(formatFull, programme.getStart()); + Date startDate = Util.parse(formatFull, programme.getStart()); if (!isToday(startDate.getTime())) continue; String liveTvgId = targetChannel.getTvgId(); - Date endDate = parse(formatFull, programme.getStop()); + Date endDate = Util.parse(formatFull, programme.getStop()); epgMap.computeIfAbsent(liveTvgId, key -> Epg.create(key, today)).getList().add(getEpgData(startDate, endDate, programme)); Optional.ofNullable(data.map.get(xmlChannelId)).filter(Tv.Channel::hasSrc).ifPresent(ch -> srcMap.putIfAbsent(liveTvgId, ch.getSrc())); } @@ -120,8 +121,8 @@ public class EpgParser { } private static EpgData getEpgData(Tv.Programme programme) { - Date startDate = parse(formatFull, programme.getStart()); - Date endDate = parse(formatFull, programme.getStop()); + Date startDate = Util.parse(formatFull, programme.getStart()); + Date endDate = Util.parse(formatFull, programme.getStop()); return getEpgData(startDate, endDate, programme); } @@ -139,14 +140,6 @@ public class EpgParser { } } - private static Date parse(SimpleDateFormat format, String source) { - try { - return format.parse(source); - } catch (Exception e) { - return new Date(0); - } - } - private static class XmlData { Tv tv; diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Epg.java b/app/src/main/java/com/fongmi/android/tv/bean/Epg.java index 89d748118..dd14e4d6c 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Epg.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Epg.java @@ -81,8 +81,8 @@ public class Epg { private void setTime(List formats) { setList(new ArrayList<>(new LinkedHashSet<>(getList()))); for (EpgData item : getList()) { - item.setStartTime(Util.format(getDate().concat(item.getStart()), formats)); - item.setEndTime(Util.format(getDate().concat(item.getEnd()), formats)); + item.setStartTime(Util.parse(formats, getDate().concat(item.getStart()))); + item.setEndTime(Util.parse(formats, getDate().concat(item.getEnd()))); if (item.getEndTime() < item.getStartTime()) item.checkDay(); item.setTitle(Trans.s2t(item.getTitle())); } diff --git a/app/src/main/java/com/fongmi/android/tv/player/ParseJob.java b/app/src/main/java/com/fongmi/android/tv/player/ParseJob.java index 0228b03d7..364009285 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/ParseJob.java +++ b/app/src/main/java/com/fongmi/android/tv/player/ParseJob.java @@ -12,6 +12,7 @@ import com.fongmi.android.tv.impl.ParseCallback; import com.fongmi.android.tv.server.Server; import com.fongmi.android.tv.ui.custom.CustomWebView; import com.fongmi.android.tv.utils.UrlUtil; +import com.fongmi.android.tv.utils.WebViewUtil; import com.github.catvod.net.OkHttp; import com.github.catvod.utils.Json; import com.github.catvod.utils.Util; @@ -185,8 +186,12 @@ public class ParseJob implements ParseCallback { } private void startWeb(String key, String from, Map headers, String url, String click) { - App.post(() -> webViews.add(CustomWebView.create(App.get()).start(key, from, headers, url, click, this, !url.contains("player/?url=")))); - App.get().setSniff(true); + if (WebViewUtil.support()) { + App.post(() -> webViews.add(CustomWebView.create(App.get()).start(key, from, headers, url, click, this, !url.contains("player/?url=")))); + App.get().setSniff(true); + } else { + onParseError(); + } } private Map getHeader(JsonObject object) { 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 eb9cff05e..644d97d1f 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 @@ -61,7 +61,7 @@ public class CustomWebView extends WebView implements DialogInterface.OnDismissL return new CustomWebView(context); } - public CustomWebView(@NonNull Context context) { + private CustomWebView(@NonNull Context context) { super(context); initSettings(); } @@ -121,7 +121,7 @@ public class CustomWebView extends WebView implements DialogInterface.OnDismissL String host = request.getUrl().getHost(); if (TextUtils.isEmpty(host) || isAd(host)) return empty; Map headers = request.getRequestHeaders(); - if (url.contains("/cdn-cgi/challenge-platform/")) App.post(() -> showDialog()); + if (url.contains("/cdn-cgi/challenge-platform/")) post(() -> showDialog()); if (detect && PLAYER.matcher(url).find() && addUrl(url)) onParseAdd(headers, url); else if (isVideoFormat(url)) onParseSuccess(headers, url); return super.shouldInterceptRequest(view, request); @@ -204,13 +204,13 @@ public class CustomWebView extends WebView implements DialogInterface.OnDismissL } private void onParseAdd(Map headers, String url) { - App.post(() -> CustomWebView.create(App.get()).start(key, from, headers, url, click, callback, false)); + post(() -> CustomWebView.create(App.get()).start(key, from, headers, url, click, callback, false)); } private void onParseSuccess(Map headers, String url) { if (callback != null) callback.onParseSuccess(headers, url, from); SpiderDebug.log(TAG, "url=%s, headers=%s", url, headers); - App.post(() -> stop(false)); + post(() -> stop(false)); callback = null; } diff --git a/app/src/main/java/com/fongmi/android/tv/utils/Util.java b/app/src/main/java/com/fongmi/android/tv/utils/Util.java index 3720eb993..6154b328a 100644 --- a/app/src/main/java/com/fongmi/android/tv/utils/Util.java +++ b/app/src/main/java/com/fongmi/android/tv/utils/Util.java @@ -31,6 +31,7 @@ import java.net.NetworkInterface; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.Formatter; import java.util.List; @@ -179,9 +180,16 @@ public class Util { return text; } - public static long format(String src, List formats) { - for (SimpleDateFormat format : formats) try { return format.parse(src).getTime(); } catch (Exception ignored) {} - return 0; + public static Date parse(SimpleDateFormat format, String source) { + try { + return format.parse(source); + } catch (Exception e) { + return new Date(0); + } + } + + public static long parse(List formats, String source) { + return formats.stream().map(format -> parse(format, source)).map(Date::getTime).filter(time -> time > 0).findFirst().orElse(0L); } public static boolean isLeanback() { diff --git a/app/src/main/java/com/fongmi/android/tv/utils/WebViewUtil.java b/app/src/main/java/com/fongmi/android/tv/utils/WebViewUtil.java new file mode 100644 index 000000000..a107e7de7 --- /dev/null +++ b/app/src/main/java/com/fongmi/android/tv/utils/WebViewUtil.java @@ -0,0 +1,44 @@ +package com.fongmi.android.tv.utils; + +import android.content.pm.PackageManager; +import android.webkit.CookieManager; + +import com.fongmi.android.tv.App; + +import java.util.Set; + +public class WebViewUtil { + + private static final String SYSTEM_SETTINGS_PACKAGE = "com.android.settings"; + + private static final Set BROWSER_PACKAGES = Set.of( + "com.android.chrome", + "com.mi.globalbrowser", + "com.huawei.browser", + "com.heytap.browser", + "com.vivo.browser" + ); + + private static boolean installed(PackageManager pm, String pkg) { + try { + pm.getPackageInfo(pkg, PackageManager.GET_META_DATA); + return true; + } catch (PackageManager.NameNotFoundException ignored) { + return false; + } + } + + public static String spoof() { + PackageManager pm = App.get().getPackageManager(); + return BROWSER_PACKAGES.stream().filter(packageName -> installed(pm, packageName)).findFirst().orElse(SYSTEM_SETTINGS_PACKAGE); + } + + public static boolean support() { + try { + CookieManager.getInstance(); + } catch (Throwable e) { + return false; + } + return App.get().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW); + } +} diff --git a/hook/src/main/java/com/fongmi/hook/Chromium.java b/hook/src/main/java/com/fongmi/hook/Chromium.java index e190be373..6adb8a5d4 100644 --- a/hook/src/main/java/com/fongmi/hook/Chromium.java +++ b/hook/src/main/java/com/fongmi/hook/Chromium.java @@ -1,54 +1,19 @@ package com.fongmi.hook; -import android.content.Context; -import android.content.pm.PackageManager; import android.os.Looper; import java.util.Arrays; -import java.util.Set; public class Chromium { - private static final String SYSTEM_SETTINGS_PACKAGE = "com.android.settings"; - - private static final Set CHROMIUM_CLASS_NAMES = Set.of( - "org.chromium.base.buildinfo", - "org.chromium.base.apkinfo" - ); - - private static final Set CHROMIUM_METHOD_NAMES = Set.of( - "getall", - "getpackagename", - "" - ); - - private static final Set BROWSER_PACKAGES = Set.of( - "com.android.chrome", - "com.mi.globalbrowser", - "com.huawei.browser", - "com.heytap.browser", - "com.vivo.browser" - ); - - private static boolean isInstalled(PackageManager pm, String pkg) { - try { - pm.getPackageInfo(pkg, PackageManager.GET_META_DATA); - return true; - } catch (PackageManager.NameNotFoundException ignored) { - return false; - } - } + private static final String CLASS_NAME = "org.chromium.base.buildinfo"; + private static final String METHOD_NAME = "getall"; public static boolean find() { try { - return Arrays.stream(Looper.getMainLooper().getThread().getStackTrace()).anyMatch(trace -> CHROMIUM_CLASS_NAMES.contains(trace.getClassName().toLowerCase()) && CHROMIUM_METHOD_NAMES.contains(trace.getMethodName().toLowerCase())); - } catch (Exception e) { + return Arrays.stream(Looper.getMainLooper().getThread().getStackTrace()).anyMatch(trace -> CLASS_NAME.equalsIgnoreCase(trace.getClassName()) && METHOD_NAME.equalsIgnoreCase(trace.getMethodName())); + } catch (Throwable ignored) { return false; } } - - public static String spoofedPackageName(Context context) { - PackageManager pm = context.getPackageManager(); - return BROWSER_PACKAGES.stream().filter(packageName -> isInstalled(pm, packageName)).findFirst().orElse(SYSTEM_SETTINGS_PACKAGE); - } }