Merge pull request #559 from yuhan6665/custom-config-improve

Custom config improve
This commit is contained in:
2dust
2020-08-16 20:26:17 +08:00
committed by GitHub
11 changed files with 135 additions and 99 deletions
@@ -50,12 +50,4 @@ object AppConfig {
const val MSG_STATE_STOP = 4
const val MSG_STATE_STOP_SUCCESS = 41
const val MSG_STATE_RESTART = 5
object EConfigType {
val Vmess = 1
val Custom = 2
val Shadowsocks = 3
val Socks = 4
}
}
@@ -0,0 +1,12 @@
package com.v2ray.ang.dto
enum class EConfigType(val value: Int) {
VMESS(1),
CUSTOM(2),
SHADOWSOCKS(3),
SOCKS(4);
companion object {
fun fromInt(value: Int) = values().firstOrNull { it.value == value }
}
}
@@ -108,6 +108,24 @@ data class V2rayConfig(
}
data class MuxBean(var enabled: Boolean)
fun getServerAddress(): String? {
if (protocol.equals(EConfigType.VMESS.name.toLowerCase())) {
return settings?.vnext?.get(0)?.address
} else if (protocol.equals(EConfigType.SHADOWSOCKS.name.toLowerCase()) || protocol.equals(EConfigType.SOCKS.name.toLowerCase())) {
return settings?.servers?.get(0)?.address
}
return null
}
fun getServerPort(): Int? {
if (protocol.equals(EConfigType.VMESS.name.toLowerCase())) {
return settings?.vnext?.get(0)?.port
} else if (protocol.equals(EConfigType.SHADOWSOCKS.name.toLowerCase()) || protocol.equals(EConfigType.SOCKS.name.toLowerCase())) {
return settings?.servers?.get(0)?.port
}
return null
}
}
//data class DnsBean(var servers: List<String>)
@@ -27,6 +27,7 @@ import android.support.v4.view.GravityCompat
import android.support.v7.app.ActionBarDrawerToggle
import android.support.v7.widget.helper.ItemTouchHelper
import android.util.Log
import com.v2ray.ang.dto.EConfigType
//import com.v2ray.ang.InappBuyActivity
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
@@ -252,16 +253,22 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
adapter.updateConfigList()
}
for (k in 0 until configs.vmess.count()) {
if (configs.vmess[k].configType != AppConfig.EConfigType.Custom) {
testingJobs.add(GlobalScope.launch(Dispatchers.IO) {
configs.vmess[k].testResult = Utils.tcping(configs.vmess[k].address, configs.vmess[k].port)
val myJob = coroutineContext[Job]
launch(Dispatchers.Main) {
testingJobs.remove(myJob)
adapter.updateSelectedItem(k)
}
})
var serverAddress = configs.vmess[k].address
var serverPort = configs.vmess[k].port
if (configs.vmess[k].configType == EConfigType.CUSTOM.value) {
val serverOutbound = V2rayConfigUtil.getCustomConfigServerOutbound(applicationContext, configs.vmess[k].guid)
?: continue
serverAddress = serverOutbound.getServerAddress() ?: continue
serverPort = serverOutbound.getServerPort() ?: continue
}
testingJobs.add(GlobalScope.launch(Dispatchers.IO) {
configs.vmess[k].testResult = Utils.tcping(serverAddress, serverPort)
val myJob = coroutineContext[Job]
launch(Dispatchers.Main) {
testingJobs.remove(myJob)
adapter.updateSelectedItem(k)
}
})
}
true
}
@@ -8,17 +8,19 @@ import android.view.ViewGroup
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.dto.AngConfig
import com.v2ray.ang.dto.EConfigType
import com.v2ray.ang.extension.defaultDPreference
import com.v2ray.ang.helper.ItemTouchHelperAdapter
import com.v2ray.ang.helper.ItemTouchHelperViewHolder
import com.v2ray.ang.util.AngConfigManager
import com.v2ray.ang.util.Utils
import com.v2ray.ang.util.V2rayConfigUtil
import kotlinx.android.synthetic.main.item_qrcode.view.*
import kotlinx.android.synthetic.main.item_recycler_main.view.*
import org.jetbrains.anko.*
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import java.util.concurrent.TimeUnit
import com.v2ray.ang.extension.defaultDPreference
class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<MainRecyclerAdapter.BaseViewHolder>()
, ItemTouchHelperAdapter {
@@ -49,7 +51,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
if (holder is MainViewHolder) {
val configType = configs.vmess[position].configType
val configType = EConfigType.fromInt(configs.vmess[position].configType)
val remarks = configs.vmess[position].remarks
val subid = configs.vmess[position].subid
val address = configs.vmess[position].address
@@ -67,39 +69,40 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
holder.subid.text = "S"
}
if (configType == AppConfig.EConfigType.Vmess) {
holder.type.text = "vmess"
holder.statistics.text = "$address : $port"
holder.layout_share.visibility = View.VISIBLE
} else if (configType == AppConfig.EConfigType.Custom) {
var shareOptions = share_method.asList()
if (configType == EConfigType.CUSTOM) {
holder.type.text = mActivity.getString(R.string.server_customize_config)
holder.statistics.text = ""//mActivity.getString(R.string.server_customize_config)
holder.layout_share.visibility = View.INVISIBLE
} else if (configType == AppConfig.EConfigType.Shadowsocks) {
holder.type.text = "shadowsocks"
val serverOutbound = V2rayConfigUtil.getCustomConfigServerOutbound(mActivity.applicationContext, configs.vmess[position].guid)
if (serverOutbound == null) {
holder.statistics.text = ""
} else {
holder.statistics.text = "${serverOutbound.getServerAddress()} : ${serverOutbound.getServerPort()}"
}
shareOptions = shareOptions.takeLast(1)
} else {
holder.type.text = configType?.name?.toLowerCase()
holder.statistics.text = "$address : $port"
holder.layout_share.visibility = View.VISIBLE
} else if (configType == AppConfig.EConfigType.Socks) {
holder.type.text = "socks"
holder.statistics.text = "$address : $port"
holder.layout_share.visibility = View.VISIBLE
}
holder.layout_share.setOnClickListener {
mActivity.selector(null, share_method.asList()) { dialogInterface, i ->
mActivity.selector(null, shareOptions) { dialogInterface, i ->
try {
when (i) {
0 -> {
val iv = mActivity.layoutInflater.inflate(R.layout.item_qrcode, null)
iv.iv_qcode.setImageBitmap(AngConfigManager.share2QRCode(position))
if (configType == EConfigType.CUSTOM) {
shareFullContent(position)
} else {
val iv = mActivity.layoutInflater.inflate(R.layout.item_qrcode, null)
iv.iv_qcode.setImageBitmap(AngConfigManager.share2QRCode(position))
mActivity.alert {
customView {
linearLayout {
addView(iv)
mActivity.alert {
customView {
linearLayout {
addView(iv)
}
}
}
}.show()
}.show()
}
}
1 -> {
if (AngConfigManager.share2Clipboard(position) == 0) {
@@ -108,15 +111,8 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
mActivity.toast(R.string.toast_failure)
}
}
2 -> {
if (AngConfigManager.shareFullContent2Clipboard(position) == 0) {
mActivity.toast(R.string.toast_success)
} else {
mActivity.toast(R.string.toast_failure)
}
}
else ->
mActivity.toast("else")
2 -> shareFullContent(position)
else -> mActivity.toast("else")
}
} catch (e: Exception) {
e.printStackTrace()
@@ -125,13 +121,13 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
}
holder.layout_edit.setOnClickListener {
if (configType == AppConfig.EConfigType.Vmess) {
if (configType == EConfigType.VMESS) {
mActivity.startActivity<ServerActivity>("position" to position, "isRunning" to !changeable)
} else if (configType == AppConfig.EConfigType.Custom) {
} else if (configType == EConfigType.CUSTOM) {
mActivity.startActivity<Server2Activity>("position" to position, "isRunning" to !changeable)
} else if (configType == AppConfig.EConfigType.Shadowsocks) {
} else if (configType == EConfigType.SHADOWSOCKS) {
mActivity.startActivity<Server3Activity>("position" to position, "isRunning" to !changeable)
} else if (configType == AppConfig.EConfigType.Socks) {
} else if (configType == EConfigType.SOCKS) {
mActivity.startActivity<Server4Activity>("position" to position, "isRunning" to !changeable)
}
}
@@ -176,6 +172,14 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
}
}
private fun shareFullContent(position: Int) {
if (AngConfigManager.shareFullContent2Clipboard(position) == 0) {
mActivity.toast(R.string.toast_success)
} else {
mActivity.toast(R.string.toast_failure)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
when (viewType) {
VIEW_TYPE_ITEM ->
@@ -14,6 +14,7 @@ import com.v2ray.ang.AppConfig.SS_PROTOCOL
import com.v2ray.ang.AppConfig.VMESS_PROTOCOL
import com.v2ray.ang.R
import com.v2ray.ang.dto.AngConfig
import com.v2ray.ang.dto.EConfigType
import com.v2ray.ang.dto.VmessQRCode
import java.net.URI
import java.net.URLDecoder
@@ -65,7 +66,7 @@ object AngConfigManager {
fun addServer(vmess: AngConfig.VmessBean, index: Int): Int {
try {
vmess.configVersion = 2
vmess.configType = AppConfig.EConfigType.Vmess
vmess.configType = EConfigType.VMESS.value
if (index >= 0) {
//edit
@@ -208,14 +209,14 @@ object AngConfigManager {
return app.defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG, "")
}
fun currConfigType(): Int {
fun currConfigType(): EConfigType? {
if (angConfig.index < 0
|| angConfig.vmess.count() <= 0
|| angConfig.index > angConfig.vmess.count() - 1
) {
return -1
return null
}
return angConfig.vmess[angConfig.index].configType
return EConfigType.fromInt(angConfig.vmess[angConfig.index].configType)
}
fun currConfigName(): String {
@@ -275,7 +276,7 @@ object AngConfigManager {
return R.string.toast_incorrect_protocol
}
vmess.configType = AppConfig.EConfigType.Vmess
vmess.configType = EConfigType.VMESS.value
vmess.security = "auto"
vmess.network = "tcp"
vmess.headerType = "none"
@@ -478,7 +479,7 @@ object AngConfigManager {
}
val vmess = angConfig.vmess[index]
if (angConfig.vmess[index].configType == AppConfig.EConfigType.Vmess) {
if (angConfig.vmess[index].configType == EConfigType.VMESS.value) {
val vmessQRCode = VmessQRCode()
vmessQRCode.v = vmess.configVersion.toString()
@@ -496,7 +497,7 @@ object AngConfigManager {
val conf = VMESS_PROTOCOL + Utils.encode(json)
return conf
} else if (angConfig.vmess[index].configType == AppConfig.EConfigType.Shadowsocks) {
} else if (angConfig.vmess[index].configType == EConfigType.SHADOWSOCKS.value) {
val remark = "#" + Utils.urlEncode(vmess.remarks)
val url = String.format("%s:%s@%s:%s",
vmess.security,
@@ -504,7 +505,7 @@ object AngConfigManager {
vmess.address,
vmess.port)
return SS_PROTOCOL + Utils.encode(url) + remark
} else if (angConfig.vmess[index].configType == AppConfig.EConfigType.Socks) {
} else if (angConfig.vmess[index].configType == EConfigType.SOCKS.value) {
val remark = "#" + Utils.urlEncode(vmess.remarks)
val url = String.format("%s:%s",
vmess.address,
@@ -613,7 +614,7 @@ object AngConfigManager {
//add
val vmess = AngConfig.VmessBean()
vmess.configVersion = 2
vmess.configType = AppConfig.EConfigType.Custom
vmess.configType = EConfigType.CUSTOM.value
vmess.guid = guid
vmess.remarks = vmess.guid
@@ -716,7 +717,7 @@ object AngConfigManager {
fun addCustomServer(vmess: AngConfig.VmessBean, index: Int): Int {
try {
vmess.configVersion = 2
vmess.configType = AppConfig.EConfigType.Custom
vmess.configType = EConfigType.CUSTOM.value
if (index >= 0) {
//edit
@@ -741,7 +742,7 @@ object AngConfigManager {
fun addShadowsocksServer(vmess: AngConfig.VmessBean, index: Int): Int {
try {
vmess.configVersion = 2
vmess.configType = AppConfig.EConfigType.Shadowsocks
vmess.configType = EConfigType.SHADOWSOCKS.value
if (index >= 0) {
//edit
@@ -766,7 +767,7 @@ object AngConfigManager {
fun addSocksServer(vmess: AngConfig.VmessBean, index: Int): Int {
try {
vmess.configVersion = 2
vmess.configType = AppConfig.EConfigType.Socks
vmess.configType = EConfigType.SOCKS.value
if (index >= 0) {
//edit
@@ -14,36 +14,25 @@ import kotlin.collections.HashMap
import android.app.ActivityManager
import android.content.ClipData
import android.content.Intent
import android.content.res.AssetManager
import android.net.Uri
import android.os.SystemClock
import android.text.TextUtils
import android.text.method.ScrollingMovementMethod
import android.util.Log
import android.util.Patterns
import android.view.View
import android.webkit.URLUtil
import com.v2ray.ang.AngApplication
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.dto.EConfigType
import com.v2ray.ang.extension.responseLength
import com.v2ray.ang.extension.v2RayApplication
import com.v2ray.ang.service.V2RayVpnService
import com.v2ray.ang.ui.SettingsActivity
import kotlinx.android.synthetic.main.activity_logcat.*
import kotlinx.coroutines.isActive
import me.dozen.dpreference.DPreference
import org.jetbrains.anko.toast
import org.jetbrains.anko.uiThread
import java.io.BufferedReader
import java.io.File
import java.io.IOException
import java.io.InputStreamReader
import java.net.*
import java.util.regex.Matcher
import java.util.regex.Pattern
import java.math.BigInteger
import java.util.concurrent.TimeUnit
import libv2ray.Libv2ray
import kotlin.coroutines.coroutineContext
@@ -324,7 +313,7 @@ object Utils {
if (AngConfigManager.genStoreV2rayConfig(-1)) {
val configContent = AngConfigManager.currGeneratedV2rayConfig()
val configType = AngConfigManager.currConfigType()
if (configType == AppConfig.EConfigType.Custom) {
if (configType == EConfigType.CUSTOM) {
try {
Libv2ray.testConfig(configContent)
} catch (e: Exception) {
@@ -1,5 +1,6 @@
package com.v2ray.ang.util
import android.content.Context
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
@@ -14,6 +15,8 @@ import org.json.JSONException
import org.json.JSONObject
import org.json.JSONArray
import com.google.gson.JsonObject
import com.v2ray.ang.dto.EConfigType
import com.v2ray.ang.extension.defaultDPreference
object V2rayConfigUtil {
private val requestObj: JsonObject by lazy {
@@ -40,13 +43,9 @@ object V2rayConfigUtil {
// return result
// }
if (vmess.configType == AppConfig.EConfigType.Vmess) {
result = getV2rayConfigType1(app, vmess)
} else if (vmess.configType == AppConfig.EConfigType.Custom) {
if (vmess.configType == EConfigType.CUSTOM.value) {
result = getV2rayConfigType2(app, vmess)
} else if (vmess.configType == AppConfig.EConfigType.Shadowsocks) {
result = getV2rayConfigType1(app, vmess)
} else if (vmess.configType == AppConfig.EConfigType.Socks) {
} else {
result = getV2rayConfigType1(app, vmess)
}
@@ -63,6 +62,22 @@ object V2rayConfigUtil {
}
}
fun getCustomConfigServerOutbound(content: Context, guid: String): V2rayConfig.OutboundBean? {
val jsonConfig = content.defaultDPreference.getPrefString(AppConfig.ANG_CONFIG + guid, "")
if (TextUtils.isEmpty(jsonConfig)) {
return null
}
val v2rayConfig = Gson().fromJson(jsonConfig, V2rayConfig::class.java) ?: return null
for (outbound in v2rayConfig.outbounds) {
if (outbound.protocol.equals(EConfigType.VMESS.name.toLowerCase()) ||
outbound.protocol.equals(EConfigType.SHADOWSOCKS.name.toLowerCase()) ||
outbound.protocol.equals(EConfigType.SOCKS.name.toLowerCase())) {
return outbound
}
}
return null
}
/**
* 生成v2ray的客户端配置文件
*/
@@ -163,8 +178,12 @@ object V2rayConfigUtil {
try {
val outbound = v2rayConfig.outbounds[0]
when (vmess.configType) {
AppConfig.EConfigType.Vmess -> {
val configType = EConfigType.fromInt(vmess.configType)
if (configType != null) {
outbound.protocol = configType.name.toLowerCase()
}
when (configType) {
EConfigType.VMESS -> {
outbound.settings?.servers = null
val vnext = v2rayConfig.outbounds[0].settings?.vnext?.get(0)
@@ -182,10 +201,8 @@ object V2rayConfigUtil {
//远程服务器底层传输配置
outbound.streamSettings = boundStreamSettings(vmess)
outbound.protocol = "vmess"
}
AppConfig.EConfigType.Shadowsocks -> {
EConfigType.SHADOWSOCKS -> {
outbound.settings?.vnext = null
val server = outbound.settings?.servers?.get(0)
@@ -198,10 +215,8 @@ object V2rayConfigUtil {
//Mux
outbound.mux?.enabled = false
outbound.protocol = "shadowsocks"
}
AppConfig.EConfigType.Socks -> {
EConfigType.SOCKS -> {
outbound.settings?.vnext = null
val server = outbound.settings?.servers?.get(0)
@@ -210,8 +225,6 @@ object V2rayConfigUtil {
//Mux
outbound.mux?.enabled = false
outbound.protocol = "socks"
}
else -> {
}
@@ -136,7 +136,7 @@
<string name="title_logcat">Logcat</string>
<string name="logcat_copy">复制</string>
<string name="logcat_delete">删除</string>
<string name="title_export_all">导出全部配置至剪贴板</string>
<string name="title_export_all">导出全部(非自定义)配置至剪贴板</string>
<string name="title_sub_setting">订阅设置</string>
<string name="sub_setting_remarks">备注</string>
<string name="sub_setting_url">地址(url)</string>
@@ -138,7 +138,7 @@
<string name="title_logcat">Logcat</string>
<string name="logcat_copy">複製</string>
<string name="logcat_delete">刪除</string>
<string name="title_export_all">匯出全部配置至剪貼簿</string>
<string name="title_export_all">匯出全部(非自訂)配置至剪貼簿</string>
<string name="title_sub_setting">訂閱設定</string>
<string name="sub_setting_remarks">備註</string>
<string name="sub_setting_url">位址(url)</string>
+1 -1
View File
@@ -138,7 +138,7 @@
<string name="title_logcat">Logcat</string>
<string name="logcat_copy">Copy</string>
<string name="logcat_delete">Delete</string>
<string name="title_export_all">Export all config to clipboard</string>
<string name="title_export_all">Export non-custom configs to clipboard</string>
<string name="title_sub_setting">Subscription setting</string>
<string name="sub_setting_remarks">remarks</string>
<string name="sub_setting_url">url</string>