From d7abb8f49e3e9292c09a6fb9d2ca2f03530a7810 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Tue, 14 Apr 2026 14:42:31 +0800 Subject: [PATCH] Add dynamic local SOCKS port option Introduce a dynamic SOCKS port feature: add PREF_DYNAMIC_SOCKS_PORT key, settings UI checkbox and localized strings, and pref XML entry. SettingsManager now holds a runtimeSocksPort, can generate and refresh a random port (generateRandomSocksPort, refreshRuntimeSocksPort) and respects the dynamic setting when returning getSocksPort(). V2Ray service startup triggers a runtime port refresh. Settings UI disables manual SOCKS port input when dynamic mode is enabled. Minor i18n additions (QR code/title) included for several locales. --- .../src/main/java/com/v2ray/ang/AppConfig.kt | 1 + .../com/v2ray/ang/handler/SettingsManager.kt | 33 ++++++++++++++++++- .../v2ray/ang/handler/V2RayServiceManager.kt | 2 ++ .../java/com/v2ray/ang/ui/SettingsActivity.kt | 13 ++++++++ .../app/src/main/res/values-ar/strings.xml | 3 ++ .../app/src/main/res/values-bn/strings.xml | 3 ++ .../src/main/res/values-bqi-rIR/strings.xml | 7 ++++ .../app/src/main/res/values-fa/strings.xml | 3 ++ .../app/src/main/res/values-ru/strings.xml | 3 ++ .../app/src/main/res/values-vi/strings.xml | 3 ++ .../src/main/res/values-zh-rCN/strings.xml | 3 ++ .../src/main/res/values-zh-rTW/strings.xml | 3 ++ V2rayNG/app/src/main/res/values/strings.xml | 2 ++ .../app/src/main/res/xml/pref_settings.xml | 6 ++++ 14 files changed, 84 insertions(+), 1 deletion(-) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt index 350fcce0..1de4e8ac 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt @@ -58,6 +58,7 @@ object AppConfig { const val PREF_PROXY_SHARING = "pref_proxy_sharing_enabled" const val PREF_ALLOW_INSECURE = "pref_allow_insecure" const val PREF_SOCKS_PORT = "pref_socks_port" + const val PREF_DYNAMIC_SOCKS_PORT = "pref_dynamic_socks_port" const val PREF_SOCKS_USERNAME = "pref_socks_username" const val PREF_SOCKS_PASSWORD = "pref_socks_password" const val PREF_REMOTE_DNS = "pref_remote_dns" diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt index 8677d7ae..2e087c81 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt @@ -32,9 +32,13 @@ import java.io.File import java.io.FileOutputStream import java.util.Collections import java.util.Locale +import kotlin.random.Random object SettingsManager { + @Volatile + private var runtimeSocksPort: Int? = null + fun initApp(context: Context) { ensureDefaultSettings() //ensureDefaultSubscription() @@ -273,7 +277,22 @@ object SettingsManager { * @return The SOCKS port. */ fun getSocksPort(): Int { - return Utils.parseInt(MmkvManager.decodeSettingsString(AppConfig.PREF_SOCKS_PORT), AppConfig.PORT_SOCKS.toInt()) + val port = + if (IsDynamicSocksPort()) { + runtimeSocksPort ?: refreshRuntimeSocksPort() + } else { + Utils.parseInt(MmkvManager.decodeSettingsString(AppConfig.PREF_SOCKS_PORT), AppConfig.PORT_SOCKS.toInt()) + } + return port ?: AppConfig.PORT_SOCKS.toInt() + } + + @Synchronized + fun refreshRuntimeSocksPort(): Int? { + if (IsDynamicSocksPort()) { + runtimeSocksPort = generateRandomSocksPort() + return runtimeSocksPort + } + return null } fun getSocksUsername(): String? { @@ -292,6 +311,18 @@ object SettingsManager { return getSocksPort() + if (Utils.isXray()) 0 else 1 } + private fun IsDynamicSocksPort(): Boolean { + return MmkvManager.decodeSettingsBool(AppConfig.PREF_DYNAMIC_SOCKS_PORT, false) + } + + private fun generateRandomSocksPort(): Int { + return if (Utils.isXray()) { + Random.nextInt(10000, 65536) + } else { + Random.nextInt(10000, 65535) + } + } + /** * Initialize assets. * @param context The application context. diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2RayServiceManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2RayServiceManager.kt index 891f86bf..3c6a56f7 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2RayServiceManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2RayServiceManager.kt @@ -173,6 +173,8 @@ object V2RayServiceManager { } Log.i(AppConfig.TAG, "StartCore-Manager: Starting core loop for ${config.remarks}") + // refresh socks port when enabled dynamic socks port + SettingsManager.refreshRuntimeSocksPort() val result = V2rayConfigManager.getV2rayConfig(service, guid) if (!result.status) { Log.e(AppConfig.TAG, "StartCore-Manager: Failed to get V2Ray config") diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SettingsActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SettingsActivity.kt index 523d3d79..8d883bfe 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SettingsActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SettingsActivity.kt @@ -51,6 +51,8 @@ class SettingsActivity : BaseActivity() { private val autoUpdateCheck by lazy { findPreference(AppConfig.SUBSCRIPTION_AUTO_UPDATE) } private val autoUpdateInterval by lazy { findPreference(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL) } private val mode by lazy { findPreference(AppConfig.PREF_MODE) } + private val socksPort by lazy { findPreference(AppConfig.PREF_SOCKS_PORT) } + private val dynamicSocksPort by lazy { findPreference(AppConfig.PREF_DYNAMIC_SOCKS_PORT) } private val hevTunLogLevel by lazy { findPreference(AppConfig.PREF_HEV_TUNNEL_LOGLEVEL) } private val hevTunRwTimeout by lazy { findPreference(AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT) } @@ -112,6 +114,11 @@ class SettingsActivity : BaseActivity() { updateHevTunSettings(newValue as Boolean) true } + + dynamicSocksPort?.setOnPreferenceChangeListener { _, newValue -> + updateDynamicSocksPort(newValue as Boolean) + true + } } private fun initPreferenceSummaries() { @@ -175,6 +182,8 @@ class SettingsActivity : BaseActivity() { // Initialize auto-update interval state autoUpdateInterval?.isEnabled = MmkvManager.decodeSettingsBool(AppConfig.SUBSCRIPTION_AUTO_UPDATE, false) + + updateDynamicSocksPort(MmkvManager.decodeSettingsBool(AppConfig.PREF_DYNAMIC_SOCKS_PORT, false)) } private fun updateMode(value: String?) { @@ -266,6 +275,10 @@ class SettingsActivity : BaseActivity() { fragmentInterval?.isEnabled = enabled } + private fun updateDynamicSocksPort(enabled: Boolean) { + socksPort?.isEnabled = !enabled + } + private fun updateHevTunSettings(enabled: Boolean) { hevTunLogLevel?.isEnabled = enabled hevTunRwTimeout?.isEnabled = enabled diff --git a/V2rayNG/app/src/main/res/values-ar/strings.xml b/V2rayNG/app/src/main/res/values-ar/strings.xml index b644105a..e85e80ac 100644 --- a/V2rayNG/app/src/main/res/values-ar/strings.xml +++ b/V2rayNG/app/src/main/res/values-ar/strings.xml @@ -219,6 +219,8 @@ منفذ بروكسي Local منفذ بروكسي Local + Enable dynamic local proxy port + Generate a random local proxy port each time the inbound is created Local proxy username (optional) Username Local proxy password (optional) @@ -247,6 +249,7 @@ الانضمام إلى مجموعة Telegram لم يتم العثور على تطبيق Telegram سياسة الخصوصية + QR code حول\nترجمة م. ابراهيم قاسم الكود المصدري Open Source licenses diff --git a/V2rayNG/app/src/main/res/values-bn/strings.xml b/V2rayNG/app/src/main/res/values-bn/strings.xml index 6e09a832..9bdb5425 100644 --- a/V2rayNG/app/src/main/res/values-bn/strings.xml +++ b/V2rayNG/app/src/main/res/values-bn/strings.xml @@ -219,6 +219,8 @@ Local প্রক্সি পোর্ট Local প্রক্সি পোর্ট + Enable dynamic local proxy port + Generate a random local proxy port each time the inbound is created Local proxy username (optional) Username Local proxy password (optional) @@ -247,6 +249,7 @@ টেলিগ্রাম গ্রুপে যোগদান করুন টেলিগ্রাম অ্যাপ পাওয়া যায়নি গোপনীয়তা নীতি + QR code সম্পর্কিত সোর্স কোড Open Source licenses diff --git a/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml b/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml index ef4c46f7..71835ca1 100644 --- a/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml +++ b/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml @@ -219,6 +219,12 @@ پورت پروکسی مهلی پورت پروکسی مهلی + Enable dynamic local proxy port + Generate a random local proxy port each time the inbound is created + Local proxy username (optional) + Username + Local proxy password (optional) + Password پورت DNS مهلی پورت DNS مهلی @@ -243,6 +249,7 @@ ٱووڌن من بونکۊ تلگرام برنومه تلگرامن نجوست هریم سیخومی + QR code زبار کود بونچک موجوزا کود بونچک diff --git a/V2rayNG/app/src/main/res/values-fa/strings.xml b/V2rayNG/app/src/main/res/values-fa/strings.xml index 88901cef..76291c20 100644 --- a/V2rayNG/app/src/main/res/values-fa/strings.xml +++ b/V2rayNG/app/src/main/res/values-fa/strings.xml @@ -217,6 +217,8 @@ پورت پروکسی محلی پورت پروکسی محلی + Enable dynamic local proxy port + Generate a random local proxy port each time the inbound is created Local proxy username (optional) Username Local proxy password (optional) @@ -246,6 +248,7 @@ برنامه تلگرام پیدا نشد حریم خصوصی + QR code درباره کد منبع مجوز های منبع باز diff --git a/V2rayNG/app/src/main/res/values-ru/strings.xml b/V2rayNG/app/src/main/res/values-ru/strings.xml index fca89831..5549548d 100644 --- a/V2rayNG/app/src/main/res/values-ru/strings.xml +++ b/V2rayNG/app/src/main/res/values-ru/strings.xml @@ -218,6 +218,8 @@ Порт локального прокси Порт локального прокси + Enable dynamic local proxy port + Generate a random local proxy port each time the inbound is created Имя пользователя локального прокси (опционально) Имя пользователя Пароль локального прокси (опционально) @@ -246,6 +248,7 @@ Присоединиться к группе в Telegram Приложение Telegram не найдено Политика конфиденциальности + QR-код О приложении Исходный код Лицензии открытого исходного кода diff --git a/V2rayNG/app/src/main/res/values-vi/strings.xml b/V2rayNG/app/src/main/res/values-vi/strings.xml index 34308552..9f927928 100644 --- a/V2rayNG/app/src/main/res/values-vi/strings.xml +++ b/V2rayNG/app/src/main/res/values-vi/strings.xml @@ -219,6 +219,8 @@ Cổng Proxy Local Cổng Proxy Local + Enable dynamic local proxy port + Generate a random local proxy port each time the inbound is created Tên người dùng Proxy Local (Không bắt buộc) Tên người dùng Mật khẩu Proxy Local (Không bắt buộc) @@ -248,6 +250,7 @@ Không tìm thấy ứng dụng Telegram! Chính sách bảo mật + Mã QR Giới thiệu Mã nguồn Open Source licenses diff --git a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml index bdcbbb1f..5db3fc0f 100644 --- a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml +++ b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml @@ -216,6 +216,8 @@ 本地代理端口 本地代理端口 + 启用动态本地代理端口 + 每次生成 inbound 时随机生成一个本地代理端口 本地代理用户名 (可选) 用户名 本地代理密码 (可选) @@ -245,6 +247,7 @@ 加入 Telegram Group 未找到 Telegram app 隐私权政策 + 二维码 关于 源代码 Open Source licenses diff --git a/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml b/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml index 86fcfe47..8d1a546b 100644 --- a/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml +++ b/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml @@ -217,6 +217,8 @@ 本地代理埠 本地代理埠 + 啟用動態本地代理埠 + 每次產生 inbound 時隨機產生一個本地代理埠 本地代理使用者名稱 (選擇) 使用者名稱 本地代理密碼 (選擇) @@ -246,6 +248,7 @@ 加入 Telegram 群組 未找到 Telegram 應用程式 隱私權政策 + QR 碼 關於 原始碼 Open Source licenses diff --git a/V2rayNG/app/src/main/res/values/strings.xml b/V2rayNG/app/src/main/res/values/strings.xml index fc247e42..374d61ea 100644 --- a/V2rayNG/app/src/main/res/values/strings.xml +++ b/V2rayNG/app/src/main/res/values/strings.xml @@ -222,6 +222,8 @@ Local proxy port Local proxy port + Enable dynamic local proxy port + Generate a random local proxy port each time the inbound is created Local proxy username (optional) Username Local proxy password (optional) diff --git a/V2rayNG/app/src/main/res/xml/pref_settings.xml b/V2rayNG/app/src/main/res/xml/pref_settings.xml index 15f4053e..155ad3cd 100644 --- a/V2rayNG/app/src/main/res/xml/pref_settings.xml +++ b/V2rayNG/app/src/main/res/xml/pref_settings.xml @@ -157,6 +157,12 @@ android:summary="10808" android:title="@string/title_pref_socks_port" /> + +