diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/AngApplication.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/AngApplication.kt index a999a9b4..13a31b2b 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/AngApplication.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/AngApplication.kt @@ -7,7 +7,6 @@ import androidx.work.WorkManager import com.tencent.mmkv.MMKV import com.v2ray.ang.AppConfig.ANG_PACKAGE import com.v2ray.ang.handler.SettingsManager -import com.v2ray.ang.util.Utils class AngApplication : MultiDexApplication() { companion object { @@ -36,7 +35,7 @@ class AngApplication : MultiDexApplication() { MMKV.initialize(this) - Utils.setNightMode() + SettingsManager.setNightMode() // Initialize WorkManager with the custom configuration WorkManager.initialize(this, workManagerConfiguration) 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 cf116a4d..50c88dba 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 @@ -4,12 +4,14 @@ import android.content.Context import android.content.res.AssetManager import android.text.TextUtils import android.util.Log +import androidx.appcompat.app.AppCompatDelegate import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig.ANG_PACKAGE import com.v2ray.ang.AppConfig.GEOIP_PRIVATE import com.v2ray.ang.AppConfig.GEOSITE_PRIVATE import com.v2ray.ang.AppConfig.TAG_DIRECT import com.v2ray.ang.dto.EConfigType +import com.v2ray.ang.dto.Language import com.v2ray.ang.dto.ProfileItem import com.v2ray.ang.dto.RoutingType import com.v2ray.ang.dto.RulesetItem @@ -18,10 +20,10 @@ import com.v2ray.ang.handler.MmkvManager.decodeServerConfig import com.v2ray.ang.handler.MmkvManager.decodeServerList import com.v2ray.ang.util.JsonUtil import com.v2ray.ang.util.Utils -import com.v2ray.ang.util.Utils.parseInt import java.io.File import java.io.FileOutputStream import java.util.Collections +import java.util.Locale object SettingsManager { @@ -173,7 +175,7 @@ object SettingsManager { } fun getSocksPort(): Int { - return parseInt(MmkvManager.decodeSettingsString(AppConfig.PREF_SOCKS_PORT), AppConfig.PORT_SOCKS.toInt()) + return Utils.parseInt(MmkvManager.decodeSettingsString(AppConfig.PREF_SOCKS_PORT), AppConfig.PORT_SOCKS.toInt()) } fun getHttpPort(): Int { @@ -205,4 +207,75 @@ object SettingsManager { } } + + /** + * get domestic dns servers from preference + */ + fun getDomesticDnsServers(): List { + val domesticDns = + MmkvManager.decodeSettingsString(AppConfig.PREF_DOMESTIC_DNS) ?: AppConfig.DNS_DIRECT + val ret = domesticDns.split(",").filter { Utils.isPureIpAddress(it) || Utils.isCoreDNSAddress(it) } + if (ret.isEmpty()) { + return listOf(AppConfig.DNS_DIRECT) + } + return ret + } + + /** + * get remote dns servers from preference + */ + fun getRemoteDnsServers(): List { + val remoteDns = + MmkvManager.decodeSettingsString(AppConfig.PREF_REMOTE_DNS) ?: AppConfig.DNS_PROXY + val ret = remoteDns.split(",").filter { Utils.isPureIpAddress(it) || Utils.isCoreDNSAddress(it) } + if (ret.isEmpty()) { + return listOf(AppConfig.DNS_PROXY) + } + return ret + } + + /** + * get vpn dns servers from preference + */ + fun getVpnDnsServers(): List { + val vpnDns = MmkvManager.decodeSettingsString(AppConfig.PREF_VPN_DNS) ?: AppConfig.DNS_VPN + return vpnDns.split(",").filter { Utils.isPureIpAddress(it) } + // allow empty, in that case dns will use system default + } + + + fun getDelayTestUrl(second: Boolean = false): String { + return if (second) { + AppConfig.DelayTestUrl2 + } else { + MmkvManager.decodeSettingsString(AppConfig.PREF_DELAY_TEST_URL) + ?: AppConfig.DelayTestUrl + } + } + + fun getLocale(): Locale { + val langCode = + MmkvManager.decodeSettingsString(AppConfig.PREF_LANGUAGE) ?: Language.AUTO.code + val language = Language.fromCode(langCode) + + return when (language) { + Language.AUTO -> Utils.getSysLocale() + Language.ENGLISH -> Locale.ENGLISH + Language.CHINA -> Locale.CHINA + Language.TRADITIONAL_CHINESE -> Locale.TRADITIONAL_CHINESE + Language.VIETNAMESE -> Locale("vi") + Language.RUSSIAN -> Locale("ru") + Language.PERSIAN -> Locale("fa") + Language.BANGLA -> Locale("bn") + Language.BAKHTIARI -> Locale("bqi", "IR") + } + } + + fun setNightMode() { + when (MmkvManager.decodeSettingsString(AppConfig.PREF_UI_MODE_NIGHT, "0")) { + "0" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) + "1" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) + "2" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) + } + } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2rayConfigManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2rayConfigManager.kt index 72d81345..65321724 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2rayConfigManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2rayConfigManager.kt @@ -271,7 +271,7 @@ object V2rayConfigManager { } // DNS inbound对象 - val remoteDns = Utils.getRemoteDnsServers() + val remoteDns = SettingsManager.getRemoteDnsServers() if (v2rayConfig.inbounds.none { e -> e.protocol == "dokodemo-door" && e.tag == "dns-in" }) { val dnsInboundSettings = V2rayConfig.InboundBean.InSettingsBean( address = if (Utils.isPureIpAddress(remoteDns.first())) remoteDns.first() else AppConfig.DNS_PROXY, @@ -329,7 +329,7 @@ object V2rayConfigManager { val servers = ArrayList() //remote Dns - val remoteDns = Utils.getRemoteDnsServers() + val remoteDns = SettingsManager.getRemoteDnsServers() val proxyDomain = userRule2Domain(TAG_PROXY) remoteDns.forEach { servers.add(it) @@ -344,7 +344,7 @@ object V2rayConfigManager { } // domestic DNS - val domesticDns = Utils.getDomesticDnsServers() + val domesticDns = SettingsManager.getDomesticDnsServers() val directDomain = userRule2Domain(TAG_DIRECT) val isCnRoutingMode = directDomain.contains(GEOSITE_CN) val geoipCn = arrayListOf(GEOIP_CN) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayProxyOnlyService.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayProxyOnlyService.kt index 4d387a45..589e2c6f 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayProxyOnlyService.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayProxyOnlyService.kt @@ -6,8 +6,8 @@ import android.content.Intent import android.os.Build import android.os.IBinder import androidx.annotation.RequiresApi +import com.v2ray.ang.handler.SettingsManager import com.v2ray.ang.util.MyContextWrapper -import com.v2ray.ang.util.Utils import java.lang.ref.SoftReference class V2RayProxyOnlyService : Service(), ServiceControl { @@ -49,7 +49,7 @@ class V2RayProxyOnlyService : Service(), ServiceControl { @RequiresApi(Build.VERSION_CODES.N) override fun attachBaseContext(newBase: Context?) { val context = newBase?.let { - MyContextWrapper.wrap(newBase, Utils.getLocale()) + MyContextWrapper.wrap(newBase, SettingsManager.getLocale()) } super.attachBaseContext(context) } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayServiceManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayServiceManager.kt index 8e273692..3d36d24e 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayServiceManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayServiceManager.kt @@ -15,6 +15,7 @@ import com.v2ray.ang.dto.EConfigType import com.v2ray.ang.dto.ProfileItem import com.v2ray.ang.extension.toast import com.v2ray.ang.handler.MmkvManager +import com.v2ray.ang.handler.SettingsManager import com.v2ray.ang.handler.V2rayConfigManager import com.v2ray.ang.util.MessageUtil import com.v2ray.ang.util.PluginUtil @@ -176,14 +177,14 @@ object V2RayServiceManager { var errstr = "" if (v2rayPoint.isRunning) { try { - time = v2rayPoint.measureDelay(Utils.getDelayTestUrl()) + time = v2rayPoint.measureDelay(SettingsManager.getDelayTestUrl()) } catch (e: Exception) { Log.d(ANG_PACKAGE, "measureV2rayDelay: $e") errstr = e.message?.substringAfter("\":") ?: "empty message" } if (time == -1L) { try { - time = v2rayPoint.measureDelay(Utils.getDelayTestUrl(true)) + time = v2rayPoint.measureDelay(SettingsManager.getDelayTestUrl(true)) } catch (e: Exception) { Log.d(ANG_PACKAGE, "measureV2rayDelay: $e") errstr = e.message?.substringAfter("\":") ?: "empty message" diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayVpnService.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayVpnService.kt index 57e36ce0..11b12668 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayVpnService.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayVpnService.kt @@ -133,7 +133,7 @@ class V2RayVpnService : VpnService(), ServiceControl { @RequiresApi(Build.VERSION_CODES.N) override fun attachBaseContext(newBase: Context?) { val context = newBase?.let { - MyContextWrapper.wrap(newBase, Utils.getLocale()) + MyContextWrapper.wrap(newBase, SettingsManager.getLocale()) } super.attachBaseContext(context) } @@ -182,7 +182,7 @@ class V2RayVpnService : VpnService(), ServiceControl { // if (MmkvManager.decodeSettingsBool(AppConfig.PREF_LOCAL_DNS_ENABLED) == true) { // builder.addDnsServer(PRIVATE_VLAN4_ROUTER) // } else { - Utils.getVpnDnsServers() + SettingsManager.getVpnDnsServers() .forEach { if (Utils.isPureIpAddress(it)) { builder.addDnsServer(it) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BaseActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BaseActivity.kt index f2d4ba94..46287ceb 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BaseActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BaseActivity.kt @@ -7,6 +7,7 @@ import android.view.MenuItem import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.core.view.WindowCompat +import com.v2ray.ang.handler.SettingsManager import com.v2ray.ang.util.MyContextWrapper import com.v2ray.ang.util.Utils @@ -34,6 +35,6 @@ abstract class BaseActivity : AppCompatActivity() { @RequiresApi(Build.VERSION_CODES.N) override fun attachBaseContext(newBase: Context?) { - super.attachBaseContext(MyContextWrapper.wrap(newBase ?: return, Utils.getLocale())) + super.attachBaseContext(MyContextWrapper.wrap(newBase ?: return, SettingsManager.getLocale())) } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/util/SpeedtestUtil.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/util/SpeedtestUtil.kt index 6aae9bfc..166d9198 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/util/SpeedtestUtil.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/util/SpeedtestUtil.kt @@ -7,6 +7,7 @@ import android.util.Log import com.v2ray.ang.AppConfig import com.v2ray.ang.R import com.v2ray.ang.extension.responseLength +import com.v2ray.ang.handler.SettingsManager import kotlinx.coroutines.isActive import libv2ray.Libv2ray import java.io.IOException @@ -35,7 +36,7 @@ object SpeedtestUtil { fun realPing(config: String): Long { return try { - Libv2ray.measureOutboundDelay(config, Utils.getDelayTestUrl()) + Libv2ray.measureOutboundDelay(config, SettingsManager.getDelayTestUrl()) } catch (e: Exception) { Log.d(AppConfig.ANG_PACKAGE, "realPing: $e") -1L @@ -98,7 +99,7 @@ object SpeedtestUtil { var result: String var elapsed = -1L - val conn = HttpUtil.createProxyConnection(Utils.getDelayTestUrl(), port, 30000, 30000) ?: return Pair(elapsed, "") + val conn = HttpUtil.createProxyConnection(SettingsManager.getDelayTestUrl(), port, 30000, 30000) ?: return Pair(elapsed, "") try { val start = SystemClock.elapsedRealtime() val code = conn.responseCode diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt index 6f257717..54bdd16f 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt @@ -15,14 +15,11 @@ import android.util.Base64 import android.util.Log import android.util.Patterns import android.webkit.URLUtil -import androidx.appcompat.app.AppCompatDelegate import androidx.core.content.ContextCompat import androidx.core.net.toUri import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig.ANG_PACKAGE import com.v2ray.ang.AppConfig.LOOPBACK -import com.v2ray.ang.dto.Language -import com.v2ray.ang.handler.MmkvManager import java.io.IOException import java.net.ServerSocket import java.net.URLDecoder @@ -126,37 +123,6 @@ object Utils { } } - /** - * get remote dns servers from preference - */ - fun getRemoteDnsServers(): List { - val remoteDns = - MmkvManager.decodeSettingsString(AppConfig.PREF_REMOTE_DNS) ?: AppConfig.DNS_PROXY - val ret = remoteDns.split(",").filter { isPureIpAddress(it) || isCoreDNSAddress(it) } - if (ret.isEmpty()) { - return listOf(AppConfig.DNS_PROXY) - } - return ret - } - - fun getVpnDnsServers(): List { - val vpnDns = MmkvManager.decodeSettingsString(AppConfig.PREF_VPN_DNS) ?: AppConfig.DNS_VPN - return vpnDns.split(",").filter { isPureIpAddress(it) } - // allow empty, in that case dns will use system default - } - - /** - * get remote dns servers from preference - */ - fun getDomesticDnsServers(): List { - val domesticDns = - MmkvManager.decodeSettingsString(AppConfig.PREF_DOMESTIC_DNS) ?: AppConfig.DNS_DIRECT - val ret = domesticDns.split(",").filter { isPureIpAddress(it) || isCoreDNSAddress(it) } - if (ret.isEmpty()) { - return listOf(AppConfig.DNS_DIRECT) - } - return ret - } /** * is ip address @@ -224,7 +190,7 @@ object Utils { return regV6.matches(addr) } - private fun isCoreDNSAddress(s: String): Boolean { + fun isCoreDNSAddress(s: String): Boolean { return s.startsWith("https") || s.startsWith("tcp") || s.startsWith("quic") @@ -327,15 +293,6 @@ object Utils { return context.resources.configuration.uiMode and UI_MODE_NIGHT_MASK != UI_MODE_NIGHT_NO } - - fun setNightMode() { - when (MmkvManager.decodeSettingsString(AppConfig.PREF_UI_MODE_NIGHT, "0")) { - "0" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) - "1" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) - "2" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) - } - } - fun getIpv6Address(address: String?): String { if (address == null) { return "" @@ -347,26 +304,7 @@ object Utils { } } - fun getLocale(): Locale { - val langCode = - MmkvManager.decodeSettingsString(AppConfig.PREF_LANGUAGE) ?: Language.AUTO.code - val language = Language.fromCode(langCode) - - return when (language) { - Language.AUTO -> getSysLocale() - Language.ENGLISH -> Locale.ENGLISH - Language.CHINA -> Locale.CHINA - Language.TRADITIONAL_CHINESE -> Locale.TRADITIONAL_CHINESE - Language.VIETNAMESE -> Locale("vi") - Language.RUSSIAN -> Locale("ru") - Language.PERSIAN -> Locale("fa") - Language.BANGLA -> Locale("bn") - Language.BAKHTIARI -> Locale("bqi", "IR") - } - } - - - private fun getSysLocale(): Locale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + fun getSysLocale(): Locale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { LocaleList.getDefault()[0] } else { Locale.getDefault() @@ -385,15 +323,6 @@ object Utils { fun isTv(context: Context): Boolean = context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK) - fun getDelayTestUrl(second: Boolean = false): String { - return if (second) { - AppConfig.DelayTestUrl2 - } else { - MmkvManager.decodeSettingsString(AppConfig.PREF_DELAY_TEST_URL) - ?: AppConfig.DelayTestUrl - } - } - fun findFreePort(ports: List): Int { for (port in ports) { try { diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt index 9e73ff39..96c92225 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt @@ -7,7 +7,7 @@ import androidx.lifecycle.AndroidViewModel import androidx.preference.PreferenceManager import com.v2ray.ang.AppConfig import com.v2ray.ang.handler.MmkvManager -import com.v2ray.ang.util.Utils +import com.v2ray.ang.handler.SettingsManager class SettingsViewModel(application: Application) : AndroidViewModel(application), SharedPreferences.OnSharedPreferenceChangeListener { @@ -83,7 +83,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application // } } if (key == AppConfig.PREF_UI_MODE_NIGHT) { - Utils.setNightMode() + SettingsManager.setNightMode() } } }