Compare commits

...

5 Commits

Author SHA1 Message Date
2dust 8ed17f9da0 Merge pull request #1446 from pozhiloy-enotik/patch-1
Allow external use
2022-04-15 07:21:23 +08:00
pozhiloy-enotik 1bbfda64fe Allow external use 2022-04-12 16:18:34 +03:00
2dust 5cadef8b2a Merge pull request #1416 from yuhan6665/master
Refactor and remove Kotlin synthetics
2022-03-20 10:16:16 +08:00
yuhan6665 5b92158353 Update readme 2022-03-19 21:27:26 -04:00
yuhan6665 73706c1d0f Refactor and remove Kotlin synthetics 2022-03-19 21:21:44 -04:00
5 changed files with 57 additions and 53 deletions
+2 -1
View File
@@ -29,4 +29,5 @@ Android project under V2rayNG folder can be compiled directly in Android Studio,
The aar can be compiled from the Golang project under AndroidLibV2rayLite folder. For a quick start, read guide for [Go Mobile](https://github.com/golang/go/wiki/Mobile) The aar can be compiled from the Golang project under AndroidLibV2rayLite folder. For a quick start, read guide for [Go Mobile](https://github.com/golang/go/wiki/Mobile)
and [Makefiles for Go Developers](https://tutorialedge.net/golang/makefiles-for-go-developers/) and [Makefiles for Go Developers](https://tutorialedge.net/golang/makefiles-for-go-developers/)
v2rayNG can run on Android Emulators. But VPN mode will not work if system don't support it, like Windows 11 WSA v2rayNG can run on Android Emulators. For WSA, VPN permission need to be granted via
`appops set [package name] ACTIVATE_VPN allow`
-4
View File
@@ -1,6 +1,5 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android { android {
compileSdkVersion Integer.parseInt("$compileSdkVer") compileSdkVersion Integer.parseInt("$compileSdkVer")
@@ -119,7 +118,4 @@ buildscript {
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
jcenter() jcenter()
} }
dependencies {
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlinVersion"
}
} }
+1 -1
View File
@@ -120,7 +120,7 @@
</service> </service>
<receiver <receiver
android:exported="false" android:exported="true"
android:name=".receiver.WidgetProvider" android:name=".receiver.WidgetProvider"
android:process=":RunSoLibV2RayDaemon"> android:process=":RunSoLibV2RayDaemon">
<meta-data <meta-data
@@ -8,7 +8,6 @@ import android.text.TextUtils
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import android.view.* import android.view.*
import kotlinx.android.synthetic.main.fragment_routing_settings.*
import android.view.MenuInflater import android.view.MenuInflater
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import com.tbruyelle.rxpermissions.RxPermissions import com.tbruyelle.rxpermissions.RxPermissions
@@ -62,7 +61,7 @@ class RoutingSettingsFragment : Fragment() {
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.save_routing -> { R.id.save_routing -> {
val content = et_routing_content.text.toString() val content = binding.etRoutingContent.text.toString()
defaultSharedPreferences.edit().putString(requireArguments().getString(routing_arg), content).apply() defaultSharedPreferences.edit().putString(requireArguments().getString(routing_arg), content).apply()
activity?.toast(R.string.toast_success) activity?.toast(R.string.toast_success)
true true
@@ -6,14 +6,12 @@ import android.text.TextUtils
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.AdapterView import android.widget.*
import android.widget.ArrayAdapter
import com.tencent.mmkv.MMKV import com.tencent.mmkv.MMKV
import com.v2ray.ang.R import com.v2ray.ang.R
import com.v2ray.ang.dto.EConfigType import com.v2ray.ang.dto.EConfigType
import com.v2ray.ang.dto.ServerConfig import com.v2ray.ang.dto.ServerConfig
import com.v2ray.ang.dto.V2rayConfig import com.v2ray.ang.dto.V2rayConfig
import com.v2ray.ang.dto.V2rayConfig.Companion.DEFAULT_NETWORK
import com.v2ray.ang.dto.V2rayConfig.Companion.DEFAULT_PORT import com.v2ray.ang.dto.V2rayConfig.Companion.DEFAULT_PORT
import com.v2ray.ang.dto.V2rayConfig.Companion.XTLS import com.v2ray.ang.dto.V2rayConfig.Companion.XTLS
import com.v2ray.ang.extension.toast import com.v2ray.ang.extension.toast
@@ -21,19 +19,6 @@ import com.v2ray.ang.util.MmkvManager
import com.v2ray.ang.util.MmkvManager.ID_MAIN import com.v2ray.ang.util.MmkvManager.ID_MAIN
import com.v2ray.ang.util.MmkvManager.KEY_SELECTED_SERVER import com.v2ray.ang.util.MmkvManager.KEY_SELECTED_SERVER
import com.v2ray.ang.util.Utils import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.activity_server_socks.*
import kotlinx.android.synthetic.main.activity_server_vmess.*
import kotlinx.android.synthetic.main.activity_server_vmess.et_address
import kotlinx.android.synthetic.main.activity_server_vmess.et_id
import kotlinx.android.synthetic.main.activity_server_vmess.et_path
import kotlinx.android.synthetic.main.activity_server_vmess.et_port
import kotlinx.android.synthetic.main.activity_server_vmess.et_remarks
import kotlinx.android.synthetic.main.activity_server_vmess.et_request_host
import kotlinx.android.synthetic.main.activity_server_vmess.sp_allow_insecure
import kotlinx.android.synthetic.main.activity_server_vmess.sp_header_type
import kotlinx.android.synthetic.main.activity_server_vmess.sp_header_type_title
import kotlinx.android.synthetic.main.activity_server_vmess.sp_network
import kotlinx.android.synthetic.main.activity_server_vmess.sp_stream_security
class ServerActivity : BaseActivity() { class ServerActivity : BaseActivity() {
@@ -76,6 +61,26 @@ class ServerActivity : BaseActivity() {
resources.getStringArray(R.array.allowinsecures) resources.getStringArray(R.array.allowinsecures)
} }
// Kotlin synthetics was used, but since it is removed in 1.8. We switch to old manual approach.
// We don't use AndroidViewBinding because, it is better to share similar logics for different
// protocols. Use findViewById manually ensures the xml are de-coupled with the activity logic.
private val et_remarks: EditText by lazy { findViewById(R.id.et_remarks) }
private val et_address: EditText by lazy { findViewById(R.id.et_address) }
private val et_port: EditText by lazy { findViewById(R.id.et_port) }
private val et_id: EditText by lazy { findViewById(R.id.et_id) }
//private val et_alterId: EditText? by lazy { findViewById(R.id.et_alterId) }
private val et_security: EditText? by lazy { findViewById(R.id.et_security) }
//private val sp_flow: Spinner? by lazy { findViewById(R.id.sp_flow) }
private val sp_security: Spinner? by lazy { findViewById(R.id.sp_security) }
private val sp_stream_security: Spinner? by lazy { findViewById(R.id.sp_stream_security) }
private val sp_allow_insecure: Spinner? by lazy { findViewById(R.id.sp_allow_insecure) }
//private val et_sni: EditText? by lazy { findViewById(R.id.et_sni) }
private val sp_network: Spinner? by lazy { findViewById(R.id.sp_network) }
private val sp_header_type: Spinner? by lazy { findViewById(R.id.sp_header_type) }
private val sp_header_type_title: TextView? by lazy { findViewById(R.id.sp_header_type_title) }
private val et_request_host: EditText? by lazy { findViewById(R.id.et_request_host) }
private val et_path: EditText? by lazy { findViewById(R.id.et_path) }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
title = getString(R.string.title_server) title = getString(R.string.title_server)
@@ -100,9 +105,9 @@ class ServerActivity : BaseActivity() {
getString(R.string.server_lab_mode_type) else getString(R.string.server_lab_mode_type) else
getString(R.string.server_lab_head_type) getString(R.string.server_lab_head_type)
config?.getProxyOutbound()?.getTransportSettingDetails()?.let { transportDetails -> config?.getProxyOutbound()?.getTransportSettingDetails()?.let { transportDetails ->
sp_header_type.setSelection(Utils.arrayFind(types, transportDetails[0])) sp_header_type?.setSelection(Utils.arrayFind(types, transportDetails[0]))
et_request_host.text = Utils.getEditable(transportDetails[1]) et_request_host?.text = Utils.getEditable(transportDetails[1])
et_path.text = Utils.getEditable(transportDetails[2]) et_path?.text = Utils.getEditable(transportDetails[2])
} }
} }
override fun onNothingSelected(parent: AdapterView<*>?) { override fun onNothingSelected(parent: AdapterView<*>?) {
@@ -129,9 +134,9 @@ class ServerActivity : BaseActivity() {
et_port.text = Utils.getEditable(outbound.getServerPort()?.toString() ?: DEFAULT_PORT.toString()) et_port.text = Utils.getEditable(outbound.getServerPort()?.toString() ?: DEFAULT_PORT.toString())
et_id.text = Utils.getEditable(outbound.getPassword().orEmpty()) et_id.text = Utils.getEditable(outbound.getPassword().orEmpty())
if (config.configType == EConfigType.SOCKS) { if (config.configType == EConfigType.SOCKS) {
et_security.text = Utils.getEditable(outbound.settings?.servers?.get(0)?.users?.get(0)?.user.orEmpty()) et_security?.text = Utils.getEditable(outbound.settings?.servers?.get(0)?.users?.get(0)?.user.orEmpty())
} else if (config.configType == EConfigType.VLESS) { } else if (config.configType == EConfigType.VLESS) {
et_security.text = Utils.getEditable(outbound.getSecurityEncryption().orEmpty()) et_security?.text = Utils.getEditable(outbound.getSecurityEncryption().orEmpty())
val flow = Utils.arrayFind(flows, outbound.settings?.vnext?.get(0)?.users?.get(0)?.flow.orEmpty()) val flow = Utils.arrayFind(flows, outbound.settings?.vnext?.get(0)?.users?.get(0)?.flow.orEmpty())
if (flow >= 0) { if (flow >= 0) {
//sp_flow.setSelection(flow) //sp_flow.setSelection(flow)
@@ -151,7 +156,7 @@ class ServerActivity : BaseActivity() {
if (allowinsecure >= 0) { if (allowinsecure >= 0) {
sp_allow_insecure?.setSelection(allowinsecure) sp_allow_insecure?.setSelection(allowinsecure)
} }
et_request_host.text = Utils.getEditable(tlsSetting.serverName) et_request_host?.text = Utils.getEditable(tlsSetting.serverName)
} }
} }
val network = Utils.arrayFind(networks, streamSetting.network) val network = Utils.arrayFind(networks, streamSetting.network)
@@ -214,7 +219,7 @@ class ServerActivity : BaseActivity() {
saveServers(server, port, config) saveServers(server, port, config)
} }
config.outboundBean?.streamSettings?.let { config.outboundBean?.streamSettings?.let {
saveStreamSettings(it, config) saveStreamSettings(it)
} }
MmkvManager.encodeServerConfig(editGuid, config) MmkvManager.encodeServerConfig(editGuid, config)
@@ -228,10 +233,10 @@ class ServerActivity : BaseActivity() {
vnext.port = port vnext.port = port
vnext.users[0].id = et_id.text.toString().trim() vnext.users[0].id = et_id.text.toString().trim()
if (config.configType == EConfigType.VMESS) { if (config.configType == EConfigType.VMESS) {
vnext.users[0].security = securitys[sp_security.selectedItemPosition] vnext.users[0].security = securitys[sp_security?.selectedItemPosition ?: 0]
} else if (config.configType == EConfigType.VLESS) { } else if (config.configType == EConfigType.VLESS) {
vnext.users[0].encryption = et_security.text.toString().trim() vnext.users[0].encryption = et_security?.text.toString().trim()
if (streamSecuritys[sp_stream_security.selectedItemPosition] == XTLS) { if (streamSecuritys[sp_stream_security?.selectedItemPosition ?: 0] == XTLS) {
// vnext.users[0].flow = flows[sp_flow.selectedItemPosition].ifBlank { V2rayConfig.DEFAULT_FLOW } // vnext.users[0].flow = flows[sp_flow.selectedItemPosition].ifBlank { V2rayConfig.DEFAULT_FLOW }
} else { } else {
vnext.users[0].flow = "" vnext.users[0].flow = ""
@@ -244,13 +249,13 @@ class ServerActivity : BaseActivity() {
server.port = port server.port = port
if (config.configType == EConfigType.SHADOWSOCKS) { if (config.configType == EConfigType.SHADOWSOCKS) {
server.password = et_id.text.toString().trim() server.password = et_id.text.toString().trim()
server.method = shadowsocksSecuritys[sp_security.selectedItemPosition] server.method = shadowsocksSecuritys[sp_security?.selectedItemPosition ?: 0]
} else if (config.configType == EConfigType.SOCKS) { } else if (config.configType == EConfigType.SOCKS) {
if (TextUtils.isEmpty(et_security.text) && TextUtils.isEmpty(et_id.text)) { if (TextUtils.isEmpty(et_security?.text) && TextUtils.isEmpty(et_id.text)) {
server.users = null server.users = null
} else { } else {
val socksUsersBean = V2rayConfig.OutboundBean.OutSettingsBean.ServersBean.SocksUsersBean() val socksUsersBean = V2rayConfig.OutboundBean.OutSettingsBean.ServersBean.SocksUsersBean()
socksUsersBean.user = et_security.text.toString().trim() socksUsersBean.user = et_security?.text.toString().trim()
socksUsersBean.pass = et_id.text.toString().trim() socksUsersBean.pass = et_id.text.toString().trim()
server.users = listOf(socksUsersBean) server.users = listOf(socksUsersBean)
} }
@@ -259,33 +264,36 @@ class ServerActivity : BaseActivity() {
} }
} }
private fun saveStreamSettings(streamSetting: V2rayConfig.OutboundBean.StreamSettingsBean, config: ServerConfig) { private fun saveStreamSettings(streamSetting: V2rayConfig.OutboundBean.StreamSettingsBean) {
val network = if (sp_network != null) networks[sp_network.selectedItemPosition] else DEFAULT_NETWORK val network = sp_network?.selectedItemPosition ?: return
val type = if (sp_header_type != null) transportTypes(network)[sp_header_type.selectedItemPosition] else "" val type = sp_header_type?.selectedItemPosition ?: return
val requestHost = if (et_request_host != null) et_request_host.text.toString().trim() else "" val requestHost = et_request_host?.text?.toString()?.trim() ?: return
val path = if (et_path != null) et_path.text.toString().trim() else "" val path = et_path?.text?.toString()?.trim() ?: return
//val sniField = et_sni?.text?.toString()?.trim() ?: return
val allowInsecureField = sp_allow_insecure?.selectedItemPosition ?: return
val streamSecurity = sp_stream_security?.selectedItemPosition ?: return
var sni = streamSetting.populateTransportSettings( var sni = streamSetting.populateTransportSettings(
transport = network, transport = networks[network],
headerType = type, headerType = transportTypes(networks[network])[type],
host = requestHost, host = requestHost,
path = path, path = path,
seed = path, seed = path,
quicSecurity = requestHost, quicSecurity = requestHost,
key = path, key = path,
mode = type, mode = transportTypes(networks[network])[type],
serviceName = path serviceName = path
) )
val allowInsecure = if (sp_allow_insecure == null || allowinsecures[sp_allow_insecure.selectedItemPosition].isBlank()) { //if (sniField.isNotBlank()) {
// sni = sniField
//}
val allowInsecure = if (allowinsecures[allowInsecureField].isBlank()) {
false//settingsStorage?.decodeBool(PREF_ALLOW_INSECURE) ?: false false//settingsStorage?.decodeBool(PREF_ALLOW_INSECURE) ?: false
} else { } else {
allowinsecures[sp_allow_insecure.selectedItemPosition].toBoolean() allowinsecures[allowInsecureField].toBoolean()
} }
val defaultTls = if (config.configType == EConfigType.TROJAN) V2rayConfig.TLS else "" streamSetting.populateTlsSettings(streamSecuritys[streamSecurity], allowInsecure, sni)
streamSetting.populateTlsSettings(
if (sp_stream_security != null) streamSecuritys[sp_stream_security.selectedItemPosition] else defaultTls,
allowInsecure,
sni
)
} }
private fun transportTypes(network: String?): Array<out String> { private fun transportTypes(network: String?): Array<out String> {