Optimize Storage

This commit is contained in:
2dust
2024-09-22 14:30:27 +08:00
parent 35b44f1955
commit fa7da3be10
10 changed files with 104 additions and 114 deletions
@@ -16,7 +16,6 @@ import com.v2ray.ang.dto.ServerConfig
import com.v2ray.ang.dto.V2rayConfig
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.MmkvManager
import com.v2ray.ang.util.MmkvManager.serverRawStorage
import com.v2ray.ang.util.Utils
import me.drakeet.support.toast.ToastCompat
@@ -52,7 +51,7 @@ class ServerCustomConfigActivity : BaseActivity() {
*/
private fun bindingServer(config: ServerConfig): Boolean {
binding.etRemarks.text = Utils.getEditable(config.remarks)
val raw = serverRawStorage?.decodeString(editGuid)
val raw = MmkvManager.decodeServerRaw(editGuid)
if (raw.isNullOrBlank()) {
binding.editor.setTextContent(Utils.getEditable(config.fullConfig?.toPrettyPrinting().orEmpty()))
} else {
@@ -91,7 +90,7 @@ class ServerCustomConfigActivity : BaseActivity() {
config.fullConfig = v2rayConfig
MmkvManager.encodeServerConfig(editGuid, config)
serverRawStorage?.encode(editGuid, binding.editor.text.toString())
MmkvManager.encodeServerRaw(editGuid, binding.editor.text.toString())
toast(R.string.toast_success)
finish()
return true
@@ -6,13 +6,11 @@ import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.lifecycleScope
import com.google.gson.Gson
import com.v2ray.ang.R
import com.v2ray.ang.databinding.ActivitySubEditBinding
import com.v2ray.ang.dto.SubscriptionItem
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.MmkvManager
import com.v2ray.ang.util.MmkvManager.subStorage
import com.v2ray.ang.util.Utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -30,9 +28,9 @@ class SubEditActivity : BaseActivity() {
setContentView(binding.root)
title = getString(R.string.title_sub_setting)
val json = subStorage?.decodeString(editSubId)
if (!json.isNullOrBlank()) {
bindingServer(Gson().fromJson(json, SubscriptionItem::class.java))
val subItem = MmkvManager.decodeSubscription(editSubId)
if (subItem != null) {
bindingServer(subItem)
} else {
clearServer()
}
@@ -67,13 +65,7 @@ class SubEditActivity : BaseActivity() {
* save server config
*/
private fun saveServer(): Boolean {
val subItem: SubscriptionItem
val json = subStorage?.decodeString(editSubId)
if (!json.isNullOrBlank()) {
subItem = Gson().fromJson(json, SubscriptionItem::class.java)
} else {
subItem = SubscriptionItem()
}
val subItem = MmkvManager.decodeSubscription(editSubId)?:SubscriptionItem()
subItem.remarks = binding.etRemarks.text.toString()
subItem.url = binding.etUrl.text.toString()
@@ -28,7 +28,7 @@ class TaskerActivity : BaseActivity() {
lstData.add("Default")
lstGuid.add(AppConfig.TASKER_DEFAULT_GUID)
MmkvManager.serverStorage?.allKeys()?.forEach { key ->
MmkvManager.decodeServerList()?.forEach { key ->
MmkvManager.decodeServerConfig(key)?.let { config ->
lstData.add(config.remarks)
lstGuid.add(key)
@@ -19,7 +19,6 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.gson.Gson
import com.tbruyelle.rxpermissions3.RxPermissions
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
@@ -30,7 +29,6 @@ import com.v2ray.ang.dto.AssetUrlItem
import com.v2ray.ang.extension.toTrafficString
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.MmkvManager
import com.v2ray.ang.util.MmkvManager.assetStorage
import com.v2ray.ang.util.MmkvManager.settingsStorage
import com.v2ray.ang.util.Utils
import kotlinx.coroutines.Dispatchers
@@ -137,7 +135,7 @@ class UserAssetActivity : BaseActivity() {
toast(R.string.msg_remark_is_duplicate)
return@registerForActivityResult
}
assetStorage?.encode(assetId, Gson().toJson(assetItem))
MmkvManager.encodeAsset(assetId, assetItem)
copyFile(uri)
} catch (e: Exception) {
toast(R.string.toast_asset_copy_failed)
@@ -5,13 +5,11 @@ import android.text.TextUtils
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AlertDialog
import com.google.gson.Gson
import com.v2ray.ang.R
import com.v2ray.ang.databinding.ActivityUserAssetUrlBinding
import com.v2ray.ang.dto.AssetUrlItem
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.MmkvManager
import com.v2ray.ang.util.MmkvManager.assetStorage
import com.v2ray.ang.util.Utils
import java.io.File
@@ -29,9 +27,9 @@ class UserAssetUrlActivity : BaseActivity() {
setContentView(binding.root)
title = getString(R.string.title_user_asset_add_url)
val json = assetStorage?.decodeString(editAssetId)
if (!json.isNullOrBlank()) {
bindingAsset(Gson().fromJson(json, AssetUrlItem::class.java))
val assetItem = MmkvManager.decodeAsset(editAssetId)
if (assetItem != null) {
bindingAsset(assetItem)
} else {
clearAsset()
}
@@ -59,12 +57,9 @@ class UserAssetUrlActivity : BaseActivity() {
* save asset config
*/
private fun saveServer(): Boolean {
val assetItem: AssetUrlItem
val json = assetStorage?.decodeString(editAssetId)
var assetItem = MmkvManager.decodeAsset(editAssetId)
var assetId = editAssetId
if (!json.isNullOrBlank()) {
assetItem = Gson().fromJson(json, AssetUrlItem::class.java)
if (assetItem != null) {
// remove file associated with the asset
val file = extDir.resolve(assetItem.remarks)
if (file.exists()) {
@@ -95,7 +90,7 @@ class UserAssetUrlActivity : BaseActivity() {
return false
}
assetStorage?.encode(assetId, Gson().toJson(assetItem))
MmkvManager.encodeAsset(assetId, assetItem)
toast(R.string.toast_success)
finish()
return true
@@ -13,7 +13,6 @@ import com.google.gson.reflect.TypeToken
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.dto.*
import com.v2ray.ang.util.MmkvManager.serverRawStorage
import com.v2ray.ang.util.MmkvManager.settingsStorage
import com.v2ray.ang.util.fmt.ShadowsocksFmt
import com.v2ray.ang.util.fmt.SocksFmt
@@ -178,39 +177,6 @@ object AngConfigManager {
return 0
}
// /**
// * upgrade
// */
// private fun upgradeServerVersion(vmess: AngConfig.VmessBean): Int {
// try {
// if (vmess.configVersion == 2) {
// return 0
// }
//
// when (vmess.network) {
// "ws", "h2" -> {
// var path = ""
// var host = ""
// val lstParameter = vmess.requestHost.split(";")
// if (lstParameter.isNotEmpty()) {
// path = lstParameter[0].trim()
// }
// if (lstParameter.size > 1) {
// path = lstParameter[0].trim()
// host = lstParameter[1].trim()
// }
// vmess.path = path
// vmess.requestHost = host
// }
// }
// vmess.configVersion = 2
// return 0
// } catch (e: Exception) {
// e.printStackTrace()
// return -1
// }
// }
fun importBatchConfig(server: String?, subid: String, append: Boolean): Pair<Int, Int> {
var count = parseBatchConfig(Utils.decode(server), subid, append)
if (count <= 0) {
@@ -325,7 +291,7 @@ object AngConfigManager {
.toString())
config.subscriptionId = subid
val key = MmkvManager.encodeServerConfig("", config)
serverRawStorage?.encode(key, gson.toJson(srv))
MmkvManager.encodeServerRaw(key, gson.toJson(srv))
count += 1
}
return count
@@ -340,14 +306,14 @@ object AngConfigManager {
config.fullConfig = Gson().fromJson(server, V2rayConfig::class.java)
config.remarks = config.fullConfig?.remarks ?: System.currentTimeMillis().toString()
val key = MmkvManager.encodeServerConfig("", config)
serverRawStorage?.encode(key, server)
MmkvManager.encodeServerRaw(key, server)
return 1
} else if (server.startsWith("[Interface]") && server.contains("[Peer]")) {
val config = WireguardFmt.parseWireguardConfFile(server)
?: return R.string.toast_incorrect_protocol
config.fullConfig?.remarks ?: System.currentTimeMillis().toString()
val key = MmkvManager.encodeServerConfig("", config)
serverRawStorage?.encode(key, server)
MmkvManager.encodeServerRaw(key, server)
return 1
} else {
return 0
@@ -11,6 +11,9 @@ import com.v2ray.ang.dto.ServerConfig
import com.v2ray.ang.dto.SubscriptionItem
object MmkvManager {
//region private
private const val ID_MAIN = "MAIN"
private const val ID_SERVER_CONFIG = "SERVER_CONFIG"
private const val ID_PROFILE_CONFIG = "PROFILE_CONFIG"
@@ -25,12 +28,16 @@ object MmkvManager {
private val mainStorage by lazy { MMKV.mmkvWithID(ID_MAIN, MMKV.MULTI_PROCESS_MODE) }
val settingsStorage by lazy { MMKV.mmkvWithID(ID_SETTING, MMKV.MULTI_PROCESS_MODE) }
val serverStorage by lazy { MMKV.mmkvWithID(ID_SERVER_CONFIG, MMKV.MULTI_PROCESS_MODE) }
private val serverStorage by lazy { MMKV.mmkvWithID(ID_SERVER_CONFIG, MMKV.MULTI_PROCESS_MODE) }
private val profileStorage by lazy { MMKV.mmkvWithID(ID_PROFILE_CONFIG, MMKV.MULTI_PROCESS_MODE) }
private val serverAffStorage by lazy { MMKV.mmkvWithID(ID_SERVER_AFF, MMKV.MULTI_PROCESS_MODE) }
val subStorage by lazy { MMKV.mmkvWithID(ID_SUB, MMKV.MULTI_PROCESS_MODE) }
val assetStorage by lazy { MMKV.mmkvWithID(ID_ASSET, MMKV.MULTI_PROCESS_MODE) }
val serverRawStorage by lazy { MMKV.mmkvWithID(ID_SERVER_RAW, MMKV.MULTI_PROCESS_MODE) }
private val subStorage by lazy { MMKV.mmkvWithID(ID_SUB, MMKV.MULTI_PROCESS_MODE) }
private val assetStorage by lazy { MMKV.mmkvWithID(ID_ASSET, MMKV.MULTI_PROCESS_MODE) }
private val serverRawStorage by lazy { MMKV.mmkvWithID(ID_SERVER_RAW, MMKV.MULTI_PROCESS_MODE) }
//endregion
//region Server
fun getSelectServer(): String? {
return mainStorage.decodeString(KEY_SELECTED_SERVER)
@@ -82,7 +89,7 @@ object MmkvManager {
if (!serverList.contains(key)) {
serverList.add(0, key)
encodeServerList(serverList)
if (MmkvManager.getSelectServer().isNullOrBlank()) {
if (getSelectServer().isNullOrBlank()) {
mainStorage.encode(KEY_SELECTED_SERVER, key)
}
}
@@ -101,7 +108,7 @@ object MmkvManager {
if (guid.isBlank()) {
return
}
if (MmkvManager.getSelectServer() == guid) {
if (getSelectServer() == guid) {
mainStorage.remove(KEY_SELECTED_SERVER)
}
val serverList = decodeServerList()
@@ -154,7 +161,44 @@ object MmkvManager {
}
}
fun initSubsList() {
fun removeAllServer() {
mainStorage.clearAll()
serverStorage.clearAll()
profileStorage.clearAll()
serverAffStorage.clearAll()
}
fun removeInvalidServer(guid: String) {
if (guid.isNotEmpty()) {
decodeServerAffiliationInfo(guid)?.let { aff ->
if (aff.testDelayMillis < 0L) {
removeServer(guid)
}
}
} else {
serverAffStorage.allKeys()?.forEach { key ->
decodeServerAffiliationInfo(key)?.let { aff ->
if (aff.testDelayMillis < 0L) {
removeServer(key)
}
}
}
}
}
fun encodeServerRaw(guid: String, config: String) {
serverRawStorage.encode(guid, config)
}
fun decodeServerRaw(guid: String): String? {
return serverRawStorage.decodeString(guid) ?: return null
}
//endregion
//region Subscriptions
private fun initSubsList() {
val subsList = decodeSubsList()
if (subsList.isNotEmpty()) {
return
@@ -216,6 +260,10 @@ object MmkvManager {
}
}
//endregion
//region Asset
fun decodeAssetUrls(): List<Pair<String, AssetUrlItem>> {
val assetUrlItems = mutableListOf<Pair<String, AssetUrlItem>>()
assetStorage.allKeys()?.forEach { key ->
@@ -231,44 +279,19 @@ object MmkvManager {
assetStorage.remove(assetid)
}
fun removeAllServer() {
mainStorage.clearAll()
serverStorage.clearAll()
profileStorage.clearAll()
serverAffStorage.clearAll()
fun encodeAsset(assetid: String, assetItem: AssetUrlItem) {
val key = assetid.ifBlank { Utils.getUuid() }
assetStorage.encode(key, Gson().toJson(assetItem))
}
fun removeInvalidServer(guid: String) {
if (guid.isNotEmpty()) {
decodeServerAffiliationInfo(guid)?.let { aff ->
if (aff.testDelayMillis < 0L) {
removeServer(guid)
}
}
} else {
serverAffStorage.allKeys()?.forEach { key ->
decodeServerAffiliationInfo(key)?.let { aff ->
if (aff.testDelayMillis < 0L) {
removeServer(key)
}
}
}
}
fun decodeAsset(assetid: String): AssetUrlItem? {
val json = assetStorage.decodeString(assetid) ?: return null
return Gson().fromJson(json, AssetUrlItem::class.java)
}
fun getServerViaRemarks(remarks: String?): ServerConfig? {
if (remarks == null) {
return null
}
val serverList = decodeServerList()
for (guid in serverList) {
val profile = decodeProfileConfig(guid)
if (profile != null && profile.remarks == remarks) {
return decodeServerConfig(guid)
}
}
return null
}
//endregion
//region Routing
fun decodeRoutingRulesets(): MutableList<RulesetItem>? {
val ruleset = settingsStorage.decodeString(PREF_ROUTING_RULESET)
@@ -282,4 +305,6 @@ object MmkvManager {
else
settingsStorage.encode(PREF_ROUTING_RULESET, Gson().toJson(rulesetList))
}
//endregion
}
@@ -2,10 +2,12 @@ package com.v2ray.ang.util
import android.content.Context
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.v2ray.ang.dto.RulesetItem
import com.v2ray.ang.util.MmkvManager.subStorage
import com.v2ray.ang.dto.ServerConfig
import com.v2ray.ang.util.MmkvManager.decodeProfileConfig
import com.v2ray.ang.util.MmkvManager.decodeServerConfig
import com.v2ray.ang.util.MmkvManager.decodeServerList
import java.util.Collections
object SettingsManager {
@@ -90,5 +92,18 @@ object SettingsManager {
MmkvManager.encodeSubsList(subsList)
}
fun getServerViaRemarks(remarks: String?): ServerConfig? {
if (remarks == null) {
return null
}
val serverList = decodeServerList()
for (guid in serverList) {
val profile = decodeProfileConfig(guid)
if (profile != null && profile.remarks == remarks) {
return decodeServerConfig(guid)
}
}
return null
}
}
@@ -30,7 +30,7 @@ object V2rayConfigUtil {
try {
val config = MmkvManager.decodeServerConfig(guid) ?: return Result(false)
if (config.configType == EConfigType.CUSTOM) {
val raw = MmkvManager.serverRawStorage?.decodeString(guid)
val raw = MmkvManager.decodeServerRaw(guid)
val customConfig = if (raw.isNullOrBlank()) {
config.fullConfig?.toPrettyPrinting() ?: return Result(false)
} else {
@@ -526,7 +526,7 @@ object V2rayConfigUtil {
val outbound = v2rayConfig.outbounds[0]
//Previous proxy
val prevNode = MmkvManager.getServerViaRemarks(subItem.prevProfile)
val prevNode = SettingsManager.getServerViaRemarks(subItem.prevProfile)
if (prevNode != null) {
val prevOutbound = prevNode.getProxyOutbound()
if (prevOutbound != null) {
@@ -542,7 +542,7 @@ object V2rayConfigUtil {
}
//Next proxy
val nextNode = MmkvManager.getServerViaRemarks(subItem.nextProfile)
val nextNode = SettingsManager.getServerViaRemarks(subItem.nextProfile)
if (nextNode != null) {
val nextOutbound = nextNode.getProxyOutbound()
if (nextOutbound != null) {
@@ -101,7 +101,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
config.fullConfig = Gson().fromJson(server, V2rayConfig::class.java)
config.remarks = config.fullConfig?.remarks ?: System.currentTimeMillis().toString()
val key = MmkvManager.encodeServerConfig("", config)
MmkvManager.serverRawStorage?.encode(key, server)
MmkvManager.encodeServerRaw(key, server)
serverList.add(0, key)
val profile = ProfileItem(
configType = config.configType,