Compare commits

..

56 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
18 changed files with 278 additions and 89 deletions
+3 -3
View File
@@ -11,8 +11,8 @@ android {
applicationId = "com.v2ray.ang"
minSdk = 21
targetSdk = 34
versionCode = 548
versionName = "1.8.17"
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
@@ -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) {
@@ -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)
@@ -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
@@ -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>
@@ -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>
+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>
@@ -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>
@@ -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
}