Migrate settings storage to MMKV and add PreferenceDataStore
Replaces SharedPreferences with MMKV for all settings by introducing MmkvPreferenceDataStore and updating SettingsActivity to use it. Adds encode/decode helpers for more types in MmkvManager, ensures default settings are initialized in SettingsManager, and removes the unused FragmentAdapter. This change improves consistency and reliability of settings storage.
This commit is contained in:
1 parent
a87d5d375b
commit
e684bef35d
6 files changed
+392
-202
No files matched your search
@@ -34,6 +34,8 @@ class AngApplication : MultiDexApplication() {
|
||||
|
||||
MMKV.initialize(this)
|
||||
|
||||
// Ensure critical preference defaults are present in MMKV early
|
||||
SettingsManager.ensureDefaultSettings()
|
||||
SettingsManager.setNightMode()
|
||||
// Initialize WorkManager with the custom configuration
|
||||
WorkManager.initialize(this, workManagerConfiguration)
|
||||
|
||||
@@ -493,6 +493,28 @@ object MmkvManager {
|
||||
return settingsStorage.encode(key, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the settings.
|
||||
*
|
||||
* @param key The settings key.
|
||||
* @param value The settings value.
|
||||
* @return Whether the encoding was successful.
|
||||
*/
|
||||
fun encodeSettings(key: String, value: Long): Boolean {
|
||||
return settingsStorage.encode(key, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the settings.
|
||||
*
|
||||
* @param key The settings key.
|
||||
* @param value The settings value.
|
||||
* @return Whether the encoding was successful.
|
||||
*/
|
||||
fun encodeSettings(key: String, value: Float): Boolean {
|
||||
return settingsStorage.encode(key, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the settings.
|
||||
*
|
||||
@@ -536,6 +558,39 @@ object MmkvManager {
|
||||
return settingsStorage.decodeString(key, defaultValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the settings integer.
|
||||
*
|
||||
* @param key The settings key.
|
||||
* @param defaultValue The default value.
|
||||
* @return The settings value.
|
||||
*/
|
||||
fun decodeSettingsInt(key: String, defaultValue: Int): Int {
|
||||
return settingsStorage.decodeInt(key, defaultValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the settings long.
|
||||
*
|
||||
* @param key The settings key.
|
||||
* @param defaultValue The default value.
|
||||
* @return The settings value.
|
||||
*/
|
||||
fun decodeSettingsLong(key: String, defaultValue: Long): Long {
|
||||
return settingsStorage.decodeLong(key, defaultValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the settings float.
|
||||
*
|
||||
* @param key The settings key.
|
||||
* @param defaultValue The default value.
|
||||
* @return The settings value.
|
||||
*/
|
||||
fun decodeSettingsFloat(key: String, defaultValue: Float): Float {
|
||||
return settingsStorage.decodeFloat(key, defaultValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the settings boolean.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.v2ray.ang.handler
|
||||
|
||||
import androidx.preference.PreferenceDataStore
|
||||
import com.v2ray.ang.AppConfig
|
||||
|
||||
/**
|
||||
* PreferenceDataStore implementation that bridges AndroidX Preference framework to MMKV storage.
|
||||
* This ensures that all Preference UI operations read/write directly from/to MMKV,
|
||||
* avoiding inconsistencies between SharedPreferences and MMKV.
|
||||
*/
|
||||
class MmkvPreferenceDataStore : PreferenceDataStore() {
|
||||
|
||||
override fun putString(key: String, value: String?) {
|
||||
MmkvManager.encodeSettings(key, value)
|
||||
notifySettingChanged(key)
|
||||
}
|
||||
|
||||
override fun getString(key: String, defaultValue: String?): String? {
|
||||
return MmkvManager.decodeSettingsString(key, defaultValue)
|
||||
}
|
||||
|
||||
override fun putInt(key: String, value: Int) {
|
||||
MmkvManager.encodeSettings(key, value)
|
||||
notifySettingChanged(key)
|
||||
}
|
||||
|
||||
override fun getInt(key: String, defaultValue: Int): Int {
|
||||
return MmkvManager.decodeSettingsInt(key, defaultValue)
|
||||
}
|
||||
|
||||
override fun putLong(key: String, value: Long) {
|
||||
MmkvManager.encodeSettings(key, value)
|
||||
notifySettingChanged(key)
|
||||
}
|
||||
|
||||
override fun getLong(key: String, defaultValue: Long): Long {
|
||||
return MmkvManager.decodeSettingsLong(key, defaultValue)
|
||||
}
|
||||
|
||||
override fun putFloat(key: String, value: Float) {
|
||||
MmkvManager.encodeSettings(key, value)
|
||||
notifySettingChanged(key)
|
||||
}
|
||||
|
||||
override fun getFloat(key: String, defaultValue: Float): Float {
|
||||
return MmkvManager.decodeSettingsFloat(key, defaultValue)
|
||||
}
|
||||
|
||||
override fun putBoolean(key: String, value: Boolean) {
|
||||
MmkvManager.encodeSettings(key, value)
|
||||
notifySettingChanged(key)
|
||||
}
|
||||
|
||||
override fun getBoolean(key: String, defaultValue: Boolean): Boolean {
|
||||
return MmkvManager.decodeSettingsBool(key, defaultValue)
|
||||
}
|
||||
|
||||
override fun putStringSet(key: String, values: MutableSet<String>?) {
|
||||
if (values == null) {
|
||||
MmkvManager.encodeSettings(key, null as String?)
|
||||
} else {
|
||||
MmkvManager.encodeSettings(key, values)
|
||||
}
|
||||
notifySettingChanged(key)
|
||||
}
|
||||
|
||||
override fun getStringSet(key: String, defaultValues: MutableSet<String>?): MutableSet<String>? {
|
||||
return MmkvManager.decodeSettingsStringSet(key) ?: defaultValues
|
||||
}
|
||||
|
||||
// Internal helper: notify other modules about setting changes
|
||||
private fun notifySettingChanged(key: String) {
|
||||
// Call SettingsManager.setNightMode if UI mode changed
|
||||
if (key == AppConfig.PREF_UI_MODE_NIGHT) {
|
||||
SettingsManager.setNightMode()
|
||||
}
|
||||
// Notify listeners that require service restart or reinit
|
||||
SettingsChangeManager.makeRestartService()
|
||||
}
|
||||
}
|
||||
@@ -377,4 +377,31 @@ object SettingsManager {
|
||||
fun getVpnMtu(): Int {
|
||||
return Utils.parseInt(MmkvManager.decodeSettingsString(AppConfig.PREF_VPN_MTU), AppConfig.VPN_MTU)
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure default settings are present in MMKV.
|
||||
*/
|
||||
fun ensureDefaultSettings() {
|
||||
// Write defaults in the exact order requested by the user
|
||||
ensureDefaultValue(AppConfig.PREF_MODE, AppConfig.VPN)
|
||||
ensureDefaultValue(AppConfig.PREF_VPN_DNS, AppConfig.DNS_VPN)
|
||||
ensureDefaultValue(AppConfig.PREF_VPN_MTU, AppConfig.VPN_MTU.toString())
|
||||
ensureDefaultValue(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL, AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL)
|
||||
ensureDefaultValue(AppConfig.PREF_SOCKS_PORT, AppConfig.PORT_SOCKS.toString())
|
||||
ensureDefaultValue(AppConfig.PREF_REMOTE_DNS, AppConfig.DNS_PROXY)
|
||||
ensureDefaultValue(AppConfig.PREF_DOMESTIC_DNS, AppConfig.DNS_DIRECT)
|
||||
ensureDefaultValue(AppConfig.PREF_DELAY_TEST_URL, AppConfig.DELAY_TEST_URL)
|
||||
ensureDefaultValue(AppConfig.PREF_IP_API_URL, AppConfig.IP_API_URL)
|
||||
ensureDefaultValue(AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT, AppConfig.HEVTUN_RW_TIMEOUT)
|
||||
ensureDefaultValue(AppConfig.PREF_MUX_CONCURRENCY, "8")
|
||||
ensureDefaultValue(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8")
|
||||
ensureDefaultValue(AppConfig.PREF_FRAGMENT_LENGTH, "50-100")
|
||||
ensureDefaultValue(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20")
|
||||
}
|
||||
|
||||
private fun ensureDefaultValue(key: String, default: String) {
|
||||
if (MmkvManager.decodeSettingsString(key).isNullOrEmpty()) {
|
||||
MmkvManager.encodeSettings(key, default)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.v2ray.ang.ui
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
|
||||
class FragmentAdapter(fragmentActivity: FragmentActivity, private val mFragments: List<Fragment>) :
|
||||
FragmentStateAdapter(fragmentActivity) {
|
||||
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
return mFragments[position]
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mFragments.size
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package com.v2ray.ang.ui
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import androidx.activity.viewModels
|
||||
import androidx.preference.CheckBoxPreference
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.ListPreference
|
||||
@@ -17,20 +16,20 @@ import com.v2ray.ang.AppConfig.VPN
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.extension.toLongEx
|
||||
import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.handler.MmkvPreferenceDataStore
|
||||
import com.v2ray.ang.handler.SubscriptionUpdater
|
||||
import com.v2ray.ang.util.Utils
|
||||
import com.v2ray.ang.viewmodel.SettingsViewModel
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class SettingsActivity : BaseActivity() {
|
||||
private val settingsViewModel: SettingsViewModel by viewModels()
|
||||
//private val settingsViewModel: SettingsViewModel by viewModels()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
//setContentView(R.layout.activity_settings)
|
||||
setContentViewWithToolbar(R.layout.activity_settings, showHomeAsUp = true, title = getString(R.string.title_settings))
|
||||
|
||||
settingsViewModel.startListenPreferenceChange()
|
||||
//settingsViewModel.startListenPreferenceChange()
|
||||
}
|
||||
|
||||
class SettingsFragment : PreferenceFragmentCompat() {
|
||||
@@ -58,21 +57,27 @@ class SettingsActivity : BaseActivity() {
|
||||
private val autoUpdateCheck by lazy { findPreference<CheckBoxPreference>(AppConfig.SUBSCRIPTION_AUTO_UPDATE) }
|
||||
private val autoUpdateInterval by lazy { findPreference<EditTextPreference>(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL) }
|
||||
|
||||
private val socksPort by lazy { findPreference<EditTextPreference>(AppConfig.PREF_SOCKS_PORT) }
|
||||
private val remoteDns by lazy { findPreference<EditTextPreference>(AppConfig.PREF_REMOTE_DNS) }
|
||||
private val domesticDns by lazy { findPreference<EditTextPreference>(AppConfig.PREF_DOMESTIC_DNS) }
|
||||
private val dnsHosts by lazy { findPreference<EditTextPreference>(AppConfig.PREF_DNS_HOSTS) }
|
||||
private val delayTestUrl by lazy { findPreference<EditTextPreference>(AppConfig.PREF_DELAY_TEST_URL) }
|
||||
private val ipApiUrl by lazy { findPreference<EditTextPreference>(AppConfig.PREF_IP_API_URL) }
|
||||
// private val socksPort by lazy { findPreference<EditTextPreference>(AppConfig.PREF_SOCKS_PORT) }
|
||||
// private val remoteDns by lazy { findPreference<EditTextPreference>(AppConfig.PREF_REMOTE_DNS) }
|
||||
// private val domesticDns by lazy { findPreference<EditTextPreference>(AppConfig.PREF_DOMESTIC_DNS) }
|
||||
// private val dnsHosts by lazy { findPreference<EditTextPreference>(AppConfig.PREF_DNS_HOSTS) }
|
||||
// private val delayTestUrl by lazy { findPreference<EditTextPreference>(AppConfig.PREF_DELAY_TEST_URL) }
|
||||
// private val ipApiUrl by lazy { findPreference<EditTextPreference>(AppConfig.PREF_IP_API_URL) }
|
||||
private val mode by lazy { findPreference<ListPreference>(AppConfig.PREF_MODE) }
|
||||
|
||||
private val hevTunLogLevel by lazy { findPreference<ListPreference>(AppConfig.PREF_HEV_TUNNEL_LOGLEVEL) }
|
||||
private val hevTunRwTimeout by lazy { findPreference<EditTextPreference>(AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT) }
|
||||
// private val hevTunLogLevel by lazy { findPreference<ListPreference>(AppConfig.PREF_HEV_TUNNEL_LOGLEVEL) }
|
||||
// private val hevTunRwTimeout by lazy { findPreference<EditTextPreference>(AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT) }
|
||||
// private val useHevTun by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_USE_HEV_TUNNEL) }
|
||||
|
||||
override fun onCreatePreferences(bundle: Bundle?, s: String?) {
|
||||
// Use MMKV as the storage backend for all Preferences
|
||||
// This prevents inconsistencies between SharedPreferences and MMKV
|
||||
preferenceManager.preferenceDataStore = MmkvPreferenceDataStore()
|
||||
|
||||
addPreferencesFromResource(R.xml.pref_settings)
|
||||
|
||||
initPreferenceSummaries()
|
||||
|
||||
// perAppProxy?.setOnPreferenceClickListener {
|
||||
// startActivity(Intent(activity, PerAppProxyActivity::class.java))
|
||||
// perAppProxy?.isChecked = true
|
||||
@@ -87,16 +92,16 @@ class SettingsActivity : BaseActivity() {
|
||||
// localDnsPort?.summary = nval.ifEmpty { AppConfig.PORT_LOCAL_DNS }
|
||||
// true
|
||||
// }
|
||||
vpnDns?.setOnPreferenceChangeListener { _, any ->
|
||||
vpnDns?.summary = any as String
|
||||
true
|
||||
}
|
||||
// vpnDns?.setOnPreferenceChangeListener { _, any ->
|
||||
// vpnDns?.summary = any as String
|
||||
// true
|
||||
// }
|
||||
|
||||
vpnMtu?.setOnPreferenceChangeListener { _, any ->
|
||||
val nval = any as String
|
||||
vpnMtu?.summary = nval.ifEmpty { AppConfig.VPN_MTU.toString() }
|
||||
true
|
||||
}
|
||||
// vpnMtu?.setOnPreferenceChangeListener { _, any ->
|
||||
// val nval = any as String
|
||||
// vpnMtu?.summary = nval.ifEmpty { AppConfig.VPN_MTU.toString() }
|
||||
// true
|
||||
// }
|
||||
|
||||
mux?.setOnPreferenceChangeListener { _, newValue ->
|
||||
updateMux(newValue as Boolean)
|
||||
@@ -115,18 +120,18 @@ class SettingsActivity : BaseActivity() {
|
||||
updateFragment(newValue as Boolean)
|
||||
true
|
||||
}
|
||||
fragmentPackets?.setOnPreferenceChangeListener { _, newValue ->
|
||||
updateFragmentPackets(newValue as String)
|
||||
true
|
||||
}
|
||||
fragmentLength?.setOnPreferenceChangeListener { _, newValue ->
|
||||
updateFragmentLength(newValue as String)
|
||||
true
|
||||
}
|
||||
fragmentInterval?.setOnPreferenceChangeListener { _, newValue ->
|
||||
updateFragmentInterval(newValue as String)
|
||||
true
|
||||
}
|
||||
// fragmentPackets?.setOnPreferenceChangeListener { _, newValue ->
|
||||
// updateFragmentPackets(newValue as String)
|
||||
// true
|
||||
// }
|
||||
// fragmentLength?.setOnPreferenceChangeListener { _, newValue ->
|
||||
// updateFragmentLength(newValue as String)
|
||||
// true
|
||||
// }
|
||||
// fragmentInterval?.setOnPreferenceChangeListener { _, newValue ->
|
||||
// updateFragmentInterval(newValue as String)
|
||||
// true
|
||||
// }
|
||||
|
||||
autoUpdateCheck?.setOnPreferenceChangeListener { _, newValue ->
|
||||
val value = newValue as Boolean
|
||||
@@ -137,48 +142,48 @@ class SettingsActivity : BaseActivity() {
|
||||
}
|
||||
true
|
||||
}
|
||||
autoUpdateInterval?.setOnPreferenceChangeListener { _, any ->
|
||||
var nval = any as String
|
||||
// autoUpdateInterval?.setOnPreferenceChangeListener { _, any ->
|
||||
// var nval = any as String
|
||||
//
|
||||
// // It must be greater than 15 minutes because WorkManager couldn't run tasks under 15 minutes intervals
|
||||
// nval =
|
||||
// if (TextUtils.isEmpty(nval) || nval.toLongEx() < 15) AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL else nval
|
||||
// autoUpdateInterval?.summary = nval
|
||||
// configureUpdateTask(nval.toLongEx())
|
||||
// true
|
||||
// }
|
||||
|
||||
// It must be greater than 15 minutes because WorkManager couldn't run tasks under 15 minutes intervals
|
||||
nval =
|
||||
if (TextUtils.isEmpty(nval) || nval.toLongEx() < 15) AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL else nval
|
||||
autoUpdateInterval?.summary = nval
|
||||
configureUpdateTask(nval.toLongEx())
|
||||
true
|
||||
}
|
||||
|
||||
socksPort?.setOnPreferenceChangeListener { _, any ->
|
||||
val nval = any as String
|
||||
socksPort?.summary = nval.ifEmpty { AppConfig.PORT_SOCKS }
|
||||
true
|
||||
}
|
||||
|
||||
remoteDns?.setOnPreferenceChangeListener { _, any ->
|
||||
val nval = any as String
|
||||
remoteDns?.summary = nval.ifEmpty { AppConfig.DNS_PROXY }
|
||||
true
|
||||
}
|
||||
domesticDns?.setOnPreferenceChangeListener { _, any ->
|
||||
val nval = any as String
|
||||
domesticDns?.summary = nval.ifEmpty { AppConfig.DNS_DIRECT }
|
||||
true
|
||||
}
|
||||
dnsHosts?.setOnPreferenceChangeListener { _, any ->
|
||||
val nval = any as String
|
||||
dnsHosts?.summary = nval
|
||||
true
|
||||
}
|
||||
delayTestUrl?.setOnPreferenceChangeListener { _, any ->
|
||||
val nval = any as String
|
||||
delayTestUrl?.summary = nval.ifEmpty { AppConfig.DELAY_TEST_URL }
|
||||
true
|
||||
}
|
||||
ipApiUrl?.setOnPreferenceChangeListener { _, any ->
|
||||
val nval = any as String
|
||||
ipApiUrl?.summary = nval.ifEmpty { AppConfig.IP_API_URL }
|
||||
true
|
||||
}
|
||||
// socksPort?.setOnPreferenceChangeListener { _, any ->
|
||||
// val nval = any as String
|
||||
// socksPort?.summary = nval.ifEmpty { AppConfig.PORT_SOCKS }
|
||||
// true
|
||||
// }
|
||||
//
|
||||
// remoteDns?.setOnPreferenceChangeListener { _, any ->
|
||||
// val nval = any as String
|
||||
// remoteDns?.summary = nval.ifEmpty { AppConfig.DNS_PROXY }
|
||||
// true
|
||||
// }
|
||||
// domesticDns?.setOnPreferenceChangeListener { _, any ->
|
||||
// val nval = any as String
|
||||
// domesticDns?.summary = nval.ifEmpty { AppConfig.DNS_DIRECT }
|
||||
// true
|
||||
// }
|
||||
// dnsHosts?.setOnPreferenceChangeListener { _, any ->
|
||||
// val nval = any as String
|
||||
// dnsHosts?.summary = nval
|
||||
// true
|
||||
// }
|
||||
// delayTestUrl?.setOnPreferenceChangeListener { _, any ->
|
||||
// val nval = any as String
|
||||
// delayTestUrl?.summary = nval.ifEmpty { AppConfig.DELAY_TEST_URL }
|
||||
// true
|
||||
// }
|
||||
// ipApiUrl?.setOnPreferenceChangeListener { _, any ->
|
||||
// val nval = any as String
|
||||
// ipApiUrl?.summary = nval.ifEmpty { AppConfig.IP_API_URL }
|
||||
// true
|
||||
// }
|
||||
mode?.setOnPreferenceChangeListener { _, newValue ->
|
||||
updateMode(newValue.toString())
|
||||
true
|
||||
@@ -191,113 +196,151 @@ class SettingsActivity : BaseActivity() {
|
||||
// true
|
||||
// }
|
||||
|
||||
hevTunRwTimeout?.setOnPreferenceChangeListener { _, any ->
|
||||
val nval = any as String
|
||||
hevTunRwTimeout?.summary = nval.ifEmpty { AppConfig.HEVTUN_RW_TIMEOUT }
|
||||
true
|
||||
// hevTunRwTimeout?.setOnPreferenceChangeListener { _, any ->
|
||||
// val nval = any as String
|
||||
// hevTunRwTimeout?.summary = nval.ifEmpty { AppConfig.HEVTUN_RW_TIMEOUT }
|
||||
// true
|
||||
// }
|
||||
}
|
||||
|
||||
private fun initPreferenceSummaries() {
|
||||
fun updateSummary(pref: androidx.preference.Preference) {
|
||||
when (pref) {
|
||||
is EditTextPreference -> {
|
||||
pref.summary = pref.text.orEmpty()
|
||||
pref.setOnPreferenceChangeListener { p, newValue ->
|
||||
p.summary = (newValue as? String).orEmpty()
|
||||
true
|
||||
}
|
||||
}
|
||||
is ListPreference -> {
|
||||
pref.summary = pref.entry ?: ""
|
||||
pref.setOnPreferenceChangeListener { p, newValue ->
|
||||
val lp = p as ListPreference
|
||||
val idx = lp.findIndexOfValue(newValue as? String)
|
||||
lp.summary = (if (idx >= 0) lp.entries[idx] else newValue) as CharSequence?
|
||||
true
|
||||
}
|
||||
}
|
||||
is CheckBoxPreference, is androidx.preference.SwitchPreferenceCompat -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun traverse(group: androidx.preference.PreferenceGroup) {
|
||||
for (i in 0 until group.preferenceCount) {
|
||||
val p = group.getPreference(i)
|
||||
when (p) {
|
||||
is androidx.preference.PreferenceGroup -> traverse(p)
|
||||
else -> updateSummary(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
preferenceScreen?.let { traverse(it) }
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
// Initialize mode-dependent UI states
|
||||
updateMode(MmkvManager.decodeSettingsString(AppConfig.PREF_MODE, VPN))
|
||||
localDns?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_LOCAL_DNS_ENABLED, false)
|
||||
fakeDns?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_FAKE_DNS_ENABLED, false)
|
||||
appendHttpProxy?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_APPEND_HTTP_PROXY, false)
|
||||
// localDnsPort?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_LOCAL_DNS_PORT, AppConfig.PORT_LOCAL_DNS)
|
||||
vpnDns?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_VPN_DNS, AppConfig.DNS_VPN)
|
||||
vpnMtu?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_VPN_MTU, AppConfig.VPN_MTU.toString())
|
||||
|
||||
// Initialize mux-dependent UI states
|
||||
updateMux(MmkvManager.decodeSettingsBool(AppConfig.PREF_MUX_ENABLED, false))
|
||||
mux?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_MUX_ENABLED, false)
|
||||
muxConcurrency?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_MUX_CONCURRENCY, "8")
|
||||
muxXudpConcurrency?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8")
|
||||
|
||||
// Initialize fragment-dependent UI states
|
||||
updateFragment(MmkvManager.decodeSettingsBool(AppConfig.PREF_FRAGMENT_ENABLED, false))
|
||||
fragment?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_FRAGMENT_ENABLED, false)
|
||||
fragmentPackets?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_PACKETS, "tlshello")
|
||||
fragmentLength?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_LENGTH, "50-100")
|
||||
fragmentInterval?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20")
|
||||
|
||||
autoUpdateCheck?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.SUBSCRIPTION_AUTO_UPDATE, false)
|
||||
autoUpdateInterval?.summary =
|
||||
MmkvManager.decodeSettingsString(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL, AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL)
|
||||
// Initialize auto-update interval state
|
||||
autoUpdateInterval?.isEnabled = MmkvManager.decodeSettingsBool(AppConfig.SUBSCRIPTION_AUTO_UPDATE, false)
|
||||
|
||||
socksPort?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_SOCKS_PORT, AppConfig.PORT_SOCKS)
|
||||
remoteDns?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_REMOTE_DNS, AppConfig.DNS_PROXY)
|
||||
domesticDns?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_DOMESTIC_DNS, AppConfig.DNS_DIRECT)
|
||||
dnsHosts?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_DNS_HOSTS)
|
||||
delayTestUrl?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_DELAY_TEST_URL, AppConfig.DELAY_TEST_URL)
|
||||
ipApiUrl?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_IP_API_URL, AppConfig.IP_API_URL)
|
||||
// localDns?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_LOCAL_DNS_ENABLED, false)
|
||||
// fakeDns?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_FAKE_DNS_ENABLED, false)
|
||||
// appendHttpProxy?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_APPEND_HTTP_PROXY, false)
|
||||
// vpnDns?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_VPN_DNS, AppConfig.DNS_VPN)
|
||||
// vpnMtu?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_VPN_MTU, AppConfig.VPN_MTU.toString())
|
||||
// mux?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_MUX_ENABLED, false)
|
||||
// muxConcurrency?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_MUX_CONCURRENCY, "8")
|
||||
// muxXudpConcurrency?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8")
|
||||
// fragment?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_FRAGMENT_ENABLED, false)
|
||||
// fragmentPackets?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_PACKETS, "tlshello")
|
||||
// fragmentLength?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_LENGTH, "50-100")
|
||||
// fragmentInterval?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20")
|
||||
// autoUpdateCheck?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.SUBSCRIPTION_AUTO_UPDATE, false)
|
||||
// autoUpdateInterval?.summary =
|
||||
// MmkvManager.decodeSettingsString(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL, AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL)
|
||||
// socksPort?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_SOCKS_PORT, AppConfig.PORT_SOCKS)
|
||||
// remoteDns?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_REMOTE_DNS, AppConfig.DNS_PROXY)
|
||||
// domesticDns?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_DOMESTIC_DNS, AppConfig.DNS_DIRECT)
|
||||
// dnsHosts?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_DNS_HOSTS)
|
||||
// delayTestUrl?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_DELAY_TEST_URL, AppConfig.DELAY_TEST_URL)
|
||||
// ipApiUrl?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_IP_API_URL, AppConfig.IP_API_URL)
|
||||
// hevTunRwTimeout?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT, AppConfig.HEVTUN_RW_TIMEOUT)
|
||||
|
||||
//updateHevTunSettings(MmkvManager.decodeSettingsBool(AppConfig.PREF_USE_HEV_TUNNEL, true))
|
||||
hevTunRwTimeout?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT, AppConfig.HEVTUN_RW_TIMEOUT)
|
||||
|
||||
initSharedPreference()
|
||||
// initSharedPreference()
|
||||
}
|
||||
|
||||
private fun initSharedPreference() {
|
||||
listOf(
|
||||
//localDnsPort,
|
||||
vpnDns,
|
||||
vpnMtu,
|
||||
muxConcurrency,
|
||||
muxXudpConcurrency,
|
||||
fragmentLength,
|
||||
fragmentInterval,
|
||||
autoUpdateInterval,
|
||||
socksPort,
|
||||
remoteDns,
|
||||
domesticDns,
|
||||
delayTestUrl,
|
||||
ipApiUrl,
|
||||
hevTunRwTimeout
|
||||
).forEach { key ->
|
||||
key?.text = key.summary.toString()
|
||||
}
|
||||
// listOf(
|
||||
// //localDnsPort,
|
||||
// vpnDns,
|
||||
// vpnMtu,
|
||||
// muxConcurrency,
|
||||
// muxXudpConcurrency,
|
||||
// fragmentLength,
|
||||
// fragmentInterval,
|
||||
// autoUpdateInterval,
|
||||
// socksPort,
|
||||
// remoteDns,
|
||||
// domesticDns,
|
||||
// delayTestUrl,
|
||||
// ipApiUrl,
|
||||
// hevTunRwTimeout
|
||||
// ).forEach { key ->
|
||||
// key?.summary = key.text.toString()
|
||||
// }
|
||||
|
||||
listOf(
|
||||
AppConfig.PREF_SNIFFING_ENABLED,
|
||||
AppConfig.PREF_USE_HEV_TUNNEL
|
||||
).forEach { key ->
|
||||
findPreference<CheckBoxPreference>(key)?.isChecked =
|
||||
MmkvManager.decodeSettingsBool(key, true)
|
||||
}
|
||||
|
||||
listOf(
|
||||
AppConfig.PREF_ROUTE_ONLY_ENABLED,
|
||||
AppConfig.PREF_IS_BOOTED,
|
||||
AppConfig.PREF_BYPASS_APPS,
|
||||
AppConfig.PREF_SPEED_ENABLED,
|
||||
AppConfig.PREF_CONFIRM_REMOVE,
|
||||
AppConfig.PREF_START_SCAN_IMMEDIATE,
|
||||
AppConfig.PREF_DOUBLE_COLUMN_DISPLAY,
|
||||
AppConfig.PREF_PREFER_IPV6,
|
||||
AppConfig.PREF_PROXY_SHARING,
|
||||
AppConfig.PREF_ALLOW_INSECURE
|
||||
).forEach { key ->
|
||||
findPreference<CheckBoxPreference>(key)?.isChecked =
|
||||
MmkvManager.decodeSettingsBool(key, false)
|
||||
}
|
||||
|
||||
listOf(
|
||||
AppConfig.PREF_VPN_BYPASS_LAN,
|
||||
AppConfig.PREF_VPN_INTERFACE_ADDRESS_CONFIG_INDEX,
|
||||
AppConfig.PREF_ROUTING_DOMAIN_STRATEGY,
|
||||
AppConfig.PREF_MUX_XUDP_QUIC,
|
||||
AppConfig.PREF_FRAGMENT_PACKETS,
|
||||
AppConfig.PREF_LANGUAGE,
|
||||
AppConfig.PREF_UI_MODE_NIGHT,
|
||||
AppConfig.PREF_LOGLEVEL,
|
||||
AppConfig.PREF_OUTBOUND_DOMAIN_RESOLVE_METHOD,
|
||||
AppConfig.PREF_MODE,
|
||||
AppConfig.PREF_HEV_TUNNEL_LOGLEVEL
|
||||
).forEach { key ->
|
||||
if (MmkvManager.decodeSettingsString(key) != null) {
|
||||
findPreference<ListPreference>(key)?.value = MmkvManager.decodeSettingsString(key)
|
||||
}
|
||||
}
|
||||
// listOf(
|
||||
// AppConfig.PREF_SNIFFING_ENABLED,
|
||||
// AppConfig.PREF_USE_HEV_TUNNEL
|
||||
// ).forEach { key ->
|
||||
// findPreference<CheckBoxPreference>(key)?.isChecked =
|
||||
// MmkvManager.decodeSettingsBool(key, true)
|
||||
// }
|
||||
//
|
||||
// listOf(
|
||||
// AppConfig.PREF_ROUTE_ONLY_ENABLED,
|
||||
// AppConfig.PREF_IS_BOOTED,
|
||||
// AppConfig.PREF_BYPASS_APPS,
|
||||
// AppConfig.PREF_SPEED_ENABLED,
|
||||
// AppConfig.PREF_CONFIRM_REMOVE,
|
||||
// AppConfig.PREF_START_SCAN_IMMEDIATE,
|
||||
// AppConfig.PREF_DOUBLE_COLUMN_DISPLAY,
|
||||
// AppConfig.PREF_PREFER_IPV6,
|
||||
// AppConfig.PREF_PROXY_SHARING,
|
||||
// AppConfig.PREF_ALLOW_INSECURE
|
||||
// ).forEach { key ->
|
||||
// findPreference<CheckBoxPreference>(key)?.isChecked =
|
||||
// MmkvManager.decodeSettingsBool(key, false)
|
||||
// }
|
||||
//
|
||||
// listOf(
|
||||
// AppConfig.PREF_VPN_BYPASS_LAN,
|
||||
// AppConfig.PREF_VPN_INTERFACE_ADDRESS_CONFIG_INDEX,
|
||||
// AppConfig.PREF_ROUTING_DOMAIN_STRATEGY,
|
||||
// AppConfig.PREF_MUX_XUDP_QUIC,
|
||||
// AppConfig.PREF_FRAGMENT_PACKETS,
|
||||
// AppConfig.PREF_LANGUAGE,
|
||||
// AppConfig.PREF_UI_MODE_NIGHT,
|
||||
// AppConfig.PREF_LOGLEVEL,
|
||||
// AppConfig.PREF_OUTBOUND_DOMAIN_RESOLVE_METHOD,
|
||||
// AppConfig.PREF_MODE,
|
||||
// AppConfig.PREF_HEV_TUNNEL_LOGLEVEL
|
||||
// ).forEach { key ->
|
||||
// if (MmkvManager.decodeSettingsString(key) != null) {
|
||||
// findPreference<ListPreference>(key)?.value = MmkvManager.decodeSettingsString(key)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private fun updateMode(mode: String?) {
|
||||
@@ -381,29 +424,29 @@ class SettingsActivity : BaseActivity() {
|
||||
fragmentPackets?.isEnabled = enabled
|
||||
fragmentLength?.isEnabled = enabled
|
||||
fragmentInterval?.isEnabled = enabled
|
||||
if (enabled) {
|
||||
updateFragmentPackets(MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_PACKETS, "tlshello"))
|
||||
updateFragmentLength(MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_LENGTH, "50-100"))
|
||||
updateFragmentInterval(MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateFragmentPackets(value: String?) {
|
||||
fragmentPackets?.summary = value.toString()
|
||||
}
|
||||
|
||||
private fun updateFragmentLength(value: String?) {
|
||||
fragmentLength?.summary = value.toString()
|
||||
}
|
||||
|
||||
private fun updateFragmentInterval(value: String?) {
|
||||
fragmentInterval?.summary = value.toString()
|
||||
}
|
||||
|
||||
private fun updateHevTunSettings(enabled: Boolean) {
|
||||
hevTunLogLevel?.isEnabled = enabled
|
||||
hevTunRwTimeout?.isEnabled = enabled
|
||||
// if (enabled) {
|
||||
// updateFragmentPackets(MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_PACKETS, "tlshello"))
|
||||
// updateFragmentLength(MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_LENGTH, "50-100"))
|
||||
// updateFragmentInterval(MmkvManager.decodeSettingsString(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20"))
|
||||
// }
|
||||
}
|
||||
//
|
||||
// private fun updateFragmentPackets(value: String?) {
|
||||
// fragmentPackets?.summary = value.toString()
|
||||
// }
|
||||
//
|
||||
// private fun updateFragmentLength(value: String?) {
|
||||
// fragmentLength?.summary = value.toString()
|
||||
// }
|
||||
//
|
||||
// private fun updateFragmentInterval(value: String?) {
|
||||
// fragmentInterval?.summary = value.toString()
|
||||
// }
|
||||
//
|
||||
// private fun updateHevTunSettings(enabled: Boolean) {
|
||||
// hevTunLogLevel?.isEnabled = enabled
|
||||
// hevTunRwTimeout?.isEnabled = enabled
|
||||
// }
|
||||
}
|
||||
|
||||
fun onModeHelpClicked(view: View) {
|
||||
|
||||
Reference in new issue
Block a user