Optimize and improve SettingsManager

This commit is contained in:
2dust
2025-03-19 10:38:58 +08:00
parent 0165ad54b3
commit 093716baaa
10 changed files with 95 additions and 91 deletions

View File

@@ -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)

View File

@@ -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<String> {
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<String> {
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<String> {
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)
}
}
}

View File

@@ -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<Any>()
//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)

View File

@@ -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)
}

View File

@@ -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"

View File

@@ -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)

View File

@@ -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()))
}
}

View File

@@ -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

View File

@@ -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<String> {
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<String> {
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<String> {
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>): Int {
for (port in ports) {
try {

View File

@@ -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()
}
}
}