Compare commits

..

78 Commits

Author SHA1 Message Date
2dust 6b9728dc84 Update 1.8.19 2024-03-30 17:25:08 +08:00
2dust 1ce9b7c0c8 Merge pull request #2956 from xfree-man/master
Add observatory to V2rayConfig, to enable load balancing features in a custom config
2024-03-27 07:53:57 +08:00
xfree-man ff75d3fdc2 Add observatory to V2rayConfig 2024-03-26 13:31:04 +04:00
2dust 8154812570 Merge pull request #2948 from Amir-yazdanmanesh/master
Fix deprecated codes
2024-03-22 09:58:44 +08:00
amir 1dcd2478fc Expression should use clarifying parentheses 2024-03-20 12:37:53 +03:30
amir 0515806e92 Remove deprecated codes in MainActivity.kt 2024-03-20 12:37:32 +03:30
2dust f286506ba4 Bug fix 2024-03-16 17:11:38 +08:00
2dust 48be736275 Merge pull request #2933 from Utaea/pr
Add support to transport for shadowsocks
2024-03-16 16:58:20 +08:00
2dust af0faeab16 Merge pull request #2928 from yuhan6665/authority
Add authority for gRPC
2024-03-16 16:31:12 +08:00
2dust fb6edee842 Merge branch 'master' into authority 2024-03-16 16:30:28 +08:00
2dust 1209c4b92a Merge pull request #2921 from solokot/master
Update & improve Russian translation
2024-03-16 16:26:31 +08:00
Utaea e4e668b492 Add support to transport for shadowsocks 2024-03-15 03:51:49 +00:00
yuhan6665 92d3136a23 Add authority for gRPC 2024-03-13 12:57:08 -04:00
solokot f6e74ddb45 Update & improve Russian translation 2024-03-12 10:22:16 +03:00
2dust c34f332771 Update 1.8.18 2024-03-12 10:49:52 +08:00
2dust eb1d71bda6 Add httpupgrade 2024-03-12 10:49:32 +08:00
2dust 3cdd5822cb Merge pull request #2915 from Malus-risus/master
Update dependency
2024-03-10 10:25:07 +08:00
Το μοχθηρό ^_^ 8f924b5ce1 Delete renovate.json 2024-03-09 17:33:08 +08:00
Το μοχθηρό ^_^ 2ae645dce5 Merge pull request #24 from Malus-risus/renovate/com.android.library-8.x
Update plugin com.android.library to v8.3.0
2024-03-09 17:20:13 +08:00
renovate[bot] f848a7119f Update plugin com.android.library to v8.3.0 2024-03-09 09:12:10 +00:00
Το μοχθηρό ^_^ 2fa41db32f Merge pull request #23 from Malus-risus/renovate/com.android.application-8.x
Update plugin com.android.application to v8.3.0
2024-03-09 17:11:24 +08:00
Το μοχθηρό ^_^ 9af4516761 Merge pull request #22 from Malus-risus/renovate/kotlin-ksp
Update Kotlin, KSP to v1.9.23
2024-03-09 17:11:03 +08:00
renovate[bot] 189b07124d Update plugin com.android.application to v8.3.0 2024-03-09 08:19:13 +00:00
renovate[bot] e6e5cdcdcd Update Kotlin, KSP to v1.9.23 2024-03-09 08:19:07 +00:00
Το μοχθηρό ^_^ a31e4dab85 Create renovate.json 2024-03-09 16:18:14 +08:00
2dust b2a9397dc7 Revert "Merge pull request #2903 from ssszmath/master"
This reverts commit a536df1a02, reversing
changes made to 2dc82b7e83.
2024-03-07 08:22:28 +08:00
2dust a536df1a02 Merge pull request #2903 from ssszmath/master
Fixing the problem of connecting to the Internet after publishing the application on Google Play in aab format
2024-03-07 08:06:04 +08:00
Sajad Sajad 1a2751563d add NativeLibs configuration to manifest and gradle.properties 2024-03-05 19:12:04 +03:30
2dust 2dc82b7e83 Merge pull request #2892 from vfarid/add_remark_to_custom_configs
Added remarks to all custom configs
2024-03-03 16:59:03 +08:00
2dust b02d81ae53 Merge pull request #2889 from vfarid/more_fragment_options
More fragment options + Fix for reality configs
2024-03-03 16:53:22 +08:00
Vahid Farid 773bcc5658 Set V2rayConfig remarks based on ServerConfig in V2rayConfigUtil.kt 2024-03-02 18:30:05 +03:30
Vahid Farid 9142b9cfb4 Update AngConfigManager.kt
Added remark for single config subscription
Removed unnecessary code in multiple config subscription update
2024-03-02 18:27:59 +03:30
Vahid Farid 376882d975 Add remark to custom-config for export in ServerCustomConfigActivity.kt 2024-03-02 18:26:00 +03:30
Vahid Farid f330c32ccc Get config name from custom-config's remark during import in MainViewModel.kt 2024-03-02 18:25:01 +03:30
Vahid Farid 58dbb71b53 Fix fragment for reality configs 2024-03-02 16:54:17 +03:30
Vahid Farid ebd0257f6e Added new fragment packets for reality 2024-03-02 16:53:34 +03:30
2dust 945c584fc6 Merge pull request #2886 from MrMalekfar/master
Addressing issue #2880
2024-03-01 08:07:55 +08:00
MrMalekfar 19cd24c37a Update AngConfigManager.kt 2024-03-01 02:35:56 +03:30
MrMalekfar 3994810c4e Update AngConfigManager.kt 2024-03-01 02:06:36 +03:30
MrMalekfar d86e68c77a Update AngConfigManager.kt 2024-03-01 01:51:08 +03:30
MrMalekfar cc7bdefe54 Update AngConfigManager.kt 2024-03-01 01:27:59 +03:30
MrMalekfar 51b32a030a Update AngConfigManager.kt 2024-02-29 14:15:05 +03:30
MrMalekfar 6c76ddd145 Update AngConfigManager.kt 2024-02-29 14:12:19 +03:30
MrMalekfar 0d12cc5dc8 Update AngConfigManager.kt 2024-02-29 13:55:52 +03:30
MrMalekfar cfb756723c Update AngConfigManager.kt 2024-02-29 11:07:39 +03:30
MrMalekfar 0e9f198341 Update AngConfigManager.kt 2024-02-29 09:59:58 +03:30
MrMalekfar 1fa1325630 Update AngConfigManager.kt 2024-02-29 09:50:31 +03:30
MrMalekfar dc79d3a897 Update AngConfigManager.kt 2024-02-29 09:25:06 +03:30
MrMalekfar 486f3ffc96 Update AngConfigManager.kt 2024-02-29 09:23:46 +03:30
2dust bf030e12f5 Merge pull request #2883 from admarty/master
Update vi translation
2024-02-29 08:58:12 +08:00
MrMalekfar e80cce9696 Update AngConfigManager.kt 2024-02-29 02:04:42 +03:30
admarty 5bb9ecce47 Update vi translation 2024-02-28 22:32:26 +07:00
MrMalekfar 5eb09aa54e Update AngConfigManager.kt 2024-02-28 16:31:30 +03:30
MrMalekfar ff261d9939 Update AngConfigManager.kt 2024-02-28 15:22:57 +03:30
MrMalekfar 1624ec87b2 Update AngConfigManager.kt 2024-02-28 15:06:37 +03:30
MrMalekfar f1062f2f45 Update AngConfigManager.kt 2024-02-28 14:51:54 +03:30
2dust 39341c27bc up 1.8.17 2024-02-26 08:54:51 +08:00
2dust 31a90cec2b Merge pull request #2869 from Malus-risus/master
Refactor: Simplify Extensions and Improve Compatibility
2024-02-26 08:11:39 +08:00
Το μοχθηρό ^_^ 617fc63393 Delete renovate.json 2024-02-25 19:59:53 +08:00
Το μοχθηρό ^_^ 802f2cf3eb Update _Ext.kt 2024-02-25 19:05:48 +08:00
Το μοχθηρό ^_^ c7efcde868 Update _Ext.kt 2024-02-25 18:42:39 +08:00
Το μοχθηρό ^_^ e858179204 Update _Ext.kt 2024-02-25 18:31:42 +08:00
Το μοχθηρό ^_^ 6871b0b950 Merge branch '2dust:master' into master 2024-02-25 10:42:48 +08:00
2dust e9a27a1585 Merge pull request #2868 from NagisaEfi/master
Update translation
2024-02-25 09:28:36 +08:00
Το μοχθηρό ^_^ 976b765629 Create renovate.json 2024-02-24 01:09:56 +08:00
NagisaEfi 126b9b6516 Update translation 2024-02-23 23:23:39 +08:00
2dust 94dab02b54 Merge pull request #2856 from Malus-risus/master
Remove unnecessary parentheses
2024-02-20 13:02:35 +08:00
Το μοχθηρό ^_^ a893b87730 Update MainRecyclerAdapter.kt 2024-02-19 14:36:28 +08:00
Το μοχθηρό ^_^ 7db2ddd1f7 Update V2RayServiceManager.kt 2024-02-19 14:34:50 +08:00
Το μοχθηρό ^_^ 748980aa1a Update PerAppProxyActivity.kt 2024-02-19 14:33:12 +08:00
Το μοχθηρό ^_^ 96d416066e Update AppManagerUtil.kt 2024-02-19 14:31:47 +08:00
Το μοχθηρό ^_^ 3955bb16bc Update _Ext.kt 2024-02-19 14:29:35 +08:00
Το μοχθηρό ^_^ de9bbf842f Update Utils.kt 2024-02-19 12:42:56 +08:00
Το μοχθηρό ^_^ 336b673746 Update AngConfigManager.kt 2024-02-19 12:38:24 +08:00
Το μοχθηρό ^_^ f1b6b1e871 Update SettingsActivity.kt 2024-02-19 12:07:13 +08:00
2dust fba4c03bb5 Bug fix 2024-02-17 09:55:26 +08:00
2dust a32ae5b53f Merge pull request #2848 from NotDubious/master
Update Farsi translation
2024-02-17 09:23:11 +08:00
Mahyar 589e0f38fd Update Farsi translation 2024-02-16 11:07:31 +03:30
25 changed files with 383 additions and 205 deletions
+3 -3
View File
@@ -11,8 +11,8 @@ android {
applicationId = "com.v2ray.ang"
minSdk = 21
targetSdk = 34
versionCode = 546
versionName = "1.8.16"
versionCode = 552
versionName = "1.8.19"
multiDexEnabled = true
}
@@ -102,7 +102,7 @@ dependencies {
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
//kotlin
implementation("org.jetbrains.kotlin:kotlin-reflect:1.9.22")
implementation("org.jetbrains.kotlin:kotlin-reflect:1.9.23")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0")
@@ -22,7 +22,9 @@ data class V2rayConfig(
val transport: Any? = null,
val reverse: Any? = null,
var fakedns: Any? = null,
val browserForwarder: Any? = null) {
val browserForwarder: Any? = null,
var observatory: Any? = null,
var burstObservatory: Any? = null) {
companion object {
const val DEFAULT_PORT = 443
const val DEFAULT_SECURITY = "auto"
@@ -135,6 +137,7 @@ data class V2rayConfig(
var tcpSettings: TcpSettingsBean? = null,
var kcpSettings: KcpSettingsBean? = null,
var wsSettings: WsSettingsBean? = null,
var httpupgradeSettings: HttpupgradeSettingsBean? = null,
var httpSettings: HttpSettingsBean? = null,
var tlsSettings: TlsSettingsBean? = null,
var quicSettings: QuicSettingBean? = null,
@@ -184,6 +187,10 @@ data class V2rayConfig(
data class HeadersBean(var Host: String = "")
}
data class HttpupgradeSettingsBean(var path: String = "",
var host: String = "",
val acceptProxyProtocol: Boolean? = null)
data class HttpSettingsBean(var host: List<String> = ArrayList(),
var path: String = "")
@@ -218,10 +225,12 @@ data class V2rayConfig(
}
data class GrpcSettingsBean(var serviceName: String = "",
var authority: String? = null,
var multiMode: Boolean? = null)
fun populateTransportSettings(transport: String, headerType: String?, host: String?, path: String?, seed: String?,
quicSecurity: String?, key: String?, mode: String?, serviceName: String?): String {
quicSecurity: String?, key: String?, mode: String?, serviceName: String?,
authority: String?): String {
var sni = ""
network = transport
when (network) {
@@ -259,6 +268,13 @@ data class V2rayConfig(
wssetting.path = path ?: "/"
wsSettings = wssetting
}
"httpupgrade" -> {
val httpupgradeSetting = HttpupgradeSettingsBean()
httpupgradeSetting.host = host ?: ""
sni = httpupgradeSetting.host
httpupgradeSetting.path = path ?: "/"
httpupgradeSettings = httpupgradeSetting
}
"h2", "http" -> {
network = "h2"
val h2Setting = HttpSettingsBean()
@@ -278,7 +294,8 @@ data class V2rayConfig(
val grpcSetting = GrpcSettingsBean()
grpcSetting.multiMode = mode == "multi"
grpcSetting.serviceName = serviceName ?: ""
sni = host ?: ""
grpcSetting.authority = authority ?: ""
sni = authority ?: ""
grpcSettings = grpcSetting
}
}
@@ -367,7 +384,8 @@ data class V2rayConfig(
fun getTransportSettingDetails(): List<String>? {
if (protocol.equals(EConfigType.VMESS.name, true)
|| protocol.equals(EConfigType.VLESS.name, true)
|| protocol.equals(EConfigType.TROJAN.name, true)) {
|| protocol.equals(EConfigType.TROJAN.name, true)
|| protocol.equals(EConfigType.SHADOWSOCKS.name, true)) {
val transport = streamSettings?.network ?: return null
return when (transport) {
"tcp" -> {
@@ -388,6 +406,12 @@ data class V2rayConfig(
wsSetting.headers.Host,
wsSetting.path)
}
"httpupgrade" -> {
val httpupgradeSetting = streamSettings?.httpupgradeSettings ?: return null
listOf("",
httpupgradeSetting.host,
httpupgradeSetting.path)
}
"h2" -> {
val h2Setting = streamSettings?.httpSettings ?: return null
listOf("",
@@ -403,7 +427,7 @@ data class V2rayConfig(
"grpc" -> {
val grpcSetting = streamSettings?.grpcSettings ?: return null
listOf(if (grpcSetting.multiMode == true) "multi" else "gun",
"",
grpcSetting.authority ?: "",
grpcSetting.serviceName)
}
else -> null
@@ -9,76 +9,61 @@ import org.json.JSONObject
import java.net.URI
import java.net.URLConnection
/**
* Some extensions
*/
val Context.v2RayApplication: AngApplication
get() = applicationContext as AngApplication
fun Context.toast(message: Int): Toast = ToastCompat
.makeText(this, message, Toast.LENGTH_SHORT)
.apply {
show()
}
fun Context.toast(message: CharSequence): Toast = ToastCompat
.makeText(this, message, Toast.LENGTH_SHORT)
.apply {
show()
}
fun JSONObject.putOpt(pair: Pair<String, Any>) = putOpt(pair.first, pair.second)
fun JSONObject.putOpt(pairs: Map<String, Any>) = pairs.forEach { putOpt(it.key to it.value) }
const val threshold = 1000
const val divisor = 1024F
fun Long.toSpeedString() = toTrafficString() + "/s"
fun Long.toTrafficString(): String {
if (this == 0L)
return "\t\t\t0\t B"
if (this < threshold)
return "${this.toFloat().toShortString()}\t B"
val kib = this / divisor
if (kib < threshold)
return "${kib.toShortString()}\t KB"
val mib = kib / divisor
if (mib < threshold)
return "${mib.toShortString()}\t MB"
val gib = mib / divisor
if (gib < threshold)
return "${gib.toShortString()}\t GB"
val tib = gib / divisor
if (tib < threshold)
return "${tib.toShortString()}\t TB"
val pib = tib / divisor
if (pib < threshold)
return "${pib.toShortString()}\t PB"
return "∞"
fun Context.toast(message: Int) {
ToastCompat.makeText(this, message, Toast.LENGTH_SHORT).apply { show() }
}
private fun Float.toShortString(): String {
val s = "%.2f".format(this)
if (s.length <= 4)
return s
return s.substring(0, 4).removeSuffix(".")
fun Context.toast(message: CharSequence) {
ToastCompat.makeText(this, message, Toast.LENGTH_SHORT).apply { show() }
}
fun JSONObject.putOpt(pair: Pair<String, Any?>) {
put(pair.first, pair.second)
}
fun JSONObject.putOpt(pairs: Map<String, Any?>) {
pairs.forEach { put(it.key, it.value) }
}
const val THRESHOLD = 1000L
const val DIVISOR = 1024.0
fun Long.toSpeedString(): String = this.toTrafficString() + "/s"
fun Long.toTrafficString(): String {
if (this < THRESHOLD) {
return "$this B"
}
val kb = this / DIVISOR
if (kb < THRESHOLD) {
return "${String.format("%.1f KB", kb)}"
}
val mb = kb / DIVISOR
if (mb < THRESHOLD) {
return "${String.format("%.1f MB", mb)}"
}
val gb = mb / DIVISOR
if (gb < THRESHOLD) {
return "${String.format("%.1f GB", gb)}"
}
val tb = gb / DIVISOR
if (tb < THRESHOLD) {
return "${String.format("%.1f TB", tb)}"
}
return String.format("%.1f PB", tb / DIVISOR)
}
val URLConnection.responseLength: Long
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) contentLengthLong else contentLength.toLong()
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
contentLengthLong
} else {
contentLength.toLong()
}
val URI.idnHost: String
get() = (host!!).replace("[", "").replace("]", "")
get() = host?.replace("[", "")?.replace("]", "") ?: ""
fun String.removeWhiteSpace(): String {
return this.replace(" ", "")
}
fun String.removeWhiteSpace(): String = replace("\\s+".toRegex(), "")
@@ -368,7 +368,7 @@ object V2RayServiceManager {
}
val directUplink = v2rayPoint.queryStats(TAG_DIRECT, "uplink")
val directDownlink = v2rayPoint.queryStats(TAG_DIRECT, "downlink")
val zeroSpeed = (proxyTotal == 0L && directUplink == 0L && directDownlink == 0L)
val zeroSpeed = proxyTotal == 0L && directUplink == 0L && directDownlink == 0L
if (!zeroSpeed || !lastZeroSpeed) {
if (proxyTotal == 0L) {
appendSpeedString(text, outboundTags?.firstOrNull(), 0.0, 0.0)
@@ -22,6 +22,7 @@ import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.recyclerview.widget.ItemTouchHelper
import android.util.Log
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
@@ -69,7 +70,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
binding.fab.setOnClickListener {
if (mainViewModel.isRunning.value == true) {
Utils.stopVService(this)
} else if (settingsStorage?.decodeString(AppConfig.PREF_MODE) ?: "VPN" == "VPN") {
} else if ((settingsStorage?.decodeString(AppConfig.PREF_MODE) ?: "VPN") == "VPN") {
val intent = VpnService.prepare(this)
if (intent == null) {
startV2Ray()
@@ -117,6 +118,17 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
toast(R.string.toast_permission_denied)
}
}
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
binding.drawerLayout.closeDrawer(GravityCompat.START)
} else {
//super.onBackPressed()
onBackPressedDispatcher.onBackPressed()
}
}
})
}
private fun setupViewModel() {
@@ -656,16 +668,6 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
}
}
@Deprecated("Deprecated in Java")
override fun onBackPressed() {
if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
binding.drawerLayout.closeDrawer(GravityCompat.START)
} else {
//super.onBackPressed()
onBackPressedDispatcher.onBackPressed()
}
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
when (item.itemId) {
@@ -66,7 +66,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
holder.itemMainBinding.tvName.text = config.remarks
holder.itemView.setBackgroundColor(Color.TRANSPARENT)
holder.itemMainBinding.tvTestResult.text = aff?.getTestDelayString() ?: ""
if ((aff?.testDelayMillis ?: 0L) < 0L) {
if (aff?.testDelayMillis ?: 0L < 0L) {
holder.itemMainBinding.tvTestResult.setTextColor(ContextCompat.getColor(mActivity, R.color.colorPingRed))
} else {
holder.itemMainBinding.tvTestResult.setTextColor(ContextCompat.getColor(mActivity, R.color.colorPing))
@@ -50,7 +50,7 @@ class PerAppProxyActivity : BaseActivity() {
.map {
if (blacklist != null) {
it.forEach { one ->
if ((blacklist.contains(one.packageName))) {
if (blacklist.contains(one.packageName)) {
one.isSelected = 1
} else {
one.isSelected = 0
@@ -496,15 +496,16 @@ class ServerActivity : BaseActivity() {
val spiderX = et_spider_x?.text?.toString()?.trim() ?: return
var sni = streamSetting.populateTransportSettings(
transport = networks[network],
headerType = transportTypes(networks[network])[type],
host = requestHost,
path = path,
seed = path,
quicSecurity = requestHost,
key = path,
mode = transportTypes(networks[network])[type],
serviceName = path
transport = networks[network],
headerType = transportTypes(networks[network])[type],
host = requestHost,
path = path,
seed = path,
quicSecurity = requestHost,
key = path,
mode = transportTypes(networks[network])[type],
serviceName = path,
authority = requestHost,
)
if (sniField.isNotBlank()) {
sni = sniField
@@ -91,7 +91,7 @@ class ServerCustomConfigActivity : BaseActivity() {
}
val config = MmkvManager.decodeServerConfig(editGuid) ?: ServerConfig.create(EConfigType.CUSTOM)
config.remarks = binding.etRemarks.text.toString().trim()
config.remarks = v2rayConfig.remarks ?: binding.etRemarks.text.toString().trim()
config.fullConfig = v2rayConfig
MmkvManager.encodeServerConfig(editGuid, config)
@@ -81,10 +81,10 @@ class SettingsActivity : BaseActivity() {
autoUpdateInterval?.setOnPreferenceChangeListener { _, any ->
var nval = any as String
autoUpdateInterval?.summary = nval
// It must be greater than 15 minutes because WorkManager couldn't run tasks under 15 minutes intervals
nval =
if (TextUtils.isEmpty(nval) or (nval.toLong() < 15)) AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL else nval
if (TextUtils.isEmpty(nval) || nval.toLong() < 15) AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL else nval
autoUpdateInterval?.summary = nval
configureUpdateTask(nval.toLong())
true
}
@@ -286,9 +286,9 @@ class SettingsActivity : BaseActivity() {
private fun updateMux(enabled: Boolean) {
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity())
muxConcurrency?.isVisible = enabled
muxXudpConcurrency?.isVisible = enabled
muxXudpQuic?.isVisible = enabled
muxConcurrency?.isEnabled = enabled
muxXudpConcurrency?.isEnabled = enabled
muxXudpQuic?.isEnabled = enabled
if (enabled) {
updateMuxConcurrency(defaultSharedPreferences.getString(AppConfig.PREF_MUX_CONCURRENCY, "8"))
updateMuxXudpConcurrency(defaultSharedPreferences.getString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8"))
@@ -315,9 +315,9 @@ class SettingsActivity : BaseActivity() {
private fun updateFragment(enabled: Boolean) {
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity())
fragmentPackets?.isVisible = enabled
fragmentLength?.isVisible = enabled
fragmentInterval?.isVisible = enabled
fragmentPackets?.isEnabled = enabled
fragmentLength?.isEnabled = enabled
fragmentInterval?.isEnabled = enabled
if (enabled) {
updateFragmentPackets(defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_PACKETS, "tlshello"))
updateFragmentLength(defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_LENGTH, "50-100"))
@@ -8,6 +8,11 @@ import android.util.Log
import androidx.preference.PreferenceManager
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import com.google.gson.annotations.SerializedName
import com.google.gson.reflect.TypeToken
import com.tencent.mmkv.MMKV
import com.v2ray.ang.AppConfig
import com.v2ray.ang.AppConfig.ANG_CONFIG
@@ -22,6 +27,7 @@ import com.v2ray.ang.dto.V2rayConfig.Companion.TLS
import com.v2ray.ang.util.MmkvManager.KEY_SELECTED_SERVER
import java.net.URI
import java.util.*
import java.lang.reflect.Type
import com.v2ray.ang.extension.idnHost
import com.v2ray.ang.extension.removeWhiteSpace
@@ -170,7 +176,8 @@ object AngConfigManager {
vmessBean.requestHost,
vmessBean.path,
vmessBean.headerType,
vmessBean.path
vmessBean.path,
vmessBean.requestHost,
)
val allowInsecure = if (vmessBean.allowInsecure.isBlank()) {
settingsStorage?.decodeBool(AppConfig.PREF_ALLOW_INSECURE) ?: false
@@ -269,7 +276,8 @@ object AngConfigManager {
vmessQRCode.host,
vmessQRCode.path,
vmessQRCode.type,
vmessQRCode.path
vmessQRCode.path,
vmessQRCode.host
)
val fingerprint = vmessQRCode.fp ?: streamSetting.tlsSettings?.fingerprint
@@ -377,7 +385,8 @@ object AngConfigManager {
queryParam["quicSecurity"],
queryParam["key"],
queryParam["mode"],
queryParam["serviceName"]
queryParam["serviceName"],
queryParam["authority"]
)
fingerprint = queryParam["fp"] ?: ""
config.outboundBean?.streamSettings?.populateTlsSettings(
@@ -405,7 +414,6 @@ object AngConfigManager {
.associate { it.split("=").let { (k, v) -> k to Utils.urlDecode(v) } }
config = ServerConfig.create(EConfigType.VLESS)
val streamSetting = config.outboundBean?.streamSettings ?: return -1
var fingerprint = streamSetting.tlsSettings?.fingerprint
config.remarks = Utils.urlDecode(uri.fragment ?: "")
config.outboundBean?.settings?.vnext?.get(0)?.let { vnext ->
@@ -425,15 +433,18 @@ object AngConfigManager {
queryParam["quicSecurity"],
queryParam["key"],
queryParam["mode"],
queryParam["serviceName"]
queryParam["serviceName"],
queryParam["authority"]
)
fingerprint = queryParam["fp"] ?: ""
val pbk = queryParam["pbk"] ?: ""
val sid = queryParam["sid"] ?: ""
val spx = Utils.urlDecode(queryParam["spx"] ?: "")
streamSetting.populateTlsSettings(
queryParam["security"] ?: "", allowInsecure,
queryParam["sni"] ?: sni, fingerprint, queryParam["alpn"], pbk, sid, spx
queryParam["security"] ?: "",
allowInsecure,
queryParam["sni"] ?: sni,
queryParam["fp"] ?: "",
queryParam["alpn"],
queryParam["pbk"] ?: "",
queryParam["sid"] ?: "",
queryParam["spx"] ?: ""
)
} else if (str.startsWith(EConfigType.WIREGUARD.protocolScheme)) {
val uri = URI(Utils.fixIllegalUrl(str))
@@ -514,7 +525,8 @@ object AngConfigManager {
queryParam["security"],
queryParam["key"],
queryParam["mode"],
queryParam["serviceName"])
queryParam["serviceName"],
queryParam["authority"])
streamSetting.populateTlsSettings(
if (tls) TLS else "", allowInsecure, sni, fingerprint, null,
null, null, null
@@ -577,6 +589,42 @@ object AngConfigManager {
password = base64Decode.substringAfter(":")
}
val query = Utils.urlDecode(uri.query ?: "")
if (query != "") {
val queryPairs = HashMap<String, String>()
val pairs = query.split(";")
Log.d(AppConfig.ANG_PACKAGE, pairs.toString())
for (pair in pairs) {
val idx = pair.indexOf("=")
if (idx == -1) {
queryPairs[Utils.urlDecode(pair)] = "";
} else {
queryPairs[Utils.urlDecode(pair.substring(0, idx))] = Utils.urlDecode(pair.substring(idx + 1))
}
}
Log.d(AppConfig.ANG_PACKAGE, queryPairs.toString())
var sni: String? = ""
if (queryPairs["plugin"] == "obfs-local" && queryPairs["obfs"] == "http") {
sni = config.outboundBean?.streamSettings?.populateTransportSettings(
"tcp", "http", queryPairs["obfs-host"], queryPairs["path"], null, null, null, null, null, null
)
} else if (queryPairs["plugin"] == "v2ray-plugin") {
var network = "ws";
if (queryPairs["mode"] == "quic") {
network = "quic";
}
sni = config.outboundBean?.streamSettings?.populateTransportSettings(
network, null, queryPairs["host"], queryPairs["path"], null, null, null, null, null, null
)
}
if ("tls" in queryPairs) {
config.outboundBean?.streamSettings?.populateTlsSettings(
"tls", false, sni ?: "", null, null, null, null, null
)
}
}
config.outboundBean?.settings?.servers?.get(0)?.let { server ->
server.address = uri.idnHost
server.port = uri.port
@@ -725,7 +773,7 @@ object AngConfigManager {
}
}
"ws" -> {
"ws", "httpupgrade" -> {
if (!TextUtils.isEmpty(transportDetails[1])) {
dicQuery["host"] = Utils.urlEncode(transportDetails[1])
}
@@ -752,7 +800,8 @@ object AngConfigManager {
"grpc" -> {
dicQuery["mode"] = transportDetails[0]
dicQuery["serviceName"] = transportDetails[2]
dicQuery["authority"] = Utils.urlEncode(transportDetails[1])
dicQuery["serviceName"] = Utils.urlEncode(transportDetails[2])
}
}
}
@@ -987,23 +1036,30 @@ object AngConfigManager {
&& server.contains("routing")
) {
try {
val gson = GsonBuilder().setPrettyPrinting().create()
//val gson = GsonBuilder().setPrettyPrinting().create()
val gson = GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.registerTypeAdapter( // custom serialiser is needed here since JSON by default parse number as Double, core will fail to start
object : TypeToken<Double>() {}.type,
JsonSerializer { src: Double?, _: Type?, _: JsonSerializationContext? -> JsonPrimitive(src?.toInt()) }
)
.create()
val serverList: Array<V2rayConfig> =
Gson().fromJson(server, Array<V2rayConfig>::class.java)
Gson().fromJson(server, Array<V2rayConfig>::class.java)
if (serverList.isNotEmpty()) {
var count = 0
for (srv in serverList) {
if (srv.inbounds != null && srv.outbounds != null && srv.routing != null) {
val config = ServerConfig.create(EConfigType.CUSTOM)
config.remarks = srv.remarks
?: ("%04d-".format(count + 1) + System.currentTimeMillis()
.toString())
config.subscriptionId = subid
config.fullConfig = srv
val key = MmkvManager.encodeServerConfig("", config)
serverRawStorage?.encode(key, gson.toJson(srv))
count += 1
}
val config = ServerConfig.create(EConfigType.CUSTOM)
config.remarks = srv.remarks
?: ("%04d-".format(count + 1) + System.currentTimeMillis()
.toString())
config.subscriptionId = subid
config.fullConfig = srv
val key = MmkvManager.encodeServerConfig("", config)
serverRawStorage?.encode(key, gson.toJson(srv))
count += 1
}
return count
}
@@ -1015,8 +1071,7 @@ object AngConfigManager {
val config = ServerConfig.create(EConfigType.CUSTOM)
config.subscriptionId = subid
config.fullConfig = Gson().fromJson(server, V2rayConfig::class.java)
config.remarks = System.currentTimeMillis().toString()
// config.remarks = config.fullConfig?.remarks ?: System.currentTimeMillis().toString()
config.remarks = config.fullConfig?.remarks ?: System.currentTimeMillis().toString()
val key = MmkvManager.encodeServerConfig("", config)
serverRawStorage?.encode(key, server)
return 1
@@ -22,7 +22,7 @@ object AppManagerUtil {
val appName = applicationInfo.loadLabel(packageManager).toString()
val appIcon = applicationInfo.loadIcon(packageManager)
val isSystemApp = (applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM) > 0
val isSystemApp = applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM > 0
val appInfo = AppInfo(appName, pkg.packageName, appIcon, isSystemApp, 0)
apps.add(appInfo)
@@ -210,7 +210,7 @@ object Utils {
}
fun isPureIpAddress(value: String): Boolean {
return (isIpv4Address(value) || isIpv6Address(value))
return isIpv4Address(value) || isIpv6Address(value)
}
fun isIpv4Address(value: String): Boolean {
@@ -49,7 +49,7 @@ object V2rayConfigUtil {
return Result(true, customConfig)
}
val outbound = config.getProxyOutbound() ?: return Result(false, "")
val result = getV2rayNonCustomConfig(context, outbound)
val result = getV2rayNonCustomConfig(context, outbound, config.remarks)
//Log.d(ANG_PACKAGE, result.content)
return result
} catch (e: Exception) {
@@ -63,7 +63,8 @@ object V2rayConfigUtil {
*/
private fun getV2rayNonCustomConfig(
context: Context,
outbound: V2rayConfig.OutboundBean
outbound: V2rayConfig.OutboundBean,
remarks: String,
): Result {
val result = Result(false, "")
//取得默认配置
@@ -98,6 +99,9 @@ object V2rayConfigUtil {
v2rayConfig.stats = null
v2rayConfig.policy = null
}
v2rayConfig.remarks = remarks
result.status = true
result.content = v2rayConfig.toPrettyPrinting()
return result
@@ -581,10 +585,21 @@ object V2rayConfigUtil {
tag = TAG_FRAGMENT,
mux = null
)
var packets = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_PACKETS) ?: "tlshello"
if (v2rayConfig.outbounds[0].streamSettings?.security == V2rayConfig.REALITY
&& packets == "tlshello"
) {
packets = "1-3"
} else if (v2rayConfig.outbounds[0].streamSettings?.security == V2rayConfig.TLS
&& packets != "tlshello"
) {
packets = "tlshello"
}
fragmentOutbound.settings = V2rayConfig.OutboundBean.OutSettingsBean(
fragment = V2rayConfig.OutboundBean.OutSettingsBean.FragmentBean(
packets = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_PACKETS)
?: "tlshello",
packets = packets,
length = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_LENGTH)
?: "50-100",
interval = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_INTERVAL)
@@ -97,9 +97,9 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
fun appendCustomConfigServer(server: String) {
val config = ServerConfig.create(EConfigType.CUSTOM)
config.remarks = System.currentTimeMillis().toString()
config.subscriptionId = subscriptionId
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)
serverList.add(0, key)
@@ -117,7 +117,95 @@
android:entries="@array/ss_securitys" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_lab_more_function"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_lab_network" />
<Spinner
android:id="@+id/sp_network"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height"
android:entries="@array/networks" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:id="@+id/sp_header_type_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_lab_head_type" />
<Spinner
android:id="@+id/sp_header_type"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_lab_request_host" />
<EditText
android:id="@+id/et_request_host"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height"
android:inputType="text" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_lab_path" />
<EditText
android:id="@+id/et_path"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height"
android:inputType="text" />
</LinearLayout>
<include layout="@layout/tls_layout" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -126,4 +214,4 @@
android:orientation="vertical" />
</LinearLayout>
</ScrollView>
</ScrollView>
@@ -44,7 +44,7 @@
<string name="server_lab_more_function">النقل</string>
<string name="server_lab_head_type">نوع الرأس</string>
<string name="server_lab_mode_type">وضع gRPC</string>
<string name="server_lab_request_host">طلب الاستضافة (host/ws host/h2 host)/QUIC security</string>
<string name="server_lab_request_host">طلب الاستضافة (host/ws host/h2 host)/QUIC security/gRPC Authority</string>
<string name="server_lab_path">المسار (ws path/h2 path)/QUIC key/kcp seed/gRPC serviceName</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_allow_insecure">allowInsecure</string>
+10 -6
View File
@@ -46,7 +46,7 @@
<string name="server_lab_more_function">انتقال</string>
<string name="server_lab_head_type">نوع head</string>
<string name="server_lab_mode_type">حالت gRPC</string>
<string name="server_lab_request_host">میزبان درخواست (host/host ws/host h2)/امنیت QUIC</string>
<string name="server_lab_request_host">gRPC Authority/میزبان درخواست (host/host ws/host h2)/امنیت QUIC</string>
<string name="server_lab_path">مسیر (مسیر ws/ مسیر h2) کلید QUIC/دانه kcp/نام‌خدمات gRPC</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_allow_insecure">مجوز ناامن</string>
@@ -69,7 +69,7 @@
<string name="toast_decoding_failed">رمزگشایی انجام نشد</string>
<string name="title_file_chooser">انتخاب فایل کانفیگ</string>
<string name="toast_require_file_manager">لطفا یک برنامه مدیریت فایل نصب کنید.</string>
<string name="server_customize_config">سفارشی‌سازی کانفیگ</string>
<string name="server_customize_config">کانفیگ سفارشی</string>
<string name="toast_config_file_invalid">کانفیگ معتبر نیست</string>
<string name="server_lab_content">محتوا</string>
<string name="toast_none_data_clipboard">هیچ داده‌ای در کلیپ‌بورد وجود ندارد</string>
@@ -95,7 +95,6 @@
<string name="menu_item_export_proxy_app">خروجی گرفتن در کلیپ‌بورد</string>
<string name="menu_item_import_proxy_app">وارد کردن از کلیپ‌بورد</string>
<!-- Preferences -->
<string name="title_settings">تنظیمات</string>
<string name="title_advanced">تنظیمات پیشرفته</string>
@@ -103,6 +102,7 @@
<string name="title_pref_per_app_proxy">پروکسی به تفکیک برنامه</string>
<string name="summary_pref_per_app_proxy">عمومی: برنامه بررسی شده پروکسی است، اتصال مستقیم بدون بررسی است. \nحالت bypass: برنامه بررسی شده مستقیما متصل است، پراکسی بررسی نشده است. \nگزینه‌ای برای انتخاب خودکار پروکسی برنامه در منو است</string>
<string name="title_mux_settings">تنظیمات Mux</string>
<string name="title_pref_mux_enabled">فعال کردن Mux</string>
<string name="summary_pref_mux_enabled">سریعتر است، اما ممکن است باعث اتصال ناپایدار شود\nمخزن ترافیک TCP با 8 اتصال پیش‌فرض، نحوه مدیریت UDP و QUIC را در زیر سفارشی کنید</string>
<string name="title_pref_mux_concurency">اتصالات TCP (محدوده -1 تا 1024)</string>
@@ -111,7 +111,7 @@
<string-array name="mux_xudp_quic_entries">
<item>رد کردن</item>
<item>مجاز</item>
<item>جست و خیز کردن</item>
<item>پریدن</item>
</string-array>
<string name="title_pref_speed_enabled">فعال کردن نمایش سرعت</string>
@@ -226,7 +226,11 @@
<string name="import_subscription_success">اشتراک با موفقیت ذخیره شد</string>
<string name="import_subscription_failure">ذخیره اشتراک ناموفق بود</string>
<string name="title_fragment_settings">تنظیمات Fragment</string>
<string name="title_pref_fragment_packets">Fragment Packets</string>
<string name="title_pref_fragment_length">Fragment Length (min-max)</string>
<string name="title_pref_fragment_interval">Fragment Interval (min-max)</string>
<string name="title_pref_fragment_enabled">فعال کردن Fragment</string>
<string-array name="share_method">
<item>QRcode</item>
<item>خروجی گرفتن در کلیپ‌بورد</item>
@@ -247,7 +251,7 @@
<string-array name="routing_mode">
<item>پروکسی سراسری</item>
<item>دور زدن آدرس LAN و سپس پروکسی</item>
<item>دور زذن آدرس mainland و سپس پروکسی</item>
<item>دور زدن آدرس mainland و سپس پروکسی</item>
<item>دور زدن LAN و آدرس mainland و سپس پروکسی</item>
<item>مستقیم سراسری</item>
</string-array>
+11 -11
View File
@@ -30,7 +30,7 @@
<string name="menu_item_import_config_manually_socks">Ручной ввод Socks</string>
<string name="menu_item_import_config_manually_trojan">Ручной ввод Trojan</string>
<string name="menu_item_import_config_manually_wireguard">Ручной ввод Wireguard</string>
<string name="menu_item_import_config_custom">Пользовательский профиль</string>
<string name="menu_item_import_config_custom">Другой профиль</string>
<string name="menu_item_import_config_custom_clipboard">Импорт из буфера обмена</string>
<string name="menu_item_import_config_custom_local">Импорт из файла</string>
<string name="menu_item_import_config_custom_url">Импорт из URL</string>
@@ -46,7 +46,7 @@
<string name="server_lab_more_function">Другие параметры</string>
<string name="server_lab_head_type">Тип заголовка</string>
<string name="server_lab_mode_type">Режим gRPC</string>
<string name="server_lab_request_host">Запрос узла (WS/H2) / Шифрование QUIC</string>
<string name="server_lab_request_host">Запрос узла (WS/H2) / Шифрование QUIC/gRPC Authority</string>
<string name="server_lab_path">Путь (WS/H2) / Ключ QUIC / Сид KCP / Сервис gRPC</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_allow_insecure">Разрешать небезопасные</string>
@@ -146,7 +146,7 @@
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_proxy_sharing_enabled">Разрешать подключения из LAN</string>
<string name="summary_pref_proxy_sharing_enabled">Другие устройства могут подключаться к прокси по вашему IP-адресу через протокол SOCKS/HTTP. Используйте только в надёжной сети, чтобы избежать несанкционированного подключения.</string>
<string name="summary_pref_proxy_sharing_enabled">Другие устройства могут подключаться, используя ваш IP-адрес, чтобы использовать прокси по протоколам SOCKS/HTTP. Используйте только в доверенной сети, чтобы избежать несанкционированного подключения.</string>
<string name="toast_warning_pref_proxysharing_short">Доступ из LAN разрешён, убедитесь, что вы находитесь в надёжной сети</string>
<string name="title_pref_allow_insecure">Разрешать небезопасные</string>
@@ -178,7 +178,7 @@
<string name="title_pref_auto_update_subscription">Автоматическое обновление подписок</string>
<string name="summary_pref_auto_update_subscription">Автоматическое обновление подписок в фоновом режиме с указанным интервалом. В зависимости от устройства эта функция может работать не всегда.</string>
<string name="title_pref_auto_update_interval">Интервал автообновления (мин., не менее 15)</string>
<string name="title_pref_auto_update_interval">Интервал автообновления (минут, не менее 15)</string>
<string name="title_core_loglevel">Подробность ведения журнала</string>
<string name="title_mode">Режим</string>
@@ -186,7 +186,7 @@
<string name="title_language">Язык</string>
<string name="title_ui_settings">Настройки интерфейса</string>
<string name="title_logcat">Системный журнал</string>
<string name="title_logcat">Журнал</string>
<string name="logcat_copy">Копировать</string>
<string name="logcat_clear">Очистить</string>
<string name="title_service_restart">Перезапуск службы</string>
@@ -195,7 +195,7 @@
<string name="title_del_invalid_config">Удалить нерабочие профили (после проверки)</string>
<string name="title_export_all">Экспорт всех профилей в буфер обмена</string>
<string name="title_sub_setting">Группы</string>
<string name="sub_setting_remarks">примечания</string>
<string name="sub_setting_remarks">Название</string>
<string name="sub_setting_url">URL (необязательно)</string>
<string name="sub_setting_enable">Использовать обновление</string>
<string name="sub_auto_update">Использовать автоматическое обновление</string>
@@ -204,7 +204,7 @@
<string name="title_real_ping_all_server">Время отклика профилей</string>
<string name="title_user_asset_setting">Файлы георесурсов</string>
<string name="title_sort_by_test_results">Сортировка по результатам теста</string>
<string name="title_filter_config">Фильтр профилей</string>
<string name="title_filter_config">Фильтр групп</string>
<string name="filter_config_all">Все группы</string>
<string name="title_del_duplicate_config_count">Удалено дубликатов профилей: %d</string>
@@ -221,7 +221,7 @@
<string name="connection_test_pending">Проверить подключение</string>
<string name="connection_test_testing">Проверка…</string>
<string name="connection_test_available">Успешно: рукопожатие HTTP заняло %d мс</string>
<string name="connection_test_available">Успешно: HTTP-соединение заняло %d мс</string>
<string name="connection_test_error">Сбой проверки интернет-соединения: %s</string>
<string name="connection_test_fail">Интернет недоступен</string>
<string name="connection_test_error_status_code">Код ошибки: #%d</string>
@@ -232,14 +232,14 @@
<string name="import_subscription_failure">Невозможно импортировать подписку</string>
<string name="title_fragment_settings">Настройки фрагментирования</string>
<string name="title_pref_fragment_packets">Фрагментирование пакетов</string>
<string name="title_pref_fragment_length">Длина фрагмента (от … до)</string>
<string name="title_pref_fragment_interval">Интервал фрагментов (от … до)</string>
<string name="title_pref_fragment_length">Длина фрагмента (от - до)</string>
<string name="title_pref_fragment_interval">Интервал фрагментов (от - до)</string>
<string name="title_pref_fragment_enabled">Использовать фрагментирование</string>
<string-array name="share_method">
<item>QR-код</item>
<item>Экспорт в буфер обмена</item>
<item>Экспорт всего профиля в буфер обмена</item>
<item>Экспорт всей конфигурации в буфер обмена</item>
</string-array>
<string-array name="share_sub_method">
@@ -46,7 +46,7 @@
<string name="server_lab_more_function">Nâng cao</string>
<string name="server_lab_head_type">Kiểu ngụy trang (type)</string>
<string name="server_lab_mode_type">Chế độ gRPC</string>
<string name="server_lab_request_host">Yêu cầu host(host/ws host/h2 host)/QUIC security</string>
<string name="server_lab_request_host">Yêu cầu host(host/ws host/h2 host)/QUIC security/gRPC Authority</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC key/kcp seed/gRPC serviceName</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_allow_insecure">allowInsecure</string>
@@ -103,7 +103,7 @@
<string name="title_pref_per_app_proxy">Proxy Theo Ứng Dụng</string>
<string name="summary_pref_per_app_proxy">- Bình thường: Ứng dụng đã chọn sẽ kết nối thông qua Proxy, chưa chọn sẽ kết nối trực tiếp. \n- Chế độ Bypass: Ứng dụng đã chọn sẽ kết nối trực tiếp, chưa chọn sẽ kết nối qua Proxy. \n- Nếu bạn đang ở Trung Quốc thì vào Menu, chọn Tự động chọn ứng dụng Proxy.</string>
<string name="title_mux_settings">Mux Settings</string>
<string name="title_mux_settings">Cài đặt Mux</string>
<string name="title_pref_mux_enabled">Bật Mux</string>
<string name="summary_pref_mux_enabled">Giảm độ trễ trong bước bắt tay của kết nối TCP. Mux phân phối dữ liệu từ nhiều kết nối TCP trên một kết nối TCP duy nhất. Không nên sử dụng Mux để xem video, download file hoặc chạy speedtest vì thường không hiệu quả.</string>
<string name="title_pref_mux_concurency">TCP connections (từ 1 đến 1024)</string>
@@ -164,7 +164,7 @@
<string name="summary_pref_confirm_remove">Yêu cầu xác nhận từ người dùng khi thực hiện xóa tệp cấu hình.</string>
<string name="title_pref_start_scan_immediate">Quét mã QR ngay lập tức</string>
<string name="summary_pref_start_scan_immediate">Mở camera để quét QR ngay khi khởi động, nếu không bạn có thể chọn quét mã hoặc chọn ảnh trên thanh công cụ.</string>
<string name="summary_pref_start_scan_immediate">Mở camera để quét mã QR ngay khi khởi động, nếu không, bạn cũng có thể chọn quét mã hoặc chọn ảnh từ thanh công cụ.</string>
<string name="title_pref_feedback">Phản hồi lỗi</string>
<string name="summary_pref_feedback">Phản hồi cải tiến hoặc lỗi lên GitHub</string>
@@ -220,7 +220,7 @@
<string name="connection_test_pending">Kiểm tra kết nối</string>
<string name="connection_test_testing">Đang kiểm tra kết nối mạng...</string>
<string name="connection_test_available">Test thành công: truy cập www.Google.com mất %d ms</string>
<string name="connection_test_available">Test thành công: Mất %d ms để truy cập Google.com</string>
<string name="connection_test_error">Lỗi kết nối mạng, hãy thử đổi cấu hình hoặc kiểm tra lại! Mã lỗi: %s</string>
<string name="connection_test_fail">Không có kết nối mạng!</string>
<string name="connection_test_error_status_code">Mã lỗi: #%d</string>
@@ -238,7 +238,7 @@
<string-array name="share_sub_method">
<item>Xuất gói ra mã QR (Chụp màn hình để lưu)</item>
<item>Xuất gói đăng ký vào bảng nhớ tạm</item>
<item>Xuất gói vào bảng nhớ tạm</item>
</string-array>
<string-array name="routing_tag">
@@ -46,8 +46,8 @@
<string name="server_lab_more_function">底层传输方式(transport)</string>
<string name="server_lab_head_type">伪装类型(type)</string>
<string name="server_lab_mode_type">gRPC 传输模式(mode)</string>
<string name="server_lab_request_host">伪装域名(host)(host/ws host/h2 host)/QUIC 加密方式</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC 加密密钥/kcp seed/gRPC serviceName</string>
<string name="server_lab_request_host">伪装域名(host)(host/ws host/httpupgrade host/h2 host)/QUIC 加密方式/gRPC Authority</string>
<string name="server_lab_path">path(ws path/httpupgrade path/h2 path)/QUIC 加密密钥/kcp seed/gRPC serviceName</string>
<string name="server_lab_stream_security">传输层安全(TLS)</string>
<string name="server_lab_allow_insecure">跳过证书验证(allowInsecure)</string>
<string name="server_lab_sni">SNI</string>
@@ -230,11 +230,11 @@
<string name="import_subscription_failure">导入订阅失败</string>
<string name="menu_item_add_asset">添加</string>
<string name="menu_item_add_url">添加链接</string>
<string name="title_fragment_settings">分片(fragment) 设置</string>
<string name="title_fragment_settings">分片(Fragment) 设置</string>
<string name="title_pref_fragment_packets">分片方式</string>
<string name="title_pref_fragment_length">分片包长(最小-最大)</string>
<string name="title_pref_fragment_interval">分片间隔(最小-最大)</string>
<string name="title_pref_fragment_enabled">启用分片(fragment)</string>
<string name="title_pref_fragment_enabled">启用分片(Fragment)</string>
<string-array name="share_method">
<item>二维码</item>
@@ -18,23 +18,23 @@
<string name="toast_services_failure">啟動服務失敗</string>
<!--ServerActivity-->
<string name="title_server">組態檔案</string>
<string name="menu_item_add_config">新增組態</string>
<string name="menu_item_save_config">儲存組態</string>
<string name="menu_item_del_config">刪除組態</string>
<string name="menu_item_import_config_qrcode">從 QR Code 匯入組態</string>
<string name="menu_item_import_config_clipboard">從剪貼簿匯入組態</string>
<string name="title_server">配置檔案</string>
<string name="menu_item_add_config">新增配置</string>
<string name="menu_item_save_config">儲存配置</string>
<string name="menu_item_del_config">刪除配置</string>
<string name="menu_item_import_config_qrcode">從 QR Code 匯入配置</string>
<string name="menu_item_import_config_clipboard">從剪貼簿匯入配置</string>
<string name="menu_item_import_config_manually_vmess">手動鍵入 [Vmess]</string>
<string name="menu_item_import_config_manually_vless">手動鍵入 [VLESS]</string>
<string name="menu_item_import_config_manually_ss">手動鍵入 [Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">手動鍵入 [Socks]</string>
<string name="menu_item_import_config_manually_trojan">手動鍵入 [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">手動鍵入 [Wireguard]</string>
<string name="menu_item_import_config_custom">自訂組態</string>
<string name="menu_item_import_config_custom_clipboard">從剪貼簿匯入自訂組態</string>
<string name="menu_item_import_config_custom_local">從本地匯入自訂組態</string>
<string name="menu_item_import_config_custom_url">從 URL 匯入自訂組態</string>
<string name="menu_item_import_config_custom_url_scan">掃描 URL 匯入自訂組態</string>
<string name="menu_item_import_config_custom">自訂配置</string>
<string name="menu_item_import_config_custom_clipboard">從剪貼簿匯入自訂配置</string>
<string name="menu_item_import_config_custom_local">從本地匯入自訂配置</string>
<string name="menu_item_import_config_custom_url">從 URL 匯入自訂配置</string>
<string name="menu_item_import_config_custom_url_scan">掃描 URL 匯入自訂配置</string>
<string name="del_config_comfirm">確定刪除?</string>
<string name="server_lab_remarks">備註</string>
<string name="server_lab_address">位址</string>
@@ -46,8 +46,8 @@
<string name="server_lab_more_function">底層傳輸方式 (transport)</string>
<string name="server_lab_head_type">標頭類型</string>
<string name="server_lab_mode_type">gRPC 傳輸模式 (mode)</string>
<string name="server_lab_request_host">要求主機 (host)(host/ws host/h2 host)/QUIC 加密方式</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC 加密金鑰/kcp seed/gRPC serviceName</string>
<string name="server_lab_request_host">要求主機 (host)(host/ws host/httpupgrade host/h2 host)/QUIC 加密方式/gRPC Authority</string>
<string name="server_lab_path">path(ws path/httpupgrade path/h2 path)/QUIC 加密金鑰/kcp seed/gRPC serviceName</string>
<string name="server_lab_stream_security">傳輸層安全 (TLS)</string>
<string name="server_lab_allow_insecure">跳過憑證驗證 (allowInsecure)</string>
<string name="server_lab_sni">SNI</string>
@@ -61,21 +61,21 @@
<string name="server_lab_flow">流程 (flow)</string>
<string name="server_lab_reserved">Reserved (可選)</string>
<string name="server_lab_local_address">本機位址(可選IPv4/IPv6,逗號隔開)</string>
<string name="server_lab_local_mtu">Mtu(可選, 預設1420)</string>
<string name="server_lab_local_mtu">MTU(可選, 預設1420)</string>
<string name="toast_success">成功</string>
<string name="toast_failure">失敗</string>
<string name="toast_none_data">無資料</string>
<string name="toast_incorrect_protocol">通訊協定不正確</string>
<string name="toast_decoding_failed">解碼失敗</string>
<string name="title_file_chooser">選取一個組態檔</string>
<string name="title_file_chooser">選取一個配置檔</string>
<string name="toast_require_file_manager">請安裝檔案總管。</string>
<string name="server_customize_config">自訂組態</string>
<string name="toast_config_file_invalid">無效組態</string>
<string name="server_customize_config">自訂配置</string>
<string name="toast_config_file_invalid">無效配置</string>
<string name="server_lab_content">內容</string>
<string name="toast_none_data_clipboard">剪貼簿內無資料</string>
<string name="toast_invalid_url">URL 無效</string>
<string name="server_lab_need_inbound">​​確保 inbounds port 和設定中的一致</string>
<string name="toast_malformed_josn">組態格式不正確</string>
<string name="toast_malformed_josn">配置格式不正確</string>
<string name="server_lab_request_host6">Host(SNI)(可選)</string>
<string name="toast_asset_copy_failed">失敗,請使用檔案總管</string>
<string name="menu_item_add_file">新增檔案</string>
@@ -159,8 +159,8 @@
<string name="title_pref_local_dns_port">本機 DNS 埠</string>
<string name="summary_pref_local_dns_port">本機 DNS 埠</string>
<string name="title_pref_confirm_remove">刪除配置文件確認</string>
<string name="summary_pref_confirm_remove">刪除配置文件是否需要用戶二次確認</string>
<string name="title_pref_confirm_remove">刪除配置檔案確認</string>
<string name="summary_pref_confirm_remove">刪除配置檔案是否需要用戶二次確認</string>
<string name="title_pref_start_scan_immediate">立即啟動掃碼</string>
<string name="summary_pref_start_scan_immediate">啟動時立即打開相機掃描,否則可在工具欄選擇掃碼或選照片</string>
@@ -182,27 +182,27 @@
<string name="title_mode">模式</string>
<string name="title_mode_help">輕觸以檢視說明</string>
<string name="title_language">語言</string>
<string name="title_ui_settings">用戶界面設置</string>
<string name="title_ui_settings">使用者介面設定</string>
<string name="title_logcat">Logcat</string>
<string name="logcat_copy">複製</string>
<string name="logcat_clear">清除</string>
<string name="title_service_restart">服務重啟</string>
<string name="title_del_all_config">刪除全部組態</string>
<string name="title_del_duplicate_config">刪除重複組態</string>
<string name="title_del_invalid_config">刪除無效組態 (先偵測)</string>
<string name="title_export_all">匯出全部 (非自訂) 組態至剪貼簿</string>
<string name="title_service_restart">重啟服務</string>
<string name="title_del_all_config">刪除全部配置</string>
<string name="title_del_duplicate_config">刪除重複配置</string>
<string name="title_del_invalid_config">刪除無效配置 (先偵測)</string>
<string name="title_export_all">匯出全部 (非自訂) 配置至剪貼簿</string>
<string name="title_sub_setting">訂閱分組設定</string>
<string name="sub_setting_remarks">備註</string>
<string name="sub_setting_url">Optional URL</string>
<string name="sub_setting_enable">啟用更新</string>
<string name="sub_auto_update">啟用自動更新</string>
<string name="title_sub_update">更新訂閱</string>
<string name="title_ping_all_server">偵測所有組態 Tcping</string>
<string name="title_real_ping_all_server">偵測所有組態真延遲</string>
<string name="title_ping_all_server">偵測所有配置 Tcping</string>
<string name="title_real_ping_all_server">偵測所有配置真延遲</string>
<string name="title_user_asset_setting">Geo 資源檔案</string>
<string name="title_sort_by_test_results">依偵測結果排序</string>
<string name="title_filter_config">過濾組態</string>
<string name="title_filter_config">過濾配置</string>
<string name="filter_config_all">所有訂閱分組</string>
<string name="title_del_duplicate_config_count">Delete %d duplicate configurations</string>
@@ -226,20 +226,20 @@
<string name="connection_connected">"已連線,輕觸以檢查連線能力"</string>
<string name="connection_not_connected">"未連線"</string>
<string name="import_subscription_success">訂閱導入成功</string>
<string name="import_subscription_failure">導入訂閱失敗</string>
<string name="import_subscription_success">匯入訂閱成功</string>
<string name="import_subscription_failure">匯入訂閱失敗</string>
<string name="menu_item_add_asset">添加</string>
<string name="menu_item_add_url">添加連結</string>
<string name="title_fragment_settings">分片(fragment) 設定</string>
<string name="title_fragment_settings">分片(Fragment) 設定</string>
<string name="title_pref_fragment_packets">分片方式</string>
<string name="title_pref_fragment_length">分片包长(最小-最大)</string>
<string name="title_pref_fragment_interval">分片间隔(最小-最大)</string>
<string name="title_pref_fragment_enabled">启用分片(fragment)</string>
<string name="title_pref_fragment_length">分片包長(最小-最大)</string>
<string name="title_pref_fragment_interval">分片間隔(最小-最大)</string>
<string name="title_pref_fragment_enabled">啟用分片(Fragment)</string>
<string-array name="share_method">
<item>QR Code</item>
<item>匯出至剪貼簿</item>
<item>匯出完整組態至剪貼簿</item>
<item>匯出完整配置至剪貼簿</item>
</string-array>
<string-array name="share_sub_method">
@@ -25,6 +25,7 @@
<item>tcp</item>
<item>kcp</item>
<item>ws</item>
<item>httpupgrade</item>
<item>h2</item>
<item>quic</item>
<item>grpc</item>
@@ -62,6 +63,9 @@
<string-array name="fragment_packets" translatable="false">
<item>tlshello</item>
<item>1-2</item>
<item>1-3</item>
<item>1-5</item>
</string-array>
<string-array name="streamsecurity_utls" translatable="false">
+2 -2
View File
@@ -47,8 +47,8 @@
<string name="server_lab_more_function">Transport</string>
<string name="server_lab_head_type">head type</string>
<string name="server_lab_mode_type">gRPC mode</string>
<string name="server_lab_request_host">request host(host/ws host/h2 host)/QUIC security</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC key/kcp seed/gRPC serviceName</string>
<string name="server_lab_request_host">request host(host/ws host/httpupgrade host/h2 host)/QUIC security/gRPC Authority</string>
<string name="server_lab_path">path(ws path/httpupgrade path/h2 path)/QUIC key/kcp seed/gRPC serviceName</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_stream_fingerprint" translatable="false">Fingerprint</string>
<string name="server_lab_stream_alpn" translatable="false">Alpn</string>
+1 -1
View File
@@ -2,5 +2,5 @@
plugins {
id("com.android.application") version "8.2.2" apply false
id("com.android.library") version "8.2.2" apply false
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
id("org.jetbrains.kotlin.android") version "1.9.23" apply false
}