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 ba1fbca7f..93bef9e26 100644
--- a/app/src/main/java/com/fongmi/android/tv/App.java
+++ b/app/src/main/java/com/fongmi/android/tv/App.java
@@ -106,6 +106,7 @@ public class App extends Application {
super.onCreate();
Notify.createChannel();
Logger.addLogAdapter(getLogAdapter());
+ OkHttp.get().setProxy(Setting.getProxy());
OkHttp.get().setDoh(Doh.objectFrom(Setting.getDoh()));
CaocConfig.Builder.create().backgroundMode(CaocConfig.BACKGROUND_MODE_SILENT).errorActivity(CrashActivity.class).apply();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
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 e0e572d62..8bfe3c2ef 100644
--- a/app/src/main/java/com/fongmi/android/tv/Setting.java
+++ b/app/src/main/java/com/fongmi/android/tv/Setting.java
@@ -14,6 +14,14 @@ public class Setting {
Prefers.put("doh", doh);
}
+ public static String getProxy() {
+ return Prefers.getString("proxy");
+ }
+
+ public static void putProxy(String proxy) {
+ Prefers.put("proxy", proxy);
+ }
+
public static String getKeep() {
return Prefers.getString("keep");
}
diff --git a/app/src/main/java/com/fongmi/android/tv/impl/ProxyCallback.java b/app/src/main/java/com/fongmi/android/tv/impl/ProxyCallback.java
new file mode 100644
index 000000000..b9993a642
--- /dev/null
+++ b/app/src/main/java/com/fongmi/android/tv/impl/ProxyCallback.java
@@ -0,0 +1,6 @@
+package com.fongmi.android.tv.impl;
+
+public interface ProxyCallback {
+
+ void setProxy(String proxy);
+}
diff --git a/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java b/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java
index 93da6a8bc..37b03f017 100644
--- a/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java
+++ b/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java
@@ -170,7 +170,7 @@ public class ExoUtil {
}
private static synchronized HttpDataSource.Factory getHttpDataSourceFactory() {
- if (httpDataSourceFactory == null) httpDataSourceFactory = Setting.getHttp() == 0 ? new DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true) : new OkHttpDataSource.Factory((Call.Factory) OkHttp.client());
+ if (httpDataSourceFactory == null) httpDataSourceFactory = Setting.getHttp() == 0 ? new DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true).setProxy(Setting.getProxy()) : new OkHttpDataSource.Factory((Call.Factory) OkHttp.client());
return httpDataSourceFactory;
}
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 2c5b0cf93..054cbb3be 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -78,6 +78,7 @@
图片品质
图片尺寸
DoH
+ Proxy
缓存
版本
权限
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 6c2f8ad45..6d4a4063a 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -78,6 +78,7 @@
圖片品質
圖片尺寸
DoH
+ Proxy
暫存
版本
權限
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 766f66adf..0485c7a63 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -78,6 +78,7 @@
Image quality
Image size
DoH
+ Proxy
Cache
Version
Permission
diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/custom/dialog/ProxyDialog.java b/app/src/mobile/java/com/fongmi/android/tv/ui/custom/dialog/ProxyDialog.java
new file mode 100644
index 000000000..4daa1cbac
--- /dev/null
+++ b/app/src/mobile/java/com/fongmi/android/tv/ui/custom/dialog/ProxyDialog.java
@@ -0,0 +1,91 @@
+package com.fongmi.android.tv.ui.custom.dialog;
+
+import android.content.DialogInterface;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.inputmethod.EditorInfo;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+
+import com.fongmi.android.tv.R;
+import com.fongmi.android.tv.Setting;
+import com.fongmi.android.tv.databinding.DialogProxyBinding;
+import com.fongmi.android.tv.impl.ProxyCallback;
+import com.fongmi.android.tv.ui.custom.CustomTextListener;
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+
+public class ProxyDialog {
+
+ private final DialogProxyBinding binding;
+ private final ProxyCallback callback;
+ private AlertDialog dialog;
+ private boolean append;
+
+ public static ProxyDialog create(Fragment fragment) {
+ return new ProxyDialog(fragment);
+ }
+
+ public ProxyDialog(Fragment fragment) {
+ this.callback = (ProxyCallback) fragment;
+ this.binding = DialogProxyBinding.inflate(LayoutInflater.from(fragment.getContext()));
+ this.append = true;
+ }
+
+ public void show() {
+ initDialog();
+ initView();
+ initEvent();
+ }
+
+ private void initDialog() {
+ dialog = new MaterialAlertDialogBuilder(binding.getRoot().getContext()).setTitle(R.string.setting_proxy).setView(binding.getRoot()).setPositiveButton(R.string.dialog_positive, this::onPositive).setNegativeButton(R.string.dialog_negative, this::onNegative).create();
+ dialog.getWindow().setDimAmount(0);
+ dialog.show();
+ }
+
+ private void initView() {
+ String text = Setting.getProxy();
+ binding.text.setText(text);
+ binding.text.setSelection(TextUtils.isEmpty(text) ? 0 : text.length());
+ }
+
+ private void initEvent() {
+ binding.text.addTextChangedListener(new CustomTextListener() {
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ detect(s.toString());
+ }
+ });
+ binding.text.setOnEditorActionListener((textView, actionId, event) -> {
+ if (actionId == EditorInfo.IME_ACTION_DONE) dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
+ return true;
+ });
+ }
+
+ private void detect(String s) {
+ if (append && s.equals("h")) {
+ append = false;
+ binding.text.append("ttp://");
+ } else if (append && s.equals("s")) {
+ append = false;
+ binding.text.append("ocks5://");
+ } else if (append && s.length() == 1) {
+ append = false;
+ binding.text.getText().insert(0, "socks5://");
+ } else if (s.length() > 1) {
+ append = false;
+ } else if (s.length() == 0) {
+ append = true;
+ }
+ }
+
+ private void onPositive(DialogInterface dialog, int which) {
+ callback.setProxy(binding.text.getText().toString().trim());
+ dialog.dismiss();
+ }
+
+ private void onNegative(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+}
diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/custom/dialog/UaDialog.java b/app/src/mobile/java/com/fongmi/android/tv/ui/custom/dialog/UaDialog.java
index 029f1b88b..6285057d4 100644
--- a/app/src/mobile/java/com/fongmi/android/tv/ui/custom/dialog/UaDialog.java
+++ b/app/src/mobile/java/com/fongmi/android/tv/ui/custom/dialog/UaDialog.java
@@ -42,9 +42,9 @@ public class UaDialog {
}
private void initView() {
- String ua = Setting.getUa();
- binding.text.setText(ua);
- binding.text.setSelection(TextUtils.isEmpty(ua) ? 0 : ua.length());
+ String text = Setting.getUa();
+ binding.text.setText(text);
+ binding.text.setSelection(TextUtils.isEmpty(text) ? 0 : text.length());
}
private void initEvent() {
diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java
index be41cbe07..aa874d851 100644
--- a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java
+++ b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java
@@ -26,12 +26,14 @@ import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.impl.Callback;
import com.fongmi.android.tv.impl.ConfigCallback;
import com.fongmi.android.tv.impl.LiveCallback;
+import com.fongmi.android.tv.impl.ProxyCallback;
import com.fongmi.android.tv.impl.SiteCallback;
import com.fongmi.android.tv.ui.activity.MainActivity;
import com.fongmi.android.tv.ui.base.BaseFragment;
import com.fongmi.android.tv.ui.custom.dialog.ConfigDialog;
import com.fongmi.android.tv.ui.custom.dialog.HistoryDialog;
import com.fongmi.android.tv.ui.custom.dialog.LiveDialog;
+import com.fongmi.android.tv.ui.custom.dialog.ProxyDialog;
import com.fongmi.android.tv.ui.custom.dialog.SiteDialog;
import com.fongmi.android.tv.utils.FileChooser;
import com.fongmi.android.tv.utils.FileUtil;
@@ -41,13 +43,14 @@ import com.fongmi.android.tv.utils.Utils;
import com.github.catvod.bean.Doh;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Path;
+import com.github.catvod.utils.Util;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.permissionx.guolindev.PermissionX;
import java.util.ArrayList;
import java.util.List;
-public class SettingFragment extends BaseFragment implements ConfigCallback, SiteCallback, LiveCallback {
+public class SettingFragment extends BaseFragment implements ConfigCallback, SiteCallback, LiveCallback, ProxyCallback {
private FragmentSettingBinding mBinding;
private String[] render;
@@ -87,6 +90,7 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
mBinding.wallUrl.setText(WallConfig.getDesc());
mBinding.dohText.setText(getDohList()[getDohIndex()]);
mBinding.versionText.setText(BuildConfig.VERSION_NAME);
+ mBinding.proxyText.setText(Util.scheme(Setting.getProxy()));
mBinding.sizeText.setText((size = ResUtil.getStringArray(R.array.select_size))[Setting.getSize()]);
mBinding.scaleText.setText((scale = ResUtil.getStringArray(R.array.select_scale))[Setting.getScale()]);
mBinding.playerText.setText((player = ResUtil.getStringArray(R.array.select_player))[Setting.getPlayer()]);
@@ -109,6 +113,7 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
mBinding.vod.setOnClickListener(this::onVod);
mBinding.live.setOnClickListener(this::onLive);
mBinding.wall.setOnClickListener(this::onWall);
+ mBinding.proxy.setOnClickListener(this::onProxy);
mBinding.cache.setOnClickListener(this::onCache);
mBinding.version.setOnClickListener(this::onVersion);
mBinding.vodHome.setOnClickListener(this::onVodHome);
@@ -318,6 +323,19 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
ApiConfig.load(Config.vod(), getCallback());
}
+ private void onProxy(View view) {
+ ProxyDialog.create(this).show();
+ }
+
+ @Override
+ public void setProxy(String proxy) {
+ Setting.putProxy(proxy);
+ OkHttp.get().setProxy(proxy);
+ Notify.progress(getActivity());
+ ApiConfig.load(Config.vod(), getCallback());
+ mBinding.proxyText.setText(Util.scheme(proxy));
+ }
+
private void onCache(View view) {
FileUtil.clearCache(new Callback() {
@Override
diff --git a/app/src/mobile/res/layout/dialog_proxy.xml b/app/src/mobile/res/layout/dialog_proxy.xml
new file mode 100644
index 000000000..f69ec08f5
--- /dev/null
+++ b/app/src/mobile/res/layout/dialog_proxy.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/mobile/res/layout/fragment_setting.xml b/app/src/mobile/res/layout/fragment_setting.xml
index 06f082a64..b4515cb8f 100644
--- a/app/src/mobile/res/layout/fragment_setting.xml
+++ b/app/src/mobile/res/layout/fragment_setting.xml
@@ -372,6 +372,33 @@
+
+
+
+
+
+
+
+
params) {
+ FormBody.Builder body = new FormBody.Builder();
+ for (Map.Entry entry : params.entrySet()) body.add(entry.getKey(), entry.getValue());
+ return body.build();
+ }
+
private static HttpUrl buildUrl(String url, ArrayMap params) {
HttpUrl.Builder builder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
for (Map.Entry entry : params.entrySet()) builder.addQueryParameter(entry.getKey(), entry.getValue());
return builder.build();
}
- public static FormBody toBody(ArrayMap params) {
- FormBody.Builder body = new FormBody.Builder();
- for (Map.Entry entry : params.entrySet()) body.add(entry.getKey(), entry.getValue());
- return body.build();
+ private static void setProxy(OkHttpClient.Builder builder) {
+ Uri uri = Uri.parse(proxy());
+ if (uri.getHost() == null) return;
+ String userInfo = uri.getUserInfo();
+ if (Util.scheme(uri).startsWith("socks")) {
+ builder.proxy(new Proxy(Proxy.Type.SOCKS, InetSocketAddress.createUnresolved(uri.getHost(), uri.getPort())));
+ }
+ if (Util.scheme(uri).startsWith("http")) {
+ builder.proxy(new Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved(uri.getHost(), uri.getPort())));
+ if (userInfo != null && userInfo.contains(":")) builder.proxyAuthenticator((route, response) -> {
+ String credential = Credentials.basic(userInfo.split(":")[0], userInfo.split(":")[1]);
+ return response.request().newBuilder().header("Proxy-Authorization", credential).build();
+ });
+ }
+ if (userInfo != null && userInfo.contains(":")) Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(userInfo.split(":")[0], userInfo.split(":")[1].toCharArray());
+ }
+ });
}
}