diff --git a/app/build.gradle b/app/build.gradle index c87efb219..602ca12cf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,7 +11,7 @@ android { minSdk 21 targetSdk 28 versionCode 232 - versionName "2.3.2" + versionName "0404" javaCompileOptions { annotationProcessorOptions { arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] @@ -127,6 +127,7 @@ dependencies { implementation 'org.fourthline.cling:cling-core:2.1.1' implementation 'org.fourthline.cling:cling-support:2.1.1' implementation 'org.greenrobot:eventbus:3.3.1' + implementation 'com.tencent.tbs:tbssdk:44286' implementation('org.simpleframework:simple-xml:2.7.1') { exclude group: 'stax', module: 'stax-api' exclude group: 'xpp3', module: 'xpp3' } implementation(ext: 'aar', name: 'dlna-core', group: 'fongmi', version: 'release') leanbackImplementation(ext: 'aar', name: 'dlna-dmr', group: 'fongmi', version: 'release') diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index bd7856fb3..3e24858c6 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -79,4 +79,10 @@ -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); -} \ No newline at end of file +} + +# x5 +-dontwarn dalvik.** +-dontwarn com.tencent.smtt.** +-keep class com.tencent.smtt.** { *; } +-keep class com.tencent.tbs.** { *; } \ No newline at end of file diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java index 1bad08d74..82e6c33df 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java @@ -58,6 +58,7 @@ import com.fongmi.android.tv.utils.FileUtil; import com.fongmi.android.tv.utils.KeyUtil; import com.fongmi.android.tv.utils.Notify; import com.fongmi.android.tv.utils.ResUtil; +import com.fongmi.android.tv.utils.Tbs; import com.fongmi.android.tv.utils.UrlUtil; import com.github.catvod.utils.Prefers; import com.github.catvod.utils.Trans; @@ -111,6 +112,7 @@ public class HomeActivity extends BaseActivity implements CustomTitleView.Listen setHomeType(); setPager(); initConfig(); + Tbs.init(); } @Override diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingCustomActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingCustomActivity.java index 7f5a5bfe6..9c9cbc8a8 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingCustomActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingCustomActivity.java @@ -6,6 +6,7 @@ import android.view.View; import androidx.viewbinding.ViewBinding; +import com.fongmi.android.tv.App; import com.fongmi.android.tv.R; import com.fongmi.android.tv.Setting; import com.fongmi.android.tv.databinding.ActivitySettingCustomBinding; @@ -14,8 +15,9 @@ import com.fongmi.android.tv.ui.base.BaseActivity; import com.fongmi.android.tv.ui.dialog.ButtonsDialog; import com.fongmi.android.tv.ui.dialog.DisplayDialog; import com.fongmi.android.tv.ui.dialog.MenuKeyDialog; +import com.fongmi.android.tv.ui.dialog.X5WebViewDialog; import com.fongmi.android.tv.utils.ResUtil; - +import com.tencent.smtt.sdk.QbSdk; import java.util.Locale; public class SettingCustomActivity extends BaseActivity { @@ -27,6 +29,7 @@ public class SettingCustomActivity extends BaseActivity { private String[] fullscreenMenuKey; private String[] smallWindowBackKey; private String[] homeUI; + private String[] parseWebview; @Override protected ViewBinding getBinding() { @@ -56,6 +59,7 @@ public class SettingCustomActivity extends BaseActivity { mBinding.aggregatedSearchText.setText(getSwitch(Setting.isAggregatedSearch())); mBinding.homeUIText.setText((homeUI = ResUtil.getStringArray(R.array.select_home_ui))[Setting.getHomeUI()]); mBinding.homeHistoryText.setText(getSwitch(Setting.isHomeHistory())); + mBinding.parseWebviewText.setText((parseWebview = ResUtil.getStringArray(R.array.select_parse_webview))[Setting.getParseWebView()]); } @Override @@ -75,6 +79,7 @@ public class SettingCustomActivity extends BaseActivity { mBinding.homeUI.setOnClickListener(this::setHomeUI); mBinding.homeButtons.setOnClickListener(this::onHomeButtons); mBinding.homeHistory.setOnClickListener(this::setHomeHistory); + mBinding.parseWebview.setOnClickListener(this::setParseWebview); } private void setQuality(View view) { @@ -169,4 +174,11 @@ public class SettingCustomActivity extends BaseActivity { mBinding.homeHistoryText.setText(getSwitch(Setting.isHomeHistory())); } + private void setParseWebview(View view) { + int index = Setting.getParseWebView(); + Setting.putParseWebView(index = index == parseWebview.length - 1 ? 0 : ++index); + mBinding.parseWebviewText.setText(parseWebview[index]); + if (index == 1 && QbSdk.getTbsVersion(App.get()) <= 0) X5WebViewDialog.create(this).show(); + } + } diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/dialog/X5WebViewDialog.java b/app/src/leanback/java/com/fongmi/android/tv/ui/dialog/X5WebViewDialog.java new file mode 100644 index 000000000..be92e798e --- /dev/null +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/dialog/X5WebViewDialog.java @@ -0,0 +1,84 @@ +package com.fongmi.android.tv.ui.dialog; + +import android.app.Activity; +import android.view.LayoutInflater; +import android.view.View; + +import androidx.appcompat.app.AlertDialog; + +import com.fongmi.android.tv.Setting; +import com.fongmi.android.tv.databinding.DialogX5webviewBinding; +import com.fongmi.android.tv.utils.Download; +import com.fongmi.android.tv.utils.Notify; +import com.fongmi.android.tv.utils.Tbs; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import java.io.File; +import java.util.Locale; + +public class X5WebViewDialog implements Download.Callback { + + private DialogX5webviewBinding binding; + private AlertDialog dialog; + private Activity activity; + + public X5WebViewDialog(Activity activity) { + this.activity = activity; + } + + public void show() { + binding = DialogX5webviewBinding.inflate(LayoutInflater.from(activity)); + binding.confirm.setOnClickListener(this::confirm); + binding.cancel.setOnClickListener(this::cancel); + dialog = new MaterialAlertDialogBuilder(activity).setView(binding.getRoot()).setCancelable(false).create(); + dialog.show(); + } + + public static X5WebViewDialog create(Activity activity) { + return new X5WebViewDialog(activity); + } + + private String getTbs() { + return Tbs.url(); + } + + private File getFile() { + return Tbs.file(); + } + + private void cancel(View view) { + dismiss(); + } + + private void confirm(View view) { + binding.confirm.setEnabled(false); + Download.create(getTbs(), getFile(), this).start(); + } + + private void dismiss() { + try { + if (dialog != null) dialog.dismiss(); + } catch (Exception ignored) { + } + } + + @Override + public void progress(int progress) { + binding.confirm.setText(String.format(Locale.getDefault(), "%1$d%%", progress)); + } + + @Override + public void error(String msg) { + Notify.show(msg); + Setting.putParseWebView(0); + dismiss(); + } + + @Override + public void success(File file) { + dismiss(); + Tbs.download(); + Setting.putParseWebView(1); + } + + +} diff --git a/app/src/leanback/res/layout/activity_setting_custom.xml b/app/src/leanback/res/layout/activity_setting_custom.xml index a3864f9ff..842689396 100644 --- a/app/src/leanback/res/layout/activity_setting_custom.xml +++ b/app/src/leanback/res/layout/activity_setting_custom.xml @@ -463,5 +463,43 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/leanback/res/layout/dialog_x5webview.xml b/app/src/leanback/res/layout/dialog_x5webview.xml new file mode 100644 index 000000000..1d74982ab --- /dev/null +++ b/app/src/leanback/res/layout/dialog_x5webview.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/fongmi/android/tv/Setting.java b/app/src/main/java/com/fongmi/android/tv/Setting.java index 21bfdf7ea..463ac256a 100644 --- a/app/src/main/java/com/fongmi/android/tv/Setting.java +++ b/app/src/main/java/com/fongmi/android/tv/Setting.java @@ -477,4 +477,11 @@ public class Setting { return Math.min(Prefers.getInt("config_cache", 0), 8); } + public static void putParseWebView(int key) { + Prefers.put("parse_webview", key); + } + + public static int getParseWebView() { + return Prefers.getInt("parse_webview", 0); + } } 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 99b939a9b..0df2947c8 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 @@ -4,22 +4,27 @@ import android.annotation.SuppressLint; import android.app.AlertDialog; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.net.Uri; -import android.net.http.SslError; import android.text.TextUtils; import android.view.ViewGroup; -import android.webkit.CookieManager; -import android.webkit.SslErrorHandler; -import android.webkit.WebResourceRequest; -import android.webkit.WebResourceResponse; import android.webkit.WebSettings; -import android.webkit.WebView; -import android.webkit.WebViewClient; +import com.fongmi.android.tv.utils.Notify; +import com.tencent.smtt.export.external.interfaces.SslError; +import com.tencent.smtt.export.external.interfaces.SslErrorHandler; +import com.tencent.smtt.export.external.interfaces.WebResourceRequest; +import com.tencent.smtt.export.external.interfaces.WebResourceResponse; +import com.tencent.smtt.sdk.CookieManager; +import com.tencent.smtt.sdk.QbSdk; +import com.tencent.smtt.sdk.WebChromeClient; +import com.tencent.smtt.sdk.WebView; +import com.tencent.smtt.sdk.WebViewClient; import androidx.annotation.NonNull; import com.fongmi.android.tv.App; import com.fongmi.android.tv.Constant; +import com.fongmi.android.tv.R; import com.fongmi.android.tv.Setting; import com.fongmi.android.tv.api.config.VodConfig; import com.fongmi.android.tv.bean.Site; @@ -49,12 +54,23 @@ public class CustomWebView extends WebView { private String key; public static CustomWebView create(@NonNull Context context) { + initTbs(); return new CustomWebView(context); } public CustomWebView(@NonNull Context context) { super(context); initSettings(); + showTbs(); + } + + private static void initTbs() { + if (Setting.getParseWebView() == 0) QbSdk.forceSysWebView(); + else QbSdk.unForceSysWebView(); + } + + private void showTbs() { + if (this.getIsX5Core()) Notify.show(R.string.x5webview_parsing); } @SuppressLint("SetJavaScriptEnabled") @@ -75,11 +91,7 @@ public class CustomWebView extends WebView { getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); CookieManager.getInstance().setAcceptThirdPartyCookies(this, true); setWebViewClient(webViewClient()); - } - - private void addView() { - ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(1, 1); - if (App.activity() != null) App.activity().addContentView(this, params); + setWebChromeClient(webChromeClient()); } public CustomWebView start(String key, String from, Map headers, String url, String click, ParseCallback callback, boolean detect) { @@ -89,7 +101,6 @@ public class CustomWebView extends WebView { this.click = click; this.from = from; this.key = key; - addView(); start(url, headers); return this; } @@ -146,9 +157,22 @@ public class CustomWebView extends WebView { }; } + private WebChromeClient webChromeClient() { + return new WebChromeClient() { + @Override + public Bitmap getDefaultVideoPoster() { + try { + return BitmapFactory.decodeResource(App.get().getResources(), R.drawable.ic_logo); + } catch (Throwable e) { + return super.getDefaultVideoPoster(); + } + } + }; + } + private void showDialog() { if (dialog != null || App.activity() == null) return; - removeView(); + if (getParent() != null) ((ViewGroup) getParent()).removeView(this); dialog = new AlertDialog.Builder(App.activity()).setView(this).show(); } @@ -206,13 +230,8 @@ public class CustomWebView extends WebView { callback = null; } - private void removeView() { - if (getParent() != null) ((ViewGroup) getParent()).removeView(this); - } - public void stop(boolean error) { hideDialog(); - removeView(); stopLoading(); loadUrl(BLANK); App.removeCallbacks(timer); diff --git a/app/src/main/java/com/fongmi/android/tv/utils/Tbs.java b/app/src/main/java/com/fongmi/android/tv/utils/Tbs.java new file mode 100644 index 000000000..c4ce7f73c --- /dev/null +++ b/app/src/main/java/com/fongmi/android/tv/utils/Tbs.java @@ -0,0 +1,106 @@ +package com.fongmi.android.tv.utils; + +import android.os.Build; + +import com.fongmi.android.tv.App; +import com.fongmi.android.tv.R; +import com.fongmi.android.tv.Setting; +import com.github.catvod.utils.Path; +import com.orhanobut.logger.Logger; +import com.tencent.smtt.sdk.QbSdk; +import com.tencent.smtt.sdk.TbsListener; +import com.tencent.smtt.export.external.TbsCoreSettings; + +import java.io.File; +import java.util.HashMap; + +public class Tbs { + private static final String TAG = Tbs.class.getSimpleName(); + + public static final String URL64 = "https://tmf-pkg-1314481471.cos.ap-shanghai.myqcloud.com/x5/64/46471/tbs_core_046471_20230809100104_nolog_fs_obfs_arm64-v8a_release.tbs"; + public static final String URL32 = "https://tmf-pkg-1314481471.cos.ap-shanghai.myqcloud.com/x5/32/46471/tbs_core_046471_20230809095840_nolog_fs_obfs_armeabi_release.tbs"; + + private static boolean isCpu64Bit() { + for (String abi : Build.SUPPORTED_ABIS) { + if (abi.contains("64")) return true; + } + return false; + } + + public static String getUrl() { + return isCpu64Bit() ? URL64 : URL32; + } + + private static void tbsInit() { + HashMap map = new HashMap(); + map.put(TbsCoreSettings.TBS_SETTINGS_USE_PRIVATE_CLASSLOADER, true); + QbSdk.initTbsSettings(map); + QbSdk.setDownloadWithoutWifi(false); + QbSdk.setCoreMinVersion(QbSdk.CORE_VER_ENABLE_202207); + TbsListener tbsListener = new TbsListener() { + + /** + * @param stateCode 用户可处理错误码请参考{@link com.tencent.smtt.sdk.TbsCommonCode} + */ + @Override + public void onDownloadFinish(int stateCode) { + Logger.t(TAG).d("onDownloadFinish:" + stateCode); + } + + /** + * @param stateCode 用户可处理错误码请参考{@link com.tencent.smtt.sdk.TbsCommonCode} + */ + @Override + public void onInstallFinish(int stateCode) { + Logger.t(TAG).d("onInstallFinish:" + stateCode); + } + + /** + * 首次安装应用,会触发内核下载,此时会有内核下载的进度回调。 + * @param progress 0 - 100 + */ + @Override + public void onDownloadProgress(int progress) { + Logger.t(TAG).d("onDownloadProgress:" + progress); + } + }; + QbSdk.PreInitCallback callback = new QbSdk.PreInitCallback() { + @Override + public void onViewInitFinished(boolean finished) { + if (finished) Notify.show(R.string.x5webview_enabled); + } + + @Override + public void onCoreInitFinished() { + } + }; + QbSdk.setTbsListener(tbsListener); + QbSdk.initX5Environment(App.get(), callback); + } + + public static void init() { + if (Setting.getParseWebView() == 0) return; + App.post(() -> tbsInit()); + } + + public static String url() { + return getUrl(); + } + + private static File tbs() { + File tbsDir = Path.files("tbs"); + return tbsDir; + } + + public static File file() { + File tbsDir = tbs(); + if (!tbsDir.exists()) tbsDir.mkdirs(); + File x5 = new File(tbsDir, "x5.apk"); + return x5; + } + + public static void download() { + QbSdk.installLocalQbApk(App.get(), "46471", file().getAbsolutePath(), null); + } + +} diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 0fd8a086c..9eb9c485e 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -80,6 +80,7 @@ 图片品质 图片尺寸 聚合搜索 + 嗅探内核 全屏菜单键 首页菜单键 首页源锁定 @@ -155,6 +156,12 @@ 正在检测更新… 更新 + + X5 WebView + 下载X5 WebView并启用? + X5 WebView已启用 + X5 WebView嗅探中 + 发生意外错误\n抱歉给您带来不便 重新启动 @@ -252,6 +259,11 @@ 设置页面 + + 系统 + X5 WebView + + 播放历史 站点推荐 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index b780e91cd..cc8674d0c 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -80,6 +80,7 @@ 圖片品質 圖片尺寸 聚合搜索 + 嗅探內核 全屏選單鍵 首頁選單鍵 首頁源鎖定 @@ -155,6 +156,12 @@ 正在檢查更新… 更新 + + X5 WebView + 下载X5 WebView並啟用? + X5 WebView已啟用 + X5 WebView嗅探中 + 發生意外錯誤\n抱歉給您帶來不便 重新啟動 @@ -252,6 +259,11 @@ 设置頁面 + + 系統 + X5 WebView + + 播放歷史 站點推薦 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ab9fafbd4..0cc251499 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -80,6 +80,7 @@ Image quality Image size Aggregated search + Parse webview Fullscreen menu key Home menu key Home site lock @@ -155,6 +156,12 @@ Checking for updates… Update + + X5 WebView + Download X5 WebView and Enable? + X5 WebView Enabled + X5 WebView Parsing + An unexpected error occurred.\nSorry for the inconvenience. Restart app @@ -252,6 +259,11 @@ Setting page + + System + X5 WebView + + Back Focus move