From 572955dd1ee6713b9d906550c82e9ca5b4fa8128 Mon Sep 17 00:00:00 2001 From: yuhan6665 <1588741+yuhan6665@users.noreply.github.com> Date: Sat, 20 Mar 2021 01:00:12 -0400 Subject: [PATCH] Move everything else to MMKV - Exclude old armv5 so lib from MMKV - Move subscription to MMKV - Clean up settings key - Map settings to MMKV - Say goodbye to DPreference Fix some bugs: - null pointer check - server list refresh - show test result - custom config display - fix port number in DNS object shown as Double - shadowsocks, socks streamsettings - quic settings with wrong security - main list footer --- V2rayNG/app/build.gradle | 3 +- .../kotlin/com/v2ray/ang/AngApplication.kt | 3 - .../main/kotlin/com/v2ray/ang/AppConfig.kt | 36 +-- .../v2ray/ang/dto/ServerAffiliationInfo.kt | 2 +- .../kotlin/com/v2ray/ang/dto/ServerConfig.kt | 9 +- .../com/v2ray/ang/dto/SubscriptionItem.kt | 8 + .../kotlin/com/v2ray/ang/dto/V2rayConfig.kt | 19 +- .../kotlin/com/v2ray/ang/extension/_Ext.kt | 8 - .../com/v2ray/ang/extension/_Preference.kt | 10 - .../v2ray/ang/service/V2RayServiceManager.kt | 16 +- .../com/v2ray/ang/service/V2RayVpnService.kt | 18 +- .../kotlin/com/v2ray/ang/ui/MainActivity.kt | 24 +- .../com/v2ray/ang/ui/MainRecyclerAdapter.kt | 2 +- .../com/v2ray/ang/ui/PerAppProxyActivity.kt | 19 +- .../v2ray/ang/ui/RoutingSettingsFragment.kt | 8 +- .../kotlin/com/v2ray/ang/ui/ServerActivity.kt | 33 ++- .../ang/ui/ServerCustomConfigActivity.kt | 3 +- .../com/v2ray/ang/ui/SubEditActivity.kt | 64 ++--- .../com/v2ray/ang/ui/SubSettingActivity.kt | 15 +- .../v2ray/ang/ui/SubSettingRecyclerAdapter.kt | 30 +- .../com/v2ray/ang/util/AngConfigManager.kt | 95 +------ .../kotlin/com/v2ray/ang/util/MmkvManager.kt | 65 ++++- .../main/kotlin/com/v2ray/ang/util/Utils.kt | 13 +- .../com/v2ray/ang/util/V2rayConfigUtil.kt | 49 ++-- .../com/v2ray/ang/viewmodel/MainViewModel.kt | 12 +- .../v2ray/ang/viewmodel/SettingsViewModel.kt | 28 +- V2rayNG/dpreference/.gitignore | 1 - V2rayNG/dpreference/build.gradle | 25 -- V2rayNG/dpreference/proguard-rules.pro | 17 -- .../dpreference/src/main/AndroidManifest.xml | 16 -- .../me/dozen/dpreference/DPreference.java | 86 ------ .../java/me/dozen/dpreference/IOUtils.java | 61 ---- .../java/me/dozen/dpreference/IPrefImpl.java | 39 --- .../me/dozen/dpreference/PrefAccessor.java | 116 -------- .../me/dozen/dpreference/PreferenceImpl.java | 133 --------- .../dozen/dpreference/PreferenceProvider.java | 267 ------------------ .../dozen/dpreference/StringSetConverter.java | 22 -- V2rayNG/settings.gradle | 2 +- 38 files changed, 274 insertions(+), 1103 deletions(-) create mode 100644 V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/SubscriptionItem.kt delete mode 100644 V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Preference.kt delete mode 100644 V2rayNG/dpreference/.gitignore delete mode 100644 V2rayNG/dpreference/build.gradle delete mode 100644 V2rayNG/dpreference/proguard-rules.pro delete mode 100644 V2rayNG/dpreference/src/main/AndroidManifest.xml delete mode 100644 V2rayNG/dpreference/src/main/java/me/dozen/dpreference/DPreference.java delete mode 100644 V2rayNG/dpreference/src/main/java/me/dozen/dpreference/IOUtils.java delete mode 100644 V2rayNG/dpreference/src/main/java/me/dozen/dpreference/IPrefImpl.java delete mode 100644 V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PrefAccessor.java delete mode 100644 V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PreferenceImpl.java delete mode 100644 V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PreferenceProvider.java delete mode 100644 V2rayNG/dpreference/src/main/java/me/dozen/dpreference/StringSetConverter.java diff --git a/V2rayNG/app/build.gradle b/V2rayNG/app/build.gradle index 3288a1d3..1f5dbeb8 100644 --- a/V2rayNG/app/build.gradle +++ b/V2rayNG/app/build.gradle @@ -25,12 +25,14 @@ android { minifyEnabled false zipAlignEnabled false shrinkResources false + ndk.abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' // proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } debug { minifyEnabled false zipAlignEnabled false shrinkResources false + ndk.abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' } } @@ -67,7 +69,6 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') testImplementation 'junit:junit:4.13' - implementation project(':dpreference') implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion" diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt index 320c98b8..420a6827 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt @@ -4,7 +4,6 @@ import android.support.multidex.MultiDexApplication import android.support.v7.preference.PreferenceManager import com.tencent.mmkv.MMKV import com.v2ray.ang.util.AngConfigManager -import me.dozen.dpreference.DPreference class AngApplication : MultiDexApplication() { companion object { @@ -15,8 +14,6 @@ class AngApplication : MultiDexApplication() { var firstRun = false private set - val defaultDPreference by lazy { DPreference(this, packageName + "_preferences") } - override fun onCreate() { super.onCreate() diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt index 4eee79da..8fd58789 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt @@ -6,36 +6,39 @@ package com.v2ray.ang */ object AppConfig { const val ANG_PACKAGE = "com.v2ray.ang" - const val ANG_CONFIG = "ang_config" - const val PREF_CURR_CONFIG = "pref_v2ray_config" - const val PREF_CURR_CONFIG_GUID = "pref_v2ray_config_guid" - const val PREF_CURR_CONFIG_NAME = "pref_v2ray_config_name" - const val PREF_CURR_CONFIG_DOMAIN = "pref_v2ray_config_domain" - const val PREF_CURR_CONFIG_OUTBOUND_TAGS = "pref_v2ray_config_outbound_tags" - const val PREF_INAPP_BUY_IS_PREMIUM = "pref_inapp_buy_is_premium" + // legacy + const val ANG_CONFIG = "ang_config" + const val PREF_INAPP_BUY_IS_PREMIUM = "pref_inapp_buy_is_premium" + const val PREF_ROUTING_CUSTOM = "pref_routing_custom" + + // Preferences mapped to MMKV const val PREF_MODE = "pref_mode" - // const val PREF_BYPASS_MAINLAND = "pref_bypass_mainland" - // const val PREF_START_ON_BOOT = "pref_start_on_boot" - const val PREF_PER_APP_PROXY = "pref_per_app_proxy" - // const val PREF_MUX_ENAimport libv2ray.Libv2rayBLED = "pref_mux_enabled" const val PREF_SPEED_ENABLED = "pref_speed_enabled" const val PREF_SNIFFING_ENABLED = "pref_sniffing_enabled" const val PREF_PROXY_SHARING = "pref_proxy_sharing_enabled" const val PREF_LOCAL_DNS_ENABLED = "pref_local_dns_enabled" const val PREF_REMOTE_DNS = "pref_remote_dns" const val PREF_DOMESTIC_DNS = "pref_domestic_dns" - // const val PREF_SOCKS_PORT = "pref_socks_port" -// const val PREF_HTTP_PORT = "pref_http_port" + const val PREF_FORWARD_IPV6 = "pref_forward_ipv6" const val PREF_ROUTING_DOMAIN_STRATEGY = "pref_routing_domain_strategy" const val PREF_ROUTING_MODE = "pref_routing_mode" - const val PREF_ROUTING_CUSTOM = "pref_routing_custom" + const val PREF_V2RAY_ROUTING_AGENT = "pref_v2ray_routing_agent" + const val PREF_V2RAY_ROUTING_DIRECT = "pref_v2ray_routing_direct" + const val PREF_V2RAY_ROUTING_BLOCKED = "pref_v2ray_routing_blocked" + const val PREF_PER_APP_PROXY = "pref_per_app_proxy" + const val PREF_PER_APP_PROXY_SET = "pref_per_app_proxy_set" + const val PREF_BYPASS_APPS = "pref_bypass_apps" + // const val PREF_BYPASS_MAINLAND = "pref_bypass_mainland" + // const val PREF_START_ON_BOOT = "pref_start_on_boot" + // const val PREF_MUX_ENAimport libv2ray.Libv2rayBLED = "pref_mux_enabled" + // const val PREF_SOCKS_PORT = "pref_socks_port" +// const val PREF_HTTP_PORT = "pref_http_port" // const val PREF_DONATE = "pref_donate" // const val PREF_LICENSES = "pref_licenses" // const val PREF_FEEDBACK = "pref_feedback" // const val PREF_TG_GROUP = "pref_tg_group" // const val PREF_AUTO_RESTART = "pref_auto_restart" - const val PREF_FORWARD_IPV6 = "pref_forward_ipv6" const val HTTP_PROTOCOL: String = "http://" const val HTTPS_PROTOCOL: String = "https://" @@ -50,9 +53,6 @@ object AppConfig { const val TASKER_EXTRA_BUNDLE_GUID = "tasker_extra_bundle_guid" const val TASKER_DEFAULT_GUID = "Default" - const val PREF_V2RAY_ROUTING_AGENT = "pref_v2ray_routing_agent" - const val PREF_V2RAY_ROUTING_DIRECT = "pref_v2ray_routing_direct" - const val PREF_V2RAY_ROUTING_BLOCKED = "pref_v2ray_routing_blocked" const val TAG_AGENT = "proxy" const val TAG_DIRECT = "direct" const val TAG_BLOCKED = "block" diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerAffiliationInfo.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerAffiliationInfo.kt index 100044d2..bb4d20be 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerAffiliationInfo.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerAffiliationInfo.kt @@ -1,6 +1,6 @@ package com.v2ray.ang.dto -data class ServerAffiliationInfo(var testDelayMillis: Long) { +data class ServerAffiliationInfo(var testDelayMillis: Long = 0L) { fun getTestDelayString(): String { if (testDelayMillis == 0L) { return "" diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt index 5c2bdba4..977be96f 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt @@ -28,14 +28,7 @@ data class ServerConfig( streamSettings = V2rayConfig.OutboundBean.StreamSettingsBean())) EConfigType.CUSTOM -> return ServerConfig(configType = configType) - EConfigType.SHADOWSOCKS, EConfigType.SOCKS -> - return ServerConfig( - configType = configType, - outboundBean = V2rayConfig.OutboundBean( - protocol = configType.name.toLowerCase(), - settings = V2rayConfig.OutboundBean.OutSettingsBean( - servers = listOf(V2rayConfig.OutboundBean.OutSettingsBean.ServersBean())))) - EConfigType.TROJAN -> + EConfigType.SHADOWSOCKS, EConfigType.SOCKS, EConfigType.TROJAN -> return ServerConfig( configType = configType, outboundBean = V2rayConfig.OutboundBean( diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/SubscriptionItem.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/SubscriptionItem.kt new file mode 100644 index 00000000..b2195148 --- /dev/null +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/SubscriptionItem.kt @@ -0,0 +1,8 @@ +package com.v2ray.ang.dto + +data class SubscriptionItem( + var remarks: String = "", + var url: String = "", + var enabled: Boolean = true, + val addedTime: Long = System.currentTimeMillis()) { +} diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt index e49dc15f..4cb83de7 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt @@ -1,6 +1,12 @@ package com.v2ray.ang.dto import android.text.TextUtils +import com.google.gson.GsonBuilder +import com.google.gson.JsonPrimitive +import com.google.gson.JsonSerializationContext +import com.google.gson.JsonSerializer +import com.google.gson.reflect.TypeToken +import java.lang.reflect.Type data class V2rayConfig( val stats: Any? = null, @@ -284,7 +290,7 @@ data class V2rayConfig( "quic" -> { val quicSetting = streamSettings?.quicSettings ?: return null listOf(quicSetting.header.type, - quicSetting.key, + quicSetting.security, quicSetting.key) } else -> null @@ -336,4 +342,15 @@ data class V2rayConfig( } return null } + + fun toPrettyPrinting(): String { + return GsonBuilder() + .setPrettyPrinting() + .registerTypeAdapter( // custom serialiser is needed here since JSON by default parse number as Double, core will fail to start + object: TypeToken() {}.type, + JsonSerializer { src: Double?, _: Type?, _: JsonSerializationContext? -> JsonPrimitive(src?.toInt()) } + ) + .create() + .toJson(this) + } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Ext.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Ext.kt index 73a400cd..b0e74368 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Ext.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Ext.kt @@ -4,7 +4,6 @@ import android.content.Context import android.os.Build import android.widget.Toast import com.v2ray.ang.AngApplication -import me.dozen.dpreference.DPreference import me.drakeet.support.toast.ToastCompat import org.json.JSONObject import java.net.URLConnection @@ -16,13 +15,6 @@ import java.net.URLConnection val Context.v2RayApplication: AngApplication get() = applicationContext as AngApplication -// Usage note: DPreference use Android ContentProvider to redirect multi process access to main process. -// Currently, RunSoLibV2RayDaemon process will run proxy core, keep minimum configuration and long running -// in the background, support toggle on/off. That means it should NOT use DPreference after the initial -// creation and setup of the service -val Context.defaultDPreference: DPreference - get() = v2RayApplication.defaultDPreference - inline fun Context.toast(message: Int): Toast = ToastCompat .makeText(this, message, Toast.LENGTH_SHORT) .apply { diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Preference.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Preference.kt deleted file mode 100644 index dcfa4671..00000000 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Preference.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.v2ray.ang.extension - -import android.preference.Preference - -fun Preference.onClick(listener: () -> Unit) { - setOnPreferenceClickListener { - listener() - true - } -} \ No newline at end of file diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt index b5fce5ce..adcb2c5b 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt @@ -18,10 +18,8 @@ import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig.TAG_DIRECT import com.v2ray.ang.R import com.v2ray.ang.dto.ServerConfig -import com.v2ray.ang.extension.defaultDPreference import com.v2ray.ang.extension.toSpeedString import com.v2ray.ang.extension.toast -import com.v2ray.ang.extension.v2RayApplication import com.v2ray.ang.ui.MainActivity import com.v2ray.ang.util.MessageUtil import com.v2ray.ang.util.MmkvManager @@ -45,6 +43,7 @@ object V2RayServiceManager { val v2rayPoint: V2RayPoint = Libv2ray.newV2RayPoint(V2RayCallback()) private val mMsgReceive = ReceiveMessageHandler() private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) } + private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } var serviceControl: SoftReference? = null set(value) { @@ -64,12 +63,12 @@ object V2RayServiceManager { private var mNotificationManager: NotificationManager? = null fun startV2Ray(context: Context) { - if (context.v2RayApplication.defaultDPreference.getPrefBoolean(AppConfig.PREF_PROXY_SHARING, false)) { + if (settingsStorage?.decodeBool(AppConfig.PREF_PROXY_SHARING) == true) { context.toast(R.string.toast_warning_pref_proxysharing_short) }else{ context.toast(R.string.toast_services_start) } - val intent = if (context.v2RayApplication.defaultDPreference.getPrefString(AppConfig.PREF_MODE, "VPN") == "VPN") { + val intent = if (settingsStorage?.decodeString(AppConfig.PREF_MODE) ?: "VPN" == "VPN") { Intent(context.applicationContext, V2RayVpnService::class.java) } else { Intent(context.applicationContext, V2RayProxyOnlyService::class.java) @@ -147,9 +146,9 @@ object V2RayServiceManager { v2rayPoint.configureFileContent = result.content v2rayPoint.domainName = config.getV2rayPointDomainAndPort() currentConfig = config - v2rayPoint.enableLocalDNS = service.defaultDPreference.getPrefBoolean(AppConfig.PREF_LOCAL_DNS_ENABLED, false) - v2rayPoint.forwardIpv6 = service.defaultDPreference.getPrefBoolean(AppConfig.PREF_FORWARD_IPV6, false) - v2rayPoint.proxyOnly = service.defaultDPreference.getPrefString(AppConfig.PREF_MODE, "VPN") != "VPN" + v2rayPoint.enableLocalDNS = settingsStorage?.decodeBool(AppConfig.PREF_LOCAL_DNS_ENABLED) ?: false + v2rayPoint.forwardIpv6 = settingsStorage?.decodeBool(AppConfig.PREF_FORWARD_IPV6) ?: false + v2rayPoint.proxyOnly = settingsStorage?.decodeString(AppConfig.PREF_MODE) ?: "VPN" == "VPN" try { v2rayPoint.runLoop() @@ -314,10 +313,9 @@ object V2RayServiceManager { } fun startSpeedNotification() { - val service = serviceControl?.get()?.getService() ?: return if (mSubscription == null && v2rayPoint.isRunning && - service.defaultDPreference.getPrefBoolean(AppConfig.PREF_SPEED_ENABLED, false)) { + settingsStorage?.decodeBool(AppConfig.PREF_SPEED_ENABLED) == true) { var lastZeroSpeed = false val outboundTags = currentConfig?.getAllOutboundTags() outboundTags?.remove(TAG_DIRECT) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayVpnService.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayVpnService.kt index dc92d15f..efc410ff 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayVpnService.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayVpnService.kt @@ -10,10 +10,10 @@ import android.os.ParcelFileDescriptor import android.os.StrictMode import android.support.annotation.RequiresApi import android.util.Log +import com.tencent.mmkv.MMKV import com.v2ray.ang.AppConfig import com.v2ray.ang.R -import com.v2ray.ang.extension.defaultDPreference -import com.v2ray.ang.ui.PerAppProxyActivity +import com.v2ray.ang.util.MmkvManager import com.v2ray.ang.util.Utils import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -22,6 +22,8 @@ import java.io.File import java.lang.ref.SoftReference class V2RayVpnService : VpnService(), ServiceControl { + private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } + private lateinit var mInterface: ParcelFileDescriptor /** @@ -91,8 +93,8 @@ class V2RayVpnService : VpnService(), ServiceControl { // If the old interface has exactly the same parameters, use it! // Configure a builder while parsing the parameters. val builder = Builder() - val enableLocalDns = defaultDPreference.getPrefBoolean(AppConfig.PREF_LOCAL_DNS_ENABLED, false) - val routingMode = defaultDPreference.getPrefString(AppConfig.PREF_ROUTING_MODE, "0") + val enableLocalDns = settingsStorage?.decodeBool(AppConfig.PREF_LOCAL_DNS_ENABLED) ?: false + val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) ?: "0" parameters.split(" ") .map { it.split(",") } @@ -120,7 +122,7 @@ class V2RayVpnService : VpnService(), ServiceControl { } if(!enableLocalDns) { - Utils.getRemoteDnsServers(defaultDPreference) + Utils.getRemoteDnsServers() .forEach { builder.addDnsServer(it) } @@ -129,9 +131,9 @@ class V2RayVpnService : VpnService(), ServiceControl { builder.setSession(V2RayServiceManager.currentConfig?.remarks.orEmpty()) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && - defaultDPreference.getPrefBoolean(AppConfig.PREF_PER_APP_PROXY, false)) { - val apps = defaultDPreference.getPrefStringSet(PerAppProxyActivity.PREF_PER_APP_PROXY_SET, null) - val bypassApps = defaultDPreference.getPrefBoolean(PerAppProxyActivity.PREF_BYPASS_APPS, false) + settingsStorage?.decodeBool(AppConfig.PREF_PER_APP_PROXY) == true) { + val apps = settingsStorage?.decodeStringSet(AppConfig.PREF_PER_APP_PROXY_SET) + val bypassApps = settingsStorage?.decodeBool(AppConfig.PREF_BYPASS_APPS) ?: false apps?.forEach { try { if (bypassApps) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt index 54ae616c..5c269dab 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt @@ -22,7 +22,6 @@ import com.v2ray.ang.AppConfig import com.v2ray.ang.BuildConfig import com.v2ray.ang.R import com.v2ray.ang.dto.EConfigType -import com.v2ray.ang.extension.defaultDPreference import com.v2ray.ang.extension.toast import com.v2ray.ang.helper.SimpleItemTouchHelperCallback import com.v2ray.ang.service.V2RayServiceManager @@ -51,6 +50,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList private val adapter by lazy { MainRecyclerAdapter(this) } private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) } + private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } private var mItemTouchHelper: ItemTouchHelper? = null val mainViewModel: MainViewModel by lazy { ViewModelProviders.of(this).get(MainViewModel::class.java) } @@ -63,7 +63,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList fab.setOnClickListener { if (mainViewModel.isRunning.value == true) { Utils.stopVService(this) - } else if (defaultDPreference.getPrefString(AppConfig.PREF_MODE, "VPN") == "VPN") { + } else if (settingsStorage?.decodeString(AppConfig.PREF_MODE) ?: "VPN" == "VPN") { val intent = VpnService.prepare(this) if (intent == null) { startV2Ray() @@ -297,7 +297,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList } if (count > 0) { toast(R.string.toast_success) - adapter.notifyDataSetChanged() + mainViewModel.reloadServerList() } else { toast(R.string.toast_failure) } @@ -381,18 +381,16 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList : Boolean { try { toast(R.string.title_sub_update) - val subItem = AngConfigManager.configs.subItem - for (k in 0 until subItem.count()) { - if (TextUtils.isEmpty(subItem[k].id) - || TextUtils.isEmpty(subItem[k].remarks) - || TextUtils.isEmpty(subItem[k].url) + MmkvManager.decodeSubscriptions().forEach { + if (TextUtils.isEmpty(it.first) + || TextUtils.isEmpty(it.second.remarks) + || TextUtils.isEmpty(it.second.url) ) { - continue + return@forEach } - val id = subItem[k].id - val url = subItem[k].url + val url = it.second.url if (!Utils.isValidUrl(url)) { - continue + return@forEach } Log.d("Main", url) GlobalScope.launch(Dispatchers.IO) { @@ -403,7 +401,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList "" } launch(Dispatchers.Main) { - importBatchConfig(Utils.decode(configText), id) + importBatchConfig(Utils.decode(configText), it.first) } } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt index 8b780206..0fe9fbd2 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt @@ -39,7 +39,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter? = null + private val defaultSharedPreferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -52,7 +49,7 @@ class PerAppProxyActivity : BaseActivity() { val dividerItemDecoration = DividerItemDecoration(this, LinearLayoutManager.VERTICAL) recycler_view.addItemDecoration(dividerItemDecoration) - val blacklist = defaultDPreference.getPrefStringSet(PREF_PER_APP_PROXY_SET, null) + val blacklist = defaultSharedPreferences.getStringSet(AppConfig.PREF_PER_APP_PROXY_SET, null) AppManagerUtil.rxLoadNetworkAppList(this) .subscribeOn(Schedulers.io()) @@ -142,14 +139,14 @@ class PerAppProxyActivity : BaseActivity() { }) switch_per_app_proxy.setOnCheckedChangeListener { buttonView, isChecked -> - defaultDPreference.setPrefBoolean(AppConfig.PREF_PER_APP_PROXY, isChecked) + defaultSharedPreferences.edit().putBoolean(AppConfig.PREF_PER_APP_PROXY, isChecked).apply() } - switch_per_app_proxy.isChecked = defaultDPreference.getPrefBoolean(AppConfig.PREF_PER_APP_PROXY, false) + switch_per_app_proxy.isChecked = defaultSharedPreferences.getBoolean(AppConfig.PREF_PER_APP_PROXY, false) switch_bypass_apps.setOnCheckedChangeListener { buttonView, isChecked -> - defaultDPreference.setPrefBoolean(PREF_BYPASS_APPS, isChecked) + defaultSharedPreferences.edit().putBoolean(AppConfig.PREF_BYPASS_APPS, isChecked).apply() } - switch_bypass_apps.isChecked = defaultDPreference.getPrefBoolean(PREF_BYPASS_APPS, false) + switch_bypass_apps.isChecked = defaultSharedPreferences.getBoolean(AppConfig.PREF_BYPASS_APPS, false) et_search.setOnEditorActionListener { v, actionId, event -> if (actionId == EditorInfo.IME_ACTION_SEARCH) { @@ -183,7 +180,7 @@ class PerAppProxyActivity : BaseActivity() { override fun onPause() { super.onPause() adapter?.let { - defaultDPreference.setPrefStringSet(PREF_PER_APP_PROXY_SET, it.blacklist) + defaultSharedPreferences.edit().putStringSet(AppConfig.PREF_PER_APP_PROXY_SET, it.blacklist).apply() } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsFragment.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsFragment.kt index 97917148..a32c2223 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsFragment.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsFragment.kt @@ -5,9 +5,9 @@ import android.app.Activity.RESULT_OK import android.content.Intent import android.os.Bundle import android.support.v4.app.Fragment +import android.support.v7.preference.PreferenceManager import android.view.* import com.v2ray.ang.R -import com.v2ray.ang.extension.defaultDPreference import com.v2ray.ang.util.Utils import kotlinx.android.synthetic.main.fragment_routing_settings.* import android.view.MenuInflater @@ -26,6 +26,8 @@ class RoutingSettingsFragment : Fragment() { private const val REQUEST_SCAN_APPEND = 12 } + val defaultSharedPreferences by lazy { PreferenceManager.getDefaultSharedPreferences(context) } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // Inflate the layout for this fragment @@ -43,7 +45,7 @@ class RoutingSettingsFragment : Fragment() { override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - val content = activity?.defaultDPreference?.getPrefString(arguments!!.getString(routing_arg), "") + val content = defaultSharedPreferences.getString(arguments!!.getString(routing_arg), "") et_routing_content.text = Utils.getEditable(content!!) setHasOptionsMenu(true) @@ -57,7 +59,7 @@ class RoutingSettingsFragment : Fragment() { override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { R.id.save_routing -> { val content = et_routing_content.text.toString() - activity?.defaultDPreference?.setPrefString(arguments!!.getString(routing_arg), content) + defaultSharedPreferences.edit().putString(arguments!!.getString(routing_arg), content).apply() activity?.toast(R.string.toast_success) true } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt index d4820350..c886c8f7 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt @@ -12,7 +12,6 @@ import com.v2ray.ang.dto.ServerConfig import com.v2ray.ang.dto.V2rayConfig import com.v2ray.ang.dto.V2rayConfig.Companion.DEFAULT_NETWORK import com.v2ray.ang.dto.V2rayConfig.Companion.DEFAULT_PORT -import com.v2ray.ang.dto.V2rayConfig.Companion.TLS import com.v2ray.ang.dto.V2rayConfig.Companion.XTLS import com.v2ray.ang.extension.toast import com.v2ray.ang.util.MmkvManager @@ -35,6 +34,7 @@ import kotlinx.android.synthetic.main.activity_server_vmess.sp_stream_security class ServerActivity : BaseActivity() { private val mainStorage by lazy { MMKV.mmkvWithID(ID_MAIN, MMKV.MULTI_PROCESS_MODE) } + private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } private val editGuid by lazy { intent.getStringExtra("guid").orEmpty() } private val isRunning by lazy { intent.getBooleanExtra("isRunning", false) @@ -96,7 +96,7 @@ class ServerActivity : BaseActivity() { et_remarks.text = Utils.getEditable(config.remarks) et_address.text = Utils.getEditable(outbound.getServerAddress().orEmpty()) - et_port.text = Utils.getEditable(outbound.getServerPort()?.or(DEFAULT_PORT).toString()) + et_port.text = Utils.getEditable(outbound.getServerPort()?.toString() ?: DEFAULT_PORT.toString()) et_id.text = Utils.getEditable(outbound.getPassword().orEmpty()) et_alterId?.text = Utils.getEditable(outbound.settings?.vnext?.get(0)?.users?.get(0)?.alterId.toString()) if (config.configType == EConfigType.SOCKS) { @@ -229,18 +229,22 @@ class ServerActivity : BaseActivity() { if (config.configType == EConfigType.SHADOWSOCKS) { server.password = et_id.text.toString().trim() server.method = shadowsocksSecuritys[sp_security.selectedItemPosition] - } else if (config.configType == EConfigType.SOCKS && !TextUtils.isEmpty(et_security.text) && !TextUtils.isEmpty(et_id.text)) { - val socksUsersBean = V2rayConfig.OutboundBean.OutSettingsBean.ServersBean.SocksUsersBean() - socksUsersBean.user = et_security.text.toString().trim() - socksUsersBean.pass = et_id.text.toString().trim() - server.users = listOf(socksUsersBean) + } else if (config.configType == EConfigType.SOCKS) { + if (TextUtils.isEmpty(et_security.text) && TextUtils.isEmpty(et_id.text)) { + server.users = null + } else { + val socksUsersBean = V2rayConfig.OutboundBean.OutSettingsBean.ServersBean.SocksUsersBean() + socksUsersBean.user = et_security.text.toString().trim() + socksUsersBean.pass = et_id.text.toString().trim() + server.users = listOf(socksUsersBean) + } } else if (config.configType == EConfigType.TROJAN) { server.password = et_id.text.toString().trim() } } private fun saveStreamSettings(streamSetting: V2rayConfig.OutboundBean.StreamSettingsBean) { - val requestHost = et_request_host.text.toString().trim() + val requestHost = et_request_host?.text.toString().trim() val path = et_path?.text.toString().trim() var sni = streamSetting.populateTransportSettings( if (sp_network != null) networks[sp_network.selectedItemPosition] else DEFAULT_NETWORK, @@ -254,9 +258,18 @@ class ServerActivity : BaseActivity() { if (sni.isEmpty()) { sni = requestHost } + val allowInsecure = if (sp_allow_insecure != null) { + if (allowinsecures[sp_allow_insecure.selectedItemPosition].isBlank()) { + false//settingsStorage?.decodeBool(PREF_ALLOW_INSECURE) ?: false + } else { + allowinsecures[sp_allow_insecure.selectedItemPosition].toBoolean() + } + } else { + false + } streamSetting.populateTlsSettings( - if (sp_stream_security != null) streamSecuritys[sp_stream_security.selectedItemPosition] else TLS, - if (sp_allow_insecure != null) allowinsecures[sp_allow_insecure.selectedItemPosition].toBoolean() else false, + if (sp_stream_security != null) streamSecuritys[sp_stream_security.selectedItemPosition] else "", + allowInsecure, sni ) } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerCustomConfigActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerCustomConfigActivity.kt index 7205bedd..8db9793f 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerCustomConfigActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerCustomConfigActivity.kt @@ -15,7 +15,6 @@ import com.v2ray.ang.extension.toast import com.v2ray.ang.util.MmkvManager import com.v2ray.ang.util.Utils import kotlinx.android.synthetic.main.activity_server_custom_config.* -import java.lang.Exception class ServerCustomConfigActivity : BaseActivity() { @@ -46,7 +45,7 @@ class ServerCustomConfigActivity : BaseActivity() { */ private fun bindingServer(config: ServerConfig): Boolean { et_remarks.text = Utils.getEditable(config.remarks) - tv_content.text = Utils.getEditable(Gson().toJson(config.fullConfig)) + tv_content.text = Utils.getEditable(config.fullConfig?.toPrettyPrinting().orEmpty()) return true } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt index 1d60a327..f35cdff6 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt @@ -5,10 +5,12 @@ import android.support.v7.app.AlertDialog import android.text.TextUtils import android.view.Menu import android.view.MenuItem +import com.google.gson.Gson +import com.tencent.mmkv.MMKV import com.v2ray.ang.R -import com.v2ray.ang.dto.AngConfig +import com.v2ray.ang.dto.SubscriptionItem import com.v2ray.ang.extension.toast -import com.v2ray.ang.util.AngConfigManager +import com.v2ray.ang.util.MmkvManager import com.v2ray.ang.util.Utils import kotlinx.android.synthetic.main.activity_sub_edit.* @@ -17,20 +19,17 @@ class SubEditActivity : BaseActivity() { var del_config: MenuItem? = null var save_config: MenuItem? = null - private lateinit var configs: AngConfig - private var edit_index: Int = -1 //当前编辑的 + private val subStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SUB, MMKV.MULTI_PROCESS_MODE) } + private val editSubId by lazy { intent.getStringExtra("subId").orEmpty() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_sub_edit) - - configs = AngConfigManager.configs - edit_index = intent.getIntExtra("position", -1) - title = getString(R.string.title_sub_setting) - if (edit_index >= 0) { - bindingServer(configs.subItem[edit_index]) + val json = subStorage?.decodeString(editSubId) + if (!json.isNullOrBlank()) { + bindingServer(Gson().fromJson(json, SubscriptionItem::class.java)) } else { clearServer() } @@ -40,7 +39,7 @@ class SubEditActivity : BaseActivity() { /** * bingding seleced server config */ - fun bindingServer(subItem: AngConfig.SubItemBean): Boolean { + private fun bindingServer(subItem: SubscriptionItem): Boolean { et_remarks.text = Utils.getEditable(subItem.remarks) et_url.text = Utils.getEditable(subItem.url) @@ -50,7 +49,7 @@ class SubEditActivity : BaseActivity() { /** * clear or init server config */ - fun clearServer(): Boolean { + private fun clearServer(): Boolean { et_remarks.text = null et_url.text = null @@ -60,12 +59,15 @@ class SubEditActivity : BaseActivity() { /** * save server config */ - fun saveServer(): Boolean { - val subItem: AngConfig.SubItemBean - if (edit_index >= 0) { - subItem = configs.subItem[edit_index] + private fun saveServer(): Boolean { + val subItem: SubscriptionItem + val json = subStorage?.decodeString(editSubId) + var subId = editSubId + if (!json.isNullOrBlank()) { + subItem = Gson().fromJson(json, SubscriptionItem::class.java) } else { - subItem = AngConfig.SubItemBean() + subId = Utils.getUuid() + subItem = SubscriptionItem() } subItem.remarks = et_remarks.text.toString() @@ -80,32 +82,23 @@ class SubEditActivity : BaseActivity() { return false } - if (AngConfigManager.addSubItem(subItem, edit_index) == 0) { - toast(R.string.toast_success) - finish() - return true - } else { - toast(R.string.toast_failure) - return false - } + subStorage?.encode(subId, Gson().toJson(subItem)) + toast(R.string.toast_success) + finish() + return true } /** * save server config */ - fun deleteServer(): Boolean { - if (edit_index >= 0) { + private fun deleteServer(): Boolean { + if (editSubId.isNotEmpty()) { AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm) .setPositiveButton(android.R.string.ok) { _, _ -> - if (AngConfigManager.removeSubItem(edit_index) == 0) { - toast(R.string.toast_success) - finish() - } else { - toast(R.string.toast_failure) - } + MmkvManager.removeSubscription(editSubId) + finish() } .show() - } else { } return true } @@ -115,8 +108,7 @@ class SubEditActivity : BaseActivity() { del_config = menu?.findItem(R.id.del_config) save_config = menu?.findItem(R.id.save_config) - if (edit_index >= 0) { - } else { + if (editSubId.isEmpty()) { del_config?.isVisible = false } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubSettingActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubSettingActivity.kt index e8a6b449..5cc99703 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubSettingActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubSettingActivity.kt @@ -1,15 +1,18 @@ package com.v2ray.ang.ui import android.content.Intent -import android.support.v7.widget.LinearLayoutManager import android.view.Menu import android.view.MenuItem import com.v2ray.ang.R import kotlinx.android.synthetic.main.activity_sub_setting.* import android.os.Bundle +import android.support.v7.widget.LinearLayoutManager +import com.v2ray.ang.dto.SubscriptionItem +import com.v2ray.ang.util.MmkvManager class SubSettingActivity : BaseActivity() { + var subscriptions:List> = listOf() private val adapter by lazy { SubSettingRecyclerAdapter(this) } override fun onCreate(savedInstanceState: Bundle?) { @@ -27,7 +30,8 @@ class SubSettingActivity : BaseActivity() { override fun onResume() { super.onResume() - adapter.updateConfigList() + subscriptions = MmkvManager.decodeSubscriptions() + adapter.notifyDataSetChanged() } override fun onCreateOptionsMenu(menu: Menu?): Boolean { @@ -40,14 +44,9 @@ class SubSettingActivity : BaseActivity() { override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { R.id.add_config -> { - startActivity(Intent(this, SubEditActivity::class.java) - .putExtra("position", -1) - ) - adapter.updateConfigList() + startActivity(Intent(this, SubEditActivity::class.java)) true } else -> super.onOptionsItemSelected(item) } - - } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubSettingRecyclerAdapter.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubSettingRecyclerAdapter.kt index 50c89d5b..56998f63 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubSettingRecyclerAdapter.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubSettingRecyclerAdapter.kt @@ -7,36 +7,27 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.v2ray.ang.R -import com.v2ray.ang.dto.AngConfig -import com.v2ray.ang.util.AngConfigManager import kotlinx.android.synthetic.main.item_recycler_sub_setting.view.* class SubSettingRecyclerAdapter(val activity: SubSettingActivity) : RecyclerView.Adapter() { private var mActivity: SubSettingActivity = activity - private lateinit var configs: AngConfig - init { - updateConfigList() - } - - override fun getItemCount() = configs.subItem.count() + override fun getItemCount() = mActivity.subscriptions.size override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { if (holder is MainViewHolder) { - val remarks = configs.subItem[position].remarks - val url = configs.subItem[position].url - - holder.name.text = remarks - holder.url.text = url + val subId = mActivity.subscriptions[position].first + val subItem = mActivity.subscriptions[position].second + holder.name.text = subItem.remarks + holder.url.text = subItem.url holder.itemView.setBackgroundColor(Color.TRANSPARENT) holder.layout_edit.setOnClickListener { mActivity.startActivity(Intent(mActivity, SubEditActivity::class.java) - .putExtra("position", position) + .putExtra("subId", subId) ) } - } else { } } @@ -45,15 +36,6 @@ class SubSettingRecyclerAdapter(val activity: SubSettingActivity) : RecyclerView .inflate(R.layout.item_recycler_sub_setting, parent, false)) } - fun updateConfigList() { - configs = AngConfigManager.configs - notifyDataSetChanged() - } - -// fun updateSelectedItem() { -// notifyItemChanged(configs.index) -// } - open class BaseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) class MainViewHolder(itemView: View) : BaseViewHolder(itemView) { diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt index 4e46a307..9b92aa24 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt @@ -1,6 +1,7 @@ package com.v2ray.ang.util import android.graphics.Bitmap +import android.support.v7.preference.PreferenceManager import android.text.TextUtils import com.google.gson.Gson import com.tencent.mmkv.MMKV @@ -20,8 +21,8 @@ import java.util.* object AngConfigManager { private lateinit var app: AngApplication private lateinit var angConfig: AngConfig - val configs: AngConfig get() = angConfig private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) } + private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } fun inject(app: AngApplication) { this.app = app @@ -33,7 +34,8 @@ object AngConfigManager { */ private fun loadConfig() { try { - val context = app.defaultDPreference.getPrefString(ANG_CONFIG, "") + val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(app) + val context = defaultSharedPreferences.getString(ANG_CONFIG, "") if (!TextUtils.isEmpty(context)) { angConfig = Gson().fromJson(context, AngConfig::class.java) } else { @@ -56,18 +58,6 @@ object AngConfigManager { } } - /** - * store config to file - */ - fun storeConfigFile() { - try { - val conf = Gson().toJson(angConfig) - app.defaultDPreference.setPrefString(ANG_CONFIG, conf) - } catch (e: Exception) { - e.printStackTrace() - } - } - /** * import config form qrcode or... */ @@ -79,12 +69,12 @@ object AngConfigManager { //maybe sub if (str.startsWith(HTTP_PROTOCOL) || str.startsWith(HTTPS_PROTOCOL)) { - addSubItem(str) + MmkvManager.importUrlAsSubscription(str) return 0 } var config: ServerConfig? = null - val allowInsecure = false//app.defaultDPreference.getPrefBoolean(AppConfig.PREF_ALLOW_INSECURE, false) + val allowInsecure = false//settingsStorage?.decodeBool(AppConfig.PREF_ALLOW_INSECURE) ?: false if (str.startsWith(EConfigType.VMESS.protocolScheme)) { config = ServerConfig.create(EConfigType.VMESS) val streamSetting = config.outboundBean?.streamSettings ?: return -1 @@ -573,77 +563,4 @@ object AngConfigManager { } return 0 } - - - private fun saveSubItem(subItem: ArrayList): Int { - try { - if (subItem.count() <= 0) { - return -1 - } - for (k in 0 until subItem.count()) { - if (TextUtils.isEmpty(subItem[k].id)) { - subItem[k].id = Utils.getUuid() - } - } - angConfig.subItem = subItem - - storeConfigFile() - } catch (e: Exception) { - e.printStackTrace() - return -1 - } - return 0 - } - - fun addSubItem(subItem: AngConfig.SubItemBean, index: Int): Int { - try { - if (index >= 0) { - //edit - angConfig.subItem[index] = subItem - } else { - //add - angConfig.subItem.add(subItem) - } - - saveSubItem(angConfig.subItem) - } catch (e: Exception) { - e.printStackTrace() - return -1 - } - return 0 - } - - private fun addSubItem(url: String): Int { - //already exists - angConfig.subItem.forEach { - if (it.url == url) { - return 0 - } - } - val subItem = AngConfig.SubItemBean() - subItem.remarks = "import sub" - subItem.url = url - return addSubItem(subItem, -1) - } - - /** - * - */ - fun removeSubItem(index: Int): Int { - try { - if (index < 0 || index > angConfig.subItem.count() - 1) { - return -1 - } - val subid = angConfig.subItem[index].id - MmkvManager.removeServerViaSubid(subid) - - angConfig.subItem.removeAt(index) - - storeConfigFile() - } catch (e: Exception) { - e.printStackTrace() - return -1 - } - return 0 - } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/MmkvManager.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/MmkvManager.kt index 087c346a..220d1438 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/MmkvManager.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/MmkvManager.kt @@ -4,6 +4,7 @@ import com.google.gson.Gson import com.tencent.mmkv.MMKV import com.v2ray.ang.dto.ServerAffiliationInfo import com.v2ray.ang.dto.ServerConfig +import com.v2ray.ang.dto.SubscriptionItem object MmkvManager { const val ID_MAIN = "MAIN" @@ -17,6 +18,16 @@ object MmkvManager { private val mainStorage by lazy { MMKV.mmkvWithID(ID_MAIN, MMKV.MULTI_PROCESS_MODE) } private val serverStorage by lazy { MMKV.mmkvWithID(ID_SERVER_CONFIG, MMKV.MULTI_PROCESS_MODE) } private val serverAffStorage by lazy { MMKV.mmkvWithID(ID_SERVER_AFF, MMKV.MULTI_PROCESS_MODE) } + private val subStorage by lazy { MMKV.mmkvWithID(ID_SUB, MMKV.MULTI_PROCESS_MODE) } + + fun decodeServerList(): MutableList { + val json = mainStorage?.decodeString(KEY_ANG_CONFIGS) + return if (json.isNullOrBlank()) { + mutableListOf() + } else { + Gson().fromJson(json, Array::class.java).toMutableList() + } + } fun decodeServerConfig(guid: String): ServerConfig? { if (guid.isBlank()) { @@ -36,11 +47,13 @@ object MmkvManager { guid } serverStorage?.encode(key, Gson().toJson(config)) - val serverList= Gson().fromJson(mainStorage?.decodeString(KEY_ANG_CONFIGS), Array::class.java).toMutableList() - serverList.add(guid) - mainStorage?.encode(KEY_ANG_CONFIGS, Gson().toJson(serverList)) - if (mainStorage?.decodeString(KEY_SELECTED_SERVER).isNullOrBlank()) { - mainStorage?.encode(KEY_SELECTED_SERVER, guid) + val serverList= decodeServerList() + if (!serverList.contains(key)) { + serverList.add(key) + mainStorage?.encode(KEY_ANG_CONFIGS, Gson().toJson(serverList)) + if (mainStorage?.decodeString(KEY_SELECTED_SERVER).isNullOrBlank()) { + mainStorage?.encode(KEY_SELECTED_SERVER, key) + } } return key } @@ -52,7 +65,7 @@ object MmkvManager { if (mainStorage?.decodeString(KEY_SELECTED_SERVER) == guid) { mainStorage?.remove(KEY_SELECTED_SERVER) } - val serverList= Gson().fromJson(mainStorage?.decodeString(KEY_ANG_CONFIGS), Array::class.java).toMutableList() + val serverList= decodeServerList() serverList.remove(guid) mainStorage?.encode(KEY_ANG_CONFIGS, Gson().toJson(serverList)) serverStorage?.remove(guid) @@ -83,6 +96,15 @@ object MmkvManager { return Gson().fromJson(json, ServerAffiliationInfo::class.java) } + fun encodeServerTestDelayMillis(guid: String, testResult: Long) { + if (guid.isBlank()) { + return + } + val aff = decodeServerAffiliationInfo(guid) ?: ServerAffiliationInfo() + aff.testDelayMillis = testResult + serverAffStorage?.encode(guid, Gson().toJson(aff)) + } + fun clearAllTestDelayResults() { serverAffStorage?.allKeys()?.forEach { key -> decodeServerAffiliationInfo(key)?.let { aff -> @@ -91,4 +113,35 @@ object MmkvManager { } } } + + fun importUrlAsSubscription(url: String): Int { + val subscriptions = decodeSubscriptions() + subscriptions.forEach { + if (it.second.url == url) { + return 0 + } + } + val subItem = SubscriptionItem() + subItem.remarks = "import sub" + subItem.url = url + subStorage?.encode(Utils.getUuid(), Gson().toJson(subItem)) + return 1 + } + + fun decodeSubscriptions(): List> { + val subscriptions = mutableListOf>() + subStorage?.allKeys()?.forEach { key -> + val json = subStorage?.decodeString(key) + if (!json.isNullOrBlank()) { + subscriptions.add(Pair(key, Gson().fromJson(json, SubscriptionItem::class.java))) + } + } + subscriptions.sortedBy { (_, value) -> value.addedTime } + return subscriptions + } + + fun removeSubscription(subid: String) { + subStorage?.remove(subid) + removeServerViaSubid(subid) + } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt index 05aefe3e..66845af2 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt @@ -20,16 +20,12 @@ import android.util.Log import android.util.Patterns import android.webkit.URLUtil import com.tencent.mmkv.MMKV -import com.v2ray.ang.AngApplication import com.v2ray.ang.AppConfig import com.v2ray.ang.R -import com.v2ray.ang.extension.defaultDPreference import com.v2ray.ang.extension.responseLength import com.v2ray.ang.extension.toast -import com.v2ray.ang.extension.v2RayApplication import com.v2ray.ang.service.V2RayServiceManager import kotlinx.coroutines.isActive -import me.dozen.dpreference.DPreference import java.io.IOException import java.net.* import kotlin.coroutines.coroutineContext @@ -37,6 +33,7 @@ import kotlin.coroutines.coroutineContext object Utils { private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) } + private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } private val tcpTestingSockets = ArrayList() /** @@ -126,8 +123,8 @@ object Utils { /** * get remote dns servers from preference */ - fun getRemoteDnsServers(defaultDPreference: DPreference): ArrayList { - val remoteDns = defaultDPreference.getPrefString(AppConfig.PREF_REMOTE_DNS, AppConfig.DNS_AGENT) + fun getRemoteDnsServers(): ArrayList { + val remoteDns = settingsStorage?.decodeString(AppConfig.PREF_REMOTE_DNS) ?: AppConfig.DNS_AGENT val ret = ArrayList() if (!TextUtils.isEmpty(remoteDns)) { remoteDns @@ -147,8 +144,8 @@ object Utils { /** * get remote dns servers from preference */ - fun getDomesticDnsServers(defaultDPreference: DPreference): ArrayList { - val domesticDns = defaultDPreference.getPrefString(AppConfig.PREF_DOMESTIC_DNS, AppConfig.DNS_DIRECT) + fun getDomesticDnsServers(): ArrayList { + val domesticDns = settingsStorage?.decodeString(AppConfig.PREF_DOMESTIC_DNS) ?: AppConfig.DNS_DIRECT val ret = ArrayList() if (!TextUtils.isEmpty(domesticDns)) { domesticDns diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt index 610c7476..ce260012 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt @@ -4,12 +4,12 @@ import android.content.Context import android.text.TextUtils import android.util.Log import com.google.gson.* +import com.tencent.mmkv.MMKV import com.v2ray.ang.AppConfig import com.v2ray.ang.dto.V2rayConfig import org.json.JSONException import org.json.JSONObject import com.v2ray.ang.dto.EConfigType -import com.v2ray.ang.extension.defaultDPreference object V2rayConfigUtil { // private val requestObj: JsonObject by lazy { @@ -19,6 +19,8 @@ object V2rayConfigUtil { // JSONObject("""{"version":"1.1","status":"200","reason":"OK","headers":{"Content-Type":["application/octet-stream","video/mpeg"],"Transfer-Encoding":["chunked"],"Connection":["keep-alive"],"Pragma":"no-cache"}}""") // } + private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } + data class Result(var status: Boolean, var content: String) /** @@ -28,7 +30,7 @@ object V2rayConfigUtil { try { val config = MmkvManager.decodeServerConfig(guid) ?: return Result(false, "") if (config.configType == EConfigType.CUSTOM) { - val customConfig = Gson().toJson(config.fullConfig) + val customConfig = config.fullConfig?.toPrettyPrinting() ?: return Result(false, "") Log.d("V2rayConfigUtilGoLog", customConfig) return Result(true, customConfig) } @@ -56,7 +58,7 @@ object V2rayConfigUtil { //转成Json val v2rayConfig = Gson().fromJson(assets, V2rayConfig::class.java) ?: return result - //v2rayConfig.log.loglevel = context.defaultDPreference.getPrefString(AppConfig.PREF_LOGLEVEL, "warning") + //v2rayConfig.log.loglevel = settingsStorage?.decodeString(AppConfig.PREF_LOGLEVEL) ?: "warning" inbounds(v2rayConfig, context) @@ -64,16 +66,13 @@ object V2rayConfigUtil { routing(v2rayConfig, context) - if (context.defaultDPreference.getPrefBoolean(AppConfig.PREF_LOCAL_DNS_ENABLED, false)) { + if (settingsStorage?.decodeBool(AppConfig.PREF_LOCAL_DNS_ENABLED) == true) { customLocalDns(v2rayConfig, context) } else { customRemoteDns(v2rayConfig, context) } - - val finalConfig = GsonBuilder().setPrettyPrinting().create().toJson(v2rayConfig) - result.status = true - result.content = finalConfig + result.content = v2rayConfig.toPrettyPrinting() return result } @@ -82,17 +81,17 @@ object V2rayConfigUtil { */ private fun inbounds(v2rayConfig: V2rayConfig, context: Context): Boolean { try { - //val socksPort = Utils.parseInt(context.defaultDPreference.getPrefStringNonEmpty(AppConfig.PREF_SOCKS_PORT, AppConfig .PORT_SOCKS)) - //val httpPort = Utils.parseInt(context.defaultDPreference.getPrefStringNonEmpty(AppConfig.PREF_HTTP_PORT, AppConfig.PORT_HTTP)) + //val socksPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_SOCKS_PORT) ?: AppConfig.PORT_SOCKS) + //val httpPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_HTTP_PORT) ?: AppConfig.PORT_HTTP) v2rayConfig.inbounds.forEach { curInbound -> - if (!context.defaultDPreference.getPrefBoolean(AppConfig.PREF_PROXY_SHARING, false)) { + if (!(settingsStorage?.decodeBool(AppConfig.PREF_PROXY_SHARING) ?: false)) { //bind all inbounds to localhost if the user requests curInbound.listen = "127.0.0.1" } } v2rayConfig.inbounds[0].port = 10808 - v2rayConfig.inbounds[0].sniffing?.enabled = context.defaultDPreference.getPrefBoolean(AppConfig.PREF_SNIFFING_ENABLED, true) + v2rayConfig.inbounds[0].sniffing?.enabled = settingsStorage?.decodeBool(AppConfig.PREF_SNIFFING_ENABLED) ?: true //v2rayConfig.inbounds[1].port = httpPort @@ -114,12 +113,12 @@ object V2rayConfigUtil { */ private fun routing(v2rayConfig: V2rayConfig, context: Context): Boolean { try { - routingUserRule(context.defaultDPreference.getPrefString(AppConfig.PREF_V2RAY_ROUTING_AGENT, ""), AppConfig.TAG_AGENT, v2rayConfig) - routingUserRule(context.defaultDPreference.getPrefString(AppConfig.PREF_V2RAY_ROUTING_DIRECT, ""), AppConfig.TAG_DIRECT, v2rayConfig) - routingUserRule(context.defaultDPreference.getPrefString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED, ""), AppConfig.TAG_BLOCKED, v2rayConfig) + routingUserRule(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) ?: "", AppConfig.TAG_AGENT, v2rayConfig) + routingUserRule(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT) ?: "", AppConfig.TAG_DIRECT, v2rayConfig) + routingUserRule(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED) ?: "", AppConfig.TAG_BLOCKED, v2rayConfig) - v2rayConfig.routing.domainStrategy = context.defaultDPreference.getPrefString(AppConfig.PREF_ROUTING_DOMAIN_STRATEGY, "IPIfNonMatch") - val routingMode = context.defaultDPreference.getPrefString(AppConfig.PREF_ROUTING_MODE, "0") + v2rayConfig.routing.domainStrategy = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_DOMAIN_STRATEGY) ?: "IPIfNonMatch" + val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) ?: "0" // Hardcode googleapis.cn val googleapisRoute = V2rayConfig.RoutingBean.RulesBean( @@ -234,32 +233,32 @@ object V2rayConfigUtil { try { val hosts = mutableMapOf() val servers = ArrayList() - val remoteDns = Utils.getRemoteDnsServers(context.defaultDPreference) + val remoteDns = Utils.getRemoteDnsServers() remoteDns.forEach { servers.add(it) } - val domesticDns = Utils.getDomesticDnsServers(context.defaultDPreference) + val domesticDns = Utils.getDomesticDnsServers() val geositeCn = arrayListOf("geosite:cn") val geoipCn = arrayListOf("geoip:cn") - val agDomain = userRule2Domian(context.defaultDPreference.getPrefString(AppConfig.PREF_V2RAY_ROUTING_AGENT, "")) + val agDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) ?: "") if (agDomain.size > 0) { servers.add(V2rayConfig.DnsBean.ServersBean(remoteDns.first(), 53, agDomain, null)) } - val dirDomain = userRule2Domian(context.defaultDPreference.getPrefString(AppConfig.PREF_V2RAY_ROUTING_DIRECT, "")) + val dirDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT) ?: "") if (dirDomain.size > 0) { servers.add(V2rayConfig.DnsBean.ServersBean(domesticDns.first(), 53, dirDomain, geoipCn)) } - val routingMode = context.defaultDPreference.getPrefString(AppConfig.PREF_ROUTING_MODE, "0") + val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) ?: "0" if (routingMode == "2" || routingMode == "3") { servers.add(V2rayConfig.DnsBean.ServersBean(domesticDns.first(), 53, geositeCn, geoipCn)) } - val blkDomain = userRule2Domian(context.defaultDPreference.getPrefString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED, "")) + val blkDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED) ?: "") if (blkDomain.size > 0) { hosts.putAll(blkDomain.map { it to "127.0.0.1" }) } @@ -279,7 +278,7 @@ object V2rayConfigUtil { port = 53, network = "tcp,udp") - //val localDnsPort = Utils.parseInt(context.defaultDPreference.getPrefStringNonEmpty(AppConfig.PREF_LOCAL_DNS_PORT, AppConfig.PORT_LOCAL_DNS)) + //val localDnsPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_LOCAL_DNS_PORT) ?: AppConfig.PORT_LOCAL_DNS) v2rayConfig.inbounds.add( V2rayConfig.InboundBean( tag = "dns-in", @@ -344,7 +343,7 @@ object V2rayConfigUtil { val servers = ArrayList() val hosts = mutableMapOf() - Utils.getRemoteDnsServers(context.defaultDPreference).forEach { + Utils.getRemoteDnsServers().forEach { servers.add(it) } // hardcode googleapi rule to fix play store problems diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/MainViewModel.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/MainViewModel.kt index c510d8d0..3e076cdc 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/MainViewModel.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/MainViewModel.kt @@ -24,9 +24,8 @@ import java.util.* class MainViewModel(application: Application) : AndroidViewModel(application) { private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) } - private val serverAffStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SERVER_AFF, MMKV.MULTI_PROCESS_MODE) } - var serverList= Gson().fromJson(mainStorage?.decodeString(KEY_ANG_CONFIGS), Array::class.java).toMutableList() + var serverList= MmkvManager.decodeServerList() private set val isRunning by lazy { MutableLiveData() } val updateListAction by lazy { MutableLiveData() } @@ -49,7 +48,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { } fun reloadServerList() { - serverList = Gson().fromJson(mainStorage?.decodeString(KEY_ANG_CONFIGS), Array::class.java).toMutableList() + serverList = MmkvManager.decodeServerList() updateListAction.value = -1 } @@ -85,11 +84,8 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { tcpingTestScope.launch { val testResult = Utils.tcping(serverAddress, serverPort) launch(Dispatchers.Main) { - MmkvManager.decodeServerAffiliationInfo(guid)?.let { aff -> - aff.testDelayMillis = testResult - serverAffStorage?.encode(guid, Gson().toJson(aff)) - updateListAction.value = serverList.indexOf(guid) - } + MmkvManager.encodeServerTestDelayMillis(guid, testResult) + updateListAction.value = serverList.indexOf(guid) } } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt index b2886046..d117ef2c 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt @@ -5,11 +5,14 @@ import android.arch.lifecycle.AndroidViewModel import android.content.SharedPreferences import android.support.v7.preference.PreferenceManager import android.util.Log +import com.tencent.mmkv.MMKV import com.v2ray.ang.AppConfig -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch +import com.v2ray.ang.util.MmkvManager class SettingsViewModel(application: Application) : AndroidViewModel(application), SharedPreferences.OnSharedPreferenceChangeListener { + + private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } + fun startListenPreferenceChange() { PreferenceManager.getDefaultSharedPreferences(getApplication()).registerOnSharedPreferenceChangeListener(this) } @@ -23,18 +26,27 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) { Log.d(AppConfig.ANG_PACKAGE, "Observe settings changed: $key") when(key) { - AppConfig.PREF_SNIFFING_ENABLED, - AppConfig.PREF_PROXY_SHARING, - AppConfig.PREF_LOCAL_DNS_ENABLED, + AppConfig.PREF_MODE, AppConfig.PREF_REMOTE_DNS, AppConfig.PREF_DOMESTIC_DNS, AppConfig.PREF_ROUTING_DOMAIN_STRATEGY, AppConfig.PREF_ROUTING_MODE, AppConfig.PREF_V2RAY_ROUTING_AGENT, AppConfig.PREF_V2RAY_ROUTING_BLOCKED, - AppConfig.PREF_V2RAY_ROUTING_DIRECT -> { - GlobalScope.launch { - } + AppConfig.PREF_V2RAY_ROUTING_DIRECT, -> { + settingsStorage?.encode(key, sharedPreferences.getString(key, "")) + } + AppConfig.PREF_SPEED_ENABLED, + AppConfig.PREF_SNIFFING_ENABLED, + AppConfig.PREF_PROXY_SHARING, + AppConfig.PREF_LOCAL_DNS_ENABLED, + AppConfig.PREF_FORWARD_IPV6, + AppConfig.PREF_PER_APP_PROXY, + AppConfig.PREF_BYPASS_APPS, -> { + settingsStorage?.encode(key, sharedPreferences.getBoolean(key, false)) + } + AppConfig.PREF_PER_APP_PROXY_SET -> { + settingsStorage?.encode(key, sharedPreferences.getStringSet(key, setOf())) } } } diff --git a/V2rayNG/dpreference/.gitignore b/V2rayNG/dpreference/.gitignore deleted file mode 100644 index 796b96d1..00000000 --- a/V2rayNG/dpreference/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/V2rayNG/dpreference/build.gradle b/V2rayNG/dpreference/build.gradle deleted file mode 100644 index 36a9e314..00000000 --- a/V2rayNG/dpreference/build.gradle +++ /dev/null @@ -1,25 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion Integer.parseInt("$compileSdkVer") - buildToolsVersion buildToolsVer - - defaultConfig { - minSdkVersion 17 - targetSdkVersion Integer.parseInt("$targetSdkVer") - versionCode 1 - versionName "1.0" - } - buildTypes { - release { - minifyEnabled false - } - } -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - testImplementation 'junit:junit:4.13' - implementation "com.android.support:support-annotations:$supportLibVersion" - implementation 'com.google.code.gson:gson:2.8.6' -} diff --git a/V2rayNG/dpreference/proguard-rules.pro b/V2rayNG/dpreference/proguard-rules.pro deleted file mode 100644 index c233c4c9..00000000 --- a/V2rayNG/dpreference/proguard-rules.pro +++ /dev/null @@ -1,17 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in /Users/wangyida/Library/Android/sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/V2rayNG/dpreference/src/main/AndroidManifest.xml b/V2rayNG/dpreference/src/main/AndroidManifest.xml deleted file mode 100644 index 8ca57060..00000000 --- a/V2rayNG/dpreference/src/main/AndroidManifest.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - diff --git a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/DPreference.java b/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/DPreference.java deleted file mode 100644 index fdc7eafe..00000000 --- a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/DPreference.java +++ /dev/null @@ -1,86 +0,0 @@ -package me.dozen.dpreference; - - -import android.content.Context; -import android.text.TextUtils; - -import java.util.LinkedHashSet; -import java.util.Set; - -/** - * Created by wangyida on 15-4-9. - */ -public class DPreference { - - Context mContext; - - /** - * preference file name - */ - String mName; - - private DPreference() { - } - - public DPreference(Context context, String name) { - this.mContext = context; - this.mName = name; - } - - public String getPrefString(final String key, final String defaultValue) { - return PrefAccessor.getString(mContext, mName, key, defaultValue); - } - - public void setPrefString(final String key, final String value) { - PrefAccessor.setString(mContext, mName, key, value); - } - - public boolean getPrefBoolean(final String key, final boolean defaultValue) { - return PrefAccessor.getBoolean(mContext, mName, key, defaultValue); - } - - public void setPrefBoolean(final String key, final boolean value) { - PrefAccessor.setBoolean(mContext, mName, key, value); - } - - public void setPrefInt(final String key, final int value) { - PrefAccessor.setInt(mContext, mName, key, value); - } - - public int getPrefInt(final String key, final int defaultValue) { - return PrefAccessor.getInt(mContext, mName, key, defaultValue); - } - - public void setPrefLong(final String key, final long value) { - PrefAccessor.setLong(mContext, mName, key, value); - } - - public long getPrefLong(final String key, final long defaultValue) { - return PrefAccessor.getLong(mContext, mName, key, defaultValue); - } - - public void setPrefStringSet(final String key, final Set value) { - PrefAccessor.setStringSet(mContext, mName, key, value); - } - - public Set getPrefStringSet(final String key, final Set defaultValue) { - return PrefAccessor.getStringSet(mContext, mName, key, defaultValue); - } - - public void setPrefStringOrderedSet(final String key, final LinkedHashSet value) { - PrefAccessor.setString(mContext, mName, key, StringSetConverter.encode(value)); - } - - public LinkedHashSet getPrefStringOrderedSet(final String key, final LinkedHashSet defaultValue) { - String value = PrefAccessor.getString(mContext, mName, key, ""); - if (TextUtils.isEmpty(value)) { - return defaultValue; - } - return StringSetConverter.decode(value); - } - - public void removePreference(final String key) { - PrefAccessor.remove(mContext, mName, key); - } - -} diff --git a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/IOUtils.java b/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/IOUtils.java deleted file mode 100644 index f8b8b961..00000000 --- a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/IOUtils.java +++ /dev/null @@ -1,61 +0,0 @@ -package me.dozen.dpreference; - - -import android.database.Cursor; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; - -final class IOUtils { - - // NOTE: This class is focussed on InputStream, OutputStream, Reader and - // Writer. Each method should take at least one of these as a parameter, - // or return one of them. - - private static final int EOF = -1; - - /** - * The default buffer size ({@value}) to use for {@link - */ - private static final int DEFAULT_BUFFER_SIZE = 1024; - - public static void closeQuietly(InputStream is) { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - // ignore - } - } - } - - public static void closeQuietly(OutputStream os) { - if (os != null) { - try { - os.close(); - } catch (IOException e) { - // ignore - } - } - } - - public static void closeQuietly(Reader r) { - if (r != null) { - try { - r.close(); - } catch (IOException e) { - // ignore - } - } - } - - public static void closeQuietly(Cursor cursor) { - if (cursor != null && !cursor.isClosed()) { - cursor.close(); - } - } - - -} diff --git a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/IPrefImpl.java b/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/IPrefImpl.java deleted file mode 100644 index 1e05769d..00000000 --- a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/IPrefImpl.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.dozen.dpreference; - - -import java.util.Set; - -/** - * Created by wangyida on 15/12/18. - */ -interface IPrefImpl { - - String getPrefString(String key, String defaultValue); - - void setPrefString(String key, String value); - - boolean getPrefBoolean(String key, boolean defaultValue); - - void setPrefBoolean(final String key, final boolean value); - - void setPrefInt(final String key, final int value); - - int getPrefInt(final String key, final int defaultValue); - - void setPrefFloat(final String key, final float value); - - float getPrefFloat(final String key, final float defaultValue); - - void setPrefLong(final String key, final long value); - - long getPrefLong(final String key, final long defaultValue); - - Set getPrefStringSet(String key, Set defaultValue); - - void setPrefStringSet(String key, Set value); - - void removePreference(final String key); - - boolean hasKey(String key); - -} diff --git a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PrefAccessor.java b/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PrefAccessor.java deleted file mode 100644 index 5986928d..00000000 --- a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PrefAccessor.java +++ /dev/null @@ -1,116 +0,0 @@ -package me.dozen.dpreference; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; - -import java.util.Set; - -/** - * Created by wangyida on 15/12/18. - */ -class PrefAccessor { - - public static String getString(Context context, String name, String key, String defaultValue) { - Uri URI = PreferenceProvider.buildUri(name, key, PreferenceProvider.PREF_STRING); - String value = defaultValue; - Cursor cursor = context.getContentResolver().query(URI, null, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - value = cursor.getString(cursor.getColumnIndex(PreferenceProvider.PREF_VALUE)); - } - IOUtils.closeQuietly(cursor); - return value; - } - - public static int getInt(Context context, String name, String key, int defaultValue) { - Uri URI = PreferenceProvider.buildUri(name, key, PreferenceProvider.PREF_INT); - int value = defaultValue; - Cursor cursor = context.getContentResolver().query(URI, null, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - value = cursor.getInt(cursor.getColumnIndex(PreferenceProvider.PREF_VALUE)); - } - IOUtils.closeQuietly(cursor); - return value; - } - - public static long getLong(Context context, String name, String key, long defaultValue) { - Uri URI = PreferenceProvider.buildUri(name, key, PreferenceProvider.PREF_LONG); - long value = defaultValue; - Cursor cursor = context.getContentResolver().query(URI, null, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - value = cursor.getLong(cursor.getColumnIndex(PreferenceProvider.PREF_VALUE)); - } - IOUtils.closeQuietly(cursor); - return value; - } - - public static boolean getBoolean(Context context, String name, String key, boolean defaultValue) { - Uri URI = PreferenceProvider.buildUri(name, key, PreferenceProvider.PREF_BOOLEAN); - int value = defaultValue ? 1 : 0; - Cursor cursor = context.getContentResolver().query(URI, null, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - value = cursor.getInt(cursor.getColumnIndex(PreferenceProvider.PREF_VALUE)); - } - IOUtils.closeQuietly(cursor); - return value == 1; - } - - public static Set getStringSet(Context context, String name, String key, Set defaultValue) { - Uri URI = PreferenceProvider.buildUri(name, key, PreferenceProvider.PREF_STRING_SET); - Set value = defaultValue; - Cursor cursor = context.getContentResolver().query(URI, null, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - String cursorString = cursor.getString(cursor.getColumnIndex(PreferenceProvider.PREF_VALUE)); - value = StringSetConverter.decode(cursorString); - } - IOUtils.closeQuietly(cursor); - return value; - } - - public static void remove(Context context, String name, String key) { - Uri URI = PreferenceProvider.buildUri(name, key, PreferenceProvider.PREF_STRING); - context.getContentResolver().delete(URI, null, null); - } - - public static void setString(Context context, String name, String key, String value) { - Uri URI = PreferenceProvider.buildUri(name, key, PreferenceProvider.PREF_STRING); - ContentValues cv = new ContentValues(); - cv.put(PreferenceProvider.PREF_KEY, key); - cv.put(PreferenceProvider.PREF_VALUE, value); - context.getContentResolver().update(URI, cv, null, null); - } - - public static void setBoolean(Context context, String name, String key, boolean value) { - Uri URI = PreferenceProvider.buildUri(name, key, PreferenceProvider.PREF_BOOLEAN); - ContentValues cv = new ContentValues(); - cv.put(PreferenceProvider.PREF_KEY, key); - cv.put(PreferenceProvider.PREF_VALUE, value); - context.getContentResolver().update(URI, cv, null, null); - } - - public static void setInt(Context context, String name, String key, int value) { - Uri URI = PreferenceProvider.buildUri(name, key, PreferenceProvider.PREF_INT); - ContentValues cv = new ContentValues(); - cv.put(PreferenceProvider.PREF_KEY, key); - cv.put(PreferenceProvider.PREF_VALUE, value); - context.getContentResolver().update(URI, cv, null, null); - } - - public static void setLong(Context context, String name, String key, long value) { - Uri URI = PreferenceProvider.buildUri(name, key, PreferenceProvider.PREF_LONG); - ContentValues cv = new ContentValues(); - cv.put(PreferenceProvider.PREF_KEY, key); - cv.put(PreferenceProvider.PREF_VALUE, value); - context.getContentResolver().update(URI, cv, null, null); - } - - public static void setStringSet(Context context, String name, String key, Set value) { - Uri URI = PreferenceProvider.buildUri(name, key, PreferenceProvider.PREF_STRING_SET); - ContentValues cv = new ContentValues(); - cv.put(PreferenceProvider.PREF_KEY, key); - cv.put(PreferenceProvider.PREF_VALUE, StringSetConverter.encode(value)); - context.getContentResolver().update(URI, cv, null, null); - } -} - diff --git a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PreferenceImpl.java b/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PreferenceImpl.java deleted file mode 100644 index bf36fa95..00000000 --- a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PreferenceImpl.java +++ /dev/null @@ -1,133 +0,0 @@ -package me.dozen.dpreference; - -import android.content.Context; -import android.content.SharedPreferences; - -import java.util.Set; - -/** - * Created by wangyida on 15/12/18. - */ -class PreferenceImpl implements IPrefImpl { - - private Context mContext; - - private String mPrefName; - - public PreferenceImpl(Context context, String prefName) { - mContext = context; - mPrefName = prefName; - } - - public String getPrefString(final String key, - final String defaultValue) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - return settings.getString(key, defaultValue); - } - - public void setPrefString(final String key, final String value) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - settings.edit().putString(key, value).apply(); - } - - public boolean getPrefBoolean(final String key, - final boolean defaultValue) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - return settings.getBoolean(key, defaultValue); - } - - public boolean hasKey(final String key) { - return mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE) - .contains(key); - } - - public void setPrefBoolean(final String key, final boolean value) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - settings.edit().putBoolean(key, value).apply(); - } - - public void setPrefInt(final String key, final int value) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - settings.edit().putInt(key, value).apply(); - } - - @Override - public Set getPrefStringSet(String key, Set defaultValue) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - return settings.getStringSet(key, defaultValue); - } - - @Override - public void setPrefStringSet(String key, Set value) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - settings.edit().putStringSet(key, value).apply(); - } - - public void increasePrefInt(final String key) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - increasePrefInt(settings, key); - } - - public void increasePrefInt(final SharedPreferences sp, final String key) { - final int v = sp.getInt(key, 0) + 1; - sp.edit().putInt(key, v).apply(); - } - - public void increasePrefInt(final SharedPreferences sp, final String key, - final int increment) { - final int v = sp.getInt(key, 0) + increment; - sp.edit().putInt(key, v).apply(); - } - - public int getPrefInt(final String key, final int defaultValue) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - return settings.getInt(key, defaultValue); - } - - public void setPrefFloat(final String key, final float value) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - settings.edit().putFloat(key, value).apply(); - } - - public float getPrefFloat(final String key, final float defaultValue) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - return settings.getFloat(key, defaultValue); - } - - public void setPrefLong(final String key, final long value) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - settings.edit().putLong(key, value).apply(); - } - - public long getPrefLong(final String key, final long defaultValue) { - final SharedPreferences settings = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - return settings.getLong(key, defaultValue); - } - - - public void removePreference(final String key) { - final SharedPreferences prefs = - mContext.getSharedPreferences(mPrefName, Context.MODE_PRIVATE); - prefs.edit().remove(key).apply(); - } - - public void clearPreference(final SharedPreferences p) { - final SharedPreferences.Editor editor = p.edit(); - editor.clear(); - editor.apply(); - } - -} diff --git a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PreferenceProvider.java b/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PreferenceProvider.java deleted file mode 100644 index f8bf2a94..00000000 --- a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/PreferenceProvider.java +++ /dev/null @@ -1,267 +0,0 @@ -package me.dozen.dpreference; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.content.UriMatcher; -import android.database.Cursor; -import android.database.MatrixCursor; -import android.net.Uri; -import android.support.annotation.Nullable; -import android.text.TextUtils; - -import java.util.HashMap; -import java.util.Map; - -/** - * Created by wangyida on 15/12/18. - */ -public class PreferenceProvider extends ContentProvider { - - private static final String TAG = PreferenceProvider.class.getSimpleName(); - - private static final String AUTHORITY = "com.v2ray.ang.dpreference"; - - public static final String CONTENT_PREF_BOOLEAN_URI = "content://" + AUTHORITY + "/boolean/"; - public static final String CONTENT_PREF_STRING_URI = "content://" + AUTHORITY + "/string/"; - public static final String CONTENT_PREF_INT_URI = "content://" + AUTHORITY + "/integer/"; - public static final String CONTENT_PREF_LONG_URI = "content://" + AUTHORITY + "/long/"; - public static final String CONTENT_PREF_STRING_SET_URI = "content://" + AUTHORITY + "/string_set/"; - - - public static final String PREF_KEY = "key"; - public static final String PREF_VALUE = "value"; - - public static final int PREF_BOOLEAN = 1; - public static final int PREF_STRING = 2; - public static final int PREF_INT = 3; - public static final int PREF_LONG = 4; - public static final int PREF_STRING_SET = 5; - - private static final UriMatcher sUriMatcher; - - static { - sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); - sUriMatcher.addURI(AUTHORITY, "boolean/*/*", PREF_BOOLEAN); - sUriMatcher.addURI(AUTHORITY, "string/*/*", PREF_STRING); - sUriMatcher.addURI(AUTHORITY, "integer/*/*", PREF_INT); - sUriMatcher.addURI(AUTHORITY, "long/*/*", PREF_LONG); - sUriMatcher.addURI(AUTHORITY, "string_set/*/*", PREF_STRING_SET); - - } - - @Override - public boolean onCreate() { - return true; - } - - @Nullable - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - MatrixCursor cursor = null; - PrefModel model = getPrefModelByUri(uri); - switch (sUriMatcher.match(uri)) { - case PREF_BOOLEAN: - if (getDPreference(model.getName()).hasKey(model.getKey())) { - cursor = preferenceToCursor(getDPreference(model.getName()).getPrefBoolean(model.getKey(), false) ? 1 : 0); - } - break; - case PREF_STRING: - if (getDPreference(model.getName()).hasKey(model.getKey())) { - cursor = preferenceToCursor(getDPreference(model.getName()).getPrefString(model.getKey(), "")); - } - break; - case PREF_INT: - if (getDPreference(model.getName()).hasKey(model.getKey())) { - cursor = preferenceToCursor(getDPreference(model.getName()).getPrefInt(model.getKey(), -1)); - } - break; - case PREF_LONG: - if (getDPreference(model.getName()).hasKey(model.getKey())) { - cursor = preferenceToCursor(getDPreference(model.getName()).getPrefLong(model.getKey(), -1)); - } - break; - case PREF_STRING_SET: - if (getDPreference(model.getName()).hasKey(model.getKey())) { - cursor = preferenceToCursor(getDPreference(model.getName()).getPrefStringSet(model.getKey(), null)); - } - break; - } - return cursor; - } - - @Nullable - @Override - public String getType(Uri uri) { - return null; - } - - @Nullable - @Override - public Uri insert(Uri uri, ContentValues values) { - throw new IllegalStateException("insert unsupport!!!"); - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - switch (sUriMatcher.match(uri)) { - case PREF_BOOLEAN: - case PREF_LONG: - case PREF_STRING: - case PREF_INT: - case PREF_STRING_SET: - PrefModel model = getPrefModelByUri(uri); - if (model != null) { - getDPreference(model.getName()).removePreference(model.getKey()); - } - break; - default: - throw new IllegalStateException(" unsupported uri : " + uri); - } - return 0; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - PrefModel model = getPrefModelByUri(uri); - if (model == null) { - throw new IllegalArgumentException("update prefModel is null"); - } - switch (sUriMatcher.match(uri)) { - case PREF_BOOLEAN: - persistBoolean(model.getName(), values); - break; - case PREF_LONG: - persistLong(model.getName(), values); - break; - case PREF_STRING: - persistString(model.getName(), values); - break; - case PREF_INT: - persistInt(model.getName(), values); - break; - case PREF_STRING_SET: - persistStringSet(model.getName(), values); - break; - default: - throw new IllegalStateException("update unsupported uri : " + uri); - } - return 0; - } - - private static String[] PREFERENCE_COLUMNS = {PREF_VALUE}; - - private MatrixCursor preferenceToCursor(T value) { - MatrixCursor matrixCursor = new MatrixCursor(PREFERENCE_COLUMNS, 1); - MatrixCursor.RowBuilder builder = matrixCursor.newRow(); - builder.add(value); - return matrixCursor; - } - - private void persistInt(String name, ContentValues values) { - if (values == null) { - throw new IllegalArgumentException(" values is null!!!"); - } - String kInteger = values.getAsString(PREF_KEY); - int vInteger = values.getAsInteger(PREF_VALUE); - getDPreference(name).setPrefInt(kInteger, vInteger); - } - - private void persistBoolean(String name, ContentValues values) { - if (values == null) { - throw new IllegalArgumentException(" values is null!!!"); - } - String kBoolean = values.getAsString(PREF_KEY); - boolean vBoolean = values.getAsBoolean(PREF_VALUE); - getDPreference(name).setPrefBoolean(kBoolean, vBoolean); - } - - private void persistLong(String name, ContentValues values) { - if (values == null) { - throw new IllegalArgumentException(" values is null!!!"); - } - String kLong = values.getAsString(PREF_KEY); - long vLong = values.getAsLong(PREF_VALUE); - getDPreference(name).setPrefLong(kLong, vLong); - } - - private void persistString(String name, ContentValues values) { - if (values == null) { - throw new IllegalArgumentException(" values is null!!!"); - } - String kString = values.getAsString(PREF_KEY); - String vString = values.getAsString(PREF_VALUE); - getDPreference(name).setPrefString(kString, vString); - } - - private void persistStringSet(String name, ContentValues values) { - if (values == null) { - throw new IllegalArgumentException(" values is null!!!"); - } - String kString = values.getAsString(PREF_KEY); - String vString = values.getAsString(PREF_VALUE); - getDPreference(name).setPrefStringSet(kString, StringSetConverter.decode(vString)); - } - - private static Map sPreferences = new HashMap<>(); - - private IPrefImpl getDPreference(String name) { - if (TextUtils.isEmpty(name)) { - throw new IllegalArgumentException("getDPreference name is null!!!"); - } - if (sPreferences.get(name) == null) { - IPrefImpl pref = new PreferenceImpl(getContext(), name); - sPreferences.put(name, pref); - } - return sPreferences.get(name); - } - - private PrefModel getPrefModelByUri(Uri uri) { - if (uri == null || uri.getPathSegments().size() != 3) { - throw new IllegalArgumentException("getPrefModelByUri uri is wrong : " + uri); - } - String name = uri.getPathSegments().get(1); - String key = uri.getPathSegments().get(2); - return new PrefModel(name, key); - } - - - public static Uri buildUri(String name, String key, int type) { - return Uri.parse(getUriByType(type) + name + "/" + key); - } - - private static String getUriByType(int type) { - switch (type) { - case PreferenceProvider.PREF_BOOLEAN: - return PreferenceProvider.CONTENT_PREF_BOOLEAN_URI; - case PreferenceProvider.PREF_INT: - return PreferenceProvider.CONTENT_PREF_INT_URI; - case PreferenceProvider.PREF_LONG: - return PreferenceProvider.CONTENT_PREF_LONG_URI; - case PreferenceProvider.PREF_STRING: - return PreferenceProvider.CONTENT_PREF_STRING_URI; - case PreferenceProvider.PREF_STRING_SET: - return PreferenceProvider.CONTENT_PREF_STRING_SET_URI; - } - throw new IllegalStateException("unsupport preftype : " + type); - } - - private static class PrefModel { - String name; - - String key; - - public PrefModel(String name, String key) { - this.name = name; - this.key = key; - } - - public String getName() { - return name; - } - - public String getKey() { - return key; - } - } - -} diff --git a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/StringSetConverter.java b/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/StringSetConverter.java deleted file mode 100644 index 8350d46b..00000000 --- a/V2rayNG/dpreference/src/main/java/me/dozen/dpreference/StringSetConverter.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.dozen.dpreference; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - -import java.lang.reflect.Type; -import java.util.LinkedHashSet; -import java.util.Set; - -public class StringSetConverter { - private static final Gson gson = new Gson(); - - public static String encode(Set src) { - return gson.toJson(src); - } - - public static LinkedHashSet decode(String json) { - Type setType = new TypeToken>() { - }.getType(); - return gson.fromJson(json, setType); - } -} diff --git a/V2rayNG/settings.gradle b/V2rayNG/settings.gradle index 61ddbe8d..e7b4def4 100644 --- a/V2rayNG/settings.gradle +++ b/V2rayNG/settings.gradle @@ -1 +1 @@ -include ':app', ':dpreference' +include ':app'