Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3074e9697 | ||
|
|
513ebcfa23 | ||
|
|
50d9057f1a | ||
|
|
2a563e7884 | ||
|
|
c69cd18842 | ||
|
|
7f2ced85a8 | ||
|
|
6c5eef99b5 | ||
|
|
d7c3bae8cc | ||
|
|
57c98f7c50 | ||
|
|
49be23c56a | ||
|
|
9b658e9a22 | ||
|
|
aaa84d081f |
@@ -1,3 +1,8 @@
|
||||
---
|
||||
name: v2rayNG程序问题
|
||||
about: 创建一个报告来帮助我们改进
|
||||
---
|
||||
|
||||
在提出问题前请先自行排除服务器端问题,同时也请通过搜索确认是否有人提出过相同问题。
|
||||
|
||||
|
||||
@@ -14,6 +19,7 @@
|
||||
|
||||
### 日志信息
|
||||
<details>
|
||||
|
||||
通过`adb logcat -s com.v2ray.ang GoLog V2rayConfigUtilGoLog Main`获取日志。请自行删减日志中可能出现的敏感信息。
|
||||
|
||||
如果问题可重现,建议先执行`adb logcat -c`清空系统日志再执行上述命令,再操作重现问题。
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: V2Ray程序问题
|
||||
url: https://github.com/v2fly/v2ray-core/
|
||||
about: 如果您有V2Ray而非v2rayNG的问题,请至这个链接讨论。
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
type Status struct {
|
||||
IsRunning bool
|
||||
IsTRunning bool
|
||||
PackageName string
|
||||
PackageCodePath string
|
||||
|
||||
|
||||
@@ -99,9 +99,7 @@ func (v *V2RayPoint) StopLoop() (err error) {
|
||||
v.v2rayOP.Lock()
|
||||
defer v.v2rayOP.Unlock()
|
||||
if v.status.IsRunning {
|
||||
close(v.closeChan)
|
||||
v.shutdownInit()
|
||||
v.SupportSet.OnEmitStatus(0, "Closed")
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -111,6 +109,10 @@ func (v *V2RayPoint) GetIsRunning() bool {
|
||||
return v.status.IsRunning
|
||||
}
|
||||
|
||||
func (v *V2RayPoint) GetIsTRunning() bool {
|
||||
return v.status.IsTRunning
|
||||
}
|
||||
|
||||
//Delegate Funcation
|
||||
func (v V2RayPoint) QueryStats(tag string, direct string) int64 {
|
||||
if v.statsManager == nil {
|
||||
@@ -124,12 +126,16 @@ func (v V2RayPoint) QueryStats(tag string, direct string) int64 {
|
||||
}
|
||||
|
||||
func (v *V2RayPoint) shutdownInit() {
|
||||
v.status.IsRunning = false
|
||||
close(v.closeChan)
|
||||
v.statsManager = nil
|
||||
v.status.Vpoint.Close()
|
||||
v.status.Vpoint = nil
|
||||
v.statsManager = nil
|
||||
v.status.IsRunning = false
|
||||
|
||||
v.escorter.EscortingDown()
|
||||
|
||||
v.SupportSet.Shutdown()
|
||||
v.SupportSet.OnEmitStatus(0, "Closed")
|
||||
}
|
||||
|
||||
func (v *V2RayPoint) pointloop() error {
|
||||
@@ -161,11 +167,13 @@ func (v *V2RayPoint) pointloop() error {
|
||||
v.SupportSet.Setup(v.status.GetVPNSetupArg(v.EnableLocalDNS, v.ForwardIpv6))
|
||||
v.SupportSet.OnEmitStatus(0, "Running")
|
||||
|
||||
v.status.IsTRunning = false
|
||||
if !v.ProxyOnly {
|
||||
if err := v.runTun2socks(); err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
v.status.IsTRunning = true
|
||||
|
||||
log.Printf("EnableLocalDNS: %v\nForwardIpv6: %v\nDomainName: %s",
|
||||
v.EnableLocalDNS,
|
||||
|
||||
@@ -38,6 +38,10 @@ android {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
splits {
|
||||
abi {
|
||||
enable true
|
||||
@@ -70,6 +74,10 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9"
|
||||
|
||||
// Androidx ktx
|
||||
implementation 'android.arch.lifecycle:extensions:1.1.1'
|
||||
implementation 'android.arch.lifecycle:livedata:1.1.1'
|
||||
|
||||
// Android support library
|
||||
implementation "com.android.support:support-v4:$supportLibVersion"
|
||||
implementation "com.android.support:appcompat-v7:$supportLibVersion"
|
||||
|
||||
@@ -15,6 +15,10 @@ import java.net.URLConnection
|
||||
val Context.v2RayApplication: AngApplication
|
||||
get() = applicationContext as AngApplication
|
||||
|
||||
// Usage note: DPreference use Android ContentProvider to redirect multi process access to main process.
|
||||
// Currently, RunSoLibV2RayDaemon process will run proxy core, keep minimum configuration and long running
|
||||
// in the background, support toggle on/off. That means it should NOT use DPreference after the initial
|
||||
// creation and setup of the service
|
||||
val Context.defaultDPreference: DPreference
|
||||
get() = v2RayApplication.defaultDPreference
|
||||
|
||||
|
||||
@@ -11,12 +11,10 @@ import android.service.quicksettings.Tile
|
||||
import android.service.quicksettings.TileService
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.extension.defaultDPreference
|
||||
import com.v2ray.ang.util.MessageUtil
|
||||
import com.v2ray.ang.util.Utils
|
||||
import java.lang.ref.SoftReference
|
||||
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
class QSTileService : TileService() {
|
||||
|
||||
@@ -27,7 +25,7 @@ class QSTileService : TileService() {
|
||||
qsTile?.icon = Icon.createWithResource(applicationContext, R.drawable.ic_v_idle)
|
||||
} else if (state == Tile.STATE_ACTIVE) {
|
||||
qsTile?.state = Tile.STATE_ACTIVE
|
||||
qsTile?.label = defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG_NAME, "NG")
|
||||
qsTile?.label = V2RayServiceManager.currentConfigName
|
||||
qsTile?.icon = Icon.createWithResource(applicationContext, R.drawable.ic_v)
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ object V2RayServiceManager {
|
||||
Seq.setContext(context)
|
||||
}
|
||||
}
|
||||
var currentConfigName = "NG"
|
||||
|
||||
private var lastQueryTime = 0L
|
||||
private var mBuilder: NotificationCompat.Builder? = null
|
||||
@@ -132,6 +133,7 @@ object V2RayServiceManager {
|
||||
v2rayPoint.forwardIpv6 = service.defaultDPreference.getPrefBoolean(SettingsActivity.PREF_FORWARD_IPV6, false)
|
||||
v2rayPoint.domainName = service.defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG_DOMAIN, "")
|
||||
v2rayPoint.proxyOnly = service.defaultDPreference.getPrefString(AppConfig.PREF_MODE, "VPN") != "VPN"
|
||||
currentConfigName = service.defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG_NAME, "NG")
|
||||
|
||||
try {
|
||||
v2rayPoint.runLoop()
|
||||
@@ -235,7 +237,7 @@ object V2RayServiceManager {
|
||||
|
||||
mBuilder = NotificationCompat.Builder(service, channelId)
|
||||
.setSmallIcon(R.drawable.ic_v)
|
||||
.setContentTitle(service.defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG_NAME, ""))
|
||||
.setContentTitle(currentConfigName)
|
||||
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||
.setOngoing(true)
|
||||
.setShowWhen(false)
|
||||
@@ -346,13 +348,10 @@ object V2RayServiceManager {
|
||||
}
|
||||
|
||||
fun stopSpeedNotification() {
|
||||
val service = serviceControl?.get()?.getService() ?: return
|
||||
if (mSubscription != null) {
|
||||
mSubscription?.unsubscribe() //stop queryStats
|
||||
mSubscription = null
|
||||
|
||||
val cfName = service.defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG_NAME, "")
|
||||
updateNotification(cfName, 0, 0)
|
||||
updateNotification(currentConfigName, 0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import android.os.ParcelFileDescriptor
|
||||
import android.os.StrictMode
|
||||
import android.support.annotation.RequiresApi
|
||||
import android.util.Log
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.extension.defaultDPreference
|
||||
import com.v2ray.ang.ui.PerAppProxyActivity
|
||||
@@ -127,7 +126,7 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
||||
}
|
||||
}
|
||||
|
||||
builder.setSession(defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG_NAME, ""))
|
||||
builder.setSession(V2RayServiceManager.currentConfigName)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
|
||||
defaultDPreference.getPrefBoolean(SettingsActivity.PREF_PER_APP_PROXY, false)) {
|
||||
|
||||
@@ -1,42 +1,41 @@
|
||||
package com.v2ray.ang.ui
|
||||
|
||||
import android.Manifest
|
||||
import android.content.*
|
||||
import android.arch.lifecycle.ViewModelProviders
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.net.VpnService
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.tbruyelle.rxpermissions.RxPermissions
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.util.AngConfigManager
|
||||
import com.v2ray.ang.util.Utils
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.KeyEvent
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.util.MessageUtil
|
||||
import com.v2ray.ang.util.V2rayConfigUtil
|
||||
import java.lang.ref.SoftReference
|
||||
import java.net.URL
|
||||
import android.content.IntentFilter
|
||||
import android.support.design.widget.NavigationView
|
||||
import android.support.v4.view.GravityCompat
|
||||
import android.support.v7.app.ActionBarDrawerToggle
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.helper.ItemTouchHelper
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.tbruyelle.rxpermissions.RxPermissions
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.BuildConfig
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.extension.defaultDPreference
|
||||
import com.v2ray.ang.extension.toast
|
||||
import com.v2ray.ang.helper.SimpleItemTouchHelperCallback
|
||||
import com.v2ray.ang.util.AngConfigManager
|
||||
import com.v2ray.ang.util.Utils
|
||||
import com.v2ray.ang.util.V2rayConfigUtil
|
||||
import com.v2ray.ang.viewmodel.MainViewModel
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import libv2ray.Libv2ray
|
||||
import rx.Observable
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import java.net.URL
|
||||
import java.util.concurrent.TimeUnit
|
||||
import com.v2ray.ang.helper.SimpleItemTouchHelperCallback
|
||||
import com.v2ray.ang.util.AngConfigManager.configs
|
||||
import kotlinx.coroutines.*
|
||||
import libv2ray.Libv2ray
|
||||
|
||||
class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener {
|
||||
companion object {
|
||||
@@ -46,23 +45,9 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
private const val REQUEST_SCAN_URL = 3
|
||||
}
|
||||
|
||||
var isRunning = false
|
||||
set(value) {
|
||||
field = value
|
||||
adapter.changeable = !value
|
||||
if (value) {
|
||||
fab.setImageResource(R.drawable.ic_v)
|
||||
tv_test_state.text = getString(R.string.connection_connected)
|
||||
} else {
|
||||
fab.setImageResource(R.drawable.ic_v_idle)
|
||||
tv_test_state.text = getString(R.string.connection_not_connected)
|
||||
}
|
||||
hideCircle()
|
||||
}
|
||||
|
||||
private val adapter by lazy { MainRecyclerAdapter(this) }
|
||||
private var mItemTouchHelper: ItemTouchHelper? = null
|
||||
private val tcpingTestScope by lazy { CoroutineScope(Dispatchers.IO) }
|
||||
private val mainViewModel: MainViewModel by lazy { ViewModelProviders.of(this).get(MainViewModel::class.java) }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -71,7 +56,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
fab.setOnClickListener {
|
||||
if (isRunning) {
|
||||
if (mainViewModel.isRunning.value == true) {
|
||||
Utils.stopVService(this)
|
||||
} else if (defaultDPreference.getPrefString(AppConfig.PREF_MODE, "VPN") == "VPN") {
|
||||
val intent = VpnService.prepare(this)
|
||||
@@ -85,16 +70,9 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
}
|
||||
}
|
||||
layout_test.setOnClickListener {
|
||||
if (isRunning) {
|
||||
val socksPort = 10808//Utils.parseInt(defaultDPreference.getPrefString(SettingsActivity.PREF_SOCKS_PORT, "10808"))
|
||||
|
||||
if (mainViewModel.isRunning.value == true) {
|
||||
tv_test_state.text = getString(R.string.connection_test_testing)
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
val result = Utils.testConnection(this@MainActivity, socksPort)
|
||||
launch(Dispatchers.Main) {
|
||||
tv_test_state.text = Utils.getEditable(result)
|
||||
}
|
||||
}
|
||||
mainViewModel.testCurrentServerRealPing()
|
||||
} else {
|
||||
// tv_test_state.text = getString(R.string.connection_test_fail)
|
||||
}
|
||||
@@ -115,6 +93,33 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
toggle.syncState()
|
||||
nav_view.setNavigationItemSelectedListener(this)
|
||||
version.text = "v${BuildConfig.VERSION_NAME} (${Libv2ray.checkVersionX()})"
|
||||
|
||||
setupViewModelObserver()
|
||||
}
|
||||
|
||||
private fun setupViewModelObserver() {
|
||||
mainViewModel.updateListAction.observe(this, {
|
||||
val index = it ?: return@observe
|
||||
if (index >= 0) {
|
||||
adapter.updateSelectedItem(index)
|
||||
} else {
|
||||
adapter.updateConfigList()
|
||||
}
|
||||
})
|
||||
mainViewModel.updateTestResultAction.observe(this, { tv_test_state.text = it })
|
||||
mainViewModel.isRunning.observe(this, {
|
||||
val isRunning = it ?: return@observe
|
||||
adapter.changeable = !isRunning
|
||||
if (isRunning) {
|
||||
fab.setImageResource(R.drawable.ic_v)
|
||||
tv_test_state.text = getString(R.string.connection_connected)
|
||||
} else {
|
||||
fab.setImageResource(R.drawable.ic_v_idle)
|
||||
tv_test_state.text = getString(R.string.connection_not_connected)
|
||||
}
|
||||
hideCircle()
|
||||
})
|
||||
mainViewModel.startListenBroadcast()
|
||||
}
|
||||
|
||||
fun startV2Ray() {
|
||||
@@ -128,27 +133,6 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
isRunning = false
|
||||
|
||||
// val intent = Intent(this.applicationContext, V2RayVpnService::class.java)
|
||||
// intent.`package` = AppConfig.ANG_PACKAGE
|
||||
// bindService(intent, mConnection, BIND_AUTO_CREATE)
|
||||
|
||||
mMsgReceive = ReceiveMessageHandler(this@MainActivity)
|
||||
registerReceiver(mMsgReceive, IntentFilter(AppConfig.BROADCAST_ACTION_ACTIVITY))
|
||||
MessageUtil.sendMsg2Service(this, AppConfig.MSG_REGISTER_CLIENT, "")
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
if (mMsgReceive != null) {
|
||||
unregisterReceiver(mMsgReceive)
|
||||
mMsgReceive = null
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onResume() {
|
||||
super.onResume()
|
||||
adapter.updateConfigList()
|
||||
@@ -188,7 +172,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
}
|
||||
|
||||
private fun getOptionIntent() = Intent().putExtra("position", -1)
|
||||
.putExtra("isRunning", isRunning)
|
||||
.putExtra("isRunning", mainViewModel.isRunning.value == true)
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
|
||||
R.id.import_qrcode -> {
|
||||
@@ -251,30 +235,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
}
|
||||
|
||||
R.id.ping_all -> {
|
||||
tcpingTestScope.coroutineContext[Job]?.cancelChildren()
|
||||
Utils.closeAllTcpSockets()
|
||||
for (k in 0 until configs.vmess.count()) {
|
||||
configs.vmess[k].testResult = ""
|
||||
adapter.updateConfigList()
|
||||
}
|
||||
for (k in 0 until configs.vmess.count()) {
|
||||
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
|
||||
}
|
||||
tcpingTestScope.launch {
|
||||
configs.vmess.getOrNull(k)?.let { // check null in case array is modified during testing
|
||||
it.testResult = Utils.tcping(serverAddress, serverPort)
|
||||
launch(Dispatchers.Main) {
|
||||
adapter.updateSelectedItem(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mainViewModel.testAllTcping()
|
||||
true
|
||||
}
|
||||
|
||||
@@ -514,35 +475,6 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
// }
|
||||
// }
|
||||
|
||||
private
|
||||
var mMsgReceive: BroadcastReceiver? = null
|
||||
|
||||
private class ReceiveMessageHandler(activity: MainActivity) : BroadcastReceiver() {
|
||||
internal var mReference: SoftReference<MainActivity> = SoftReference(activity)
|
||||
override fun onReceive(ctx: Context?, intent: Intent?) {
|
||||
val activity = mReference.get()
|
||||
when (intent?.getIntExtra("key", 0)) {
|
||||
AppConfig.MSG_STATE_RUNNING -> {
|
||||
activity?.isRunning = true
|
||||
}
|
||||
AppConfig.MSG_STATE_NOT_RUNNING -> {
|
||||
activity?.isRunning = false
|
||||
}
|
||||
AppConfig.MSG_STATE_START_SUCCESS -> {
|
||||
activity?.toast(R.string.toast_services_success)
|
||||
activity?.isRunning = true
|
||||
}
|
||||
AppConfig.MSG_STATE_START_FAILURE -> {
|
||||
activity?.toast(R.string.toast_services_failure)
|
||||
activity?.isRunning = false
|
||||
}
|
||||
AppConfig.MSG_STATE_STOP_SUCCESS -> {
|
||||
activity?.isRunning = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
moveTaskToBack(false)
|
||||
@@ -585,7 +517,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
}
|
||||
R.id.settings -> {
|
||||
startActivity(Intent(this, SettingsActivity::class.java)
|
||||
.putExtra("isRunning", isRunning))
|
||||
.putExtra("isRunning", mainViewModel.isRunning.value == true))
|
||||
}
|
||||
R.id.feedback -> {
|
||||
Utils.openUri(this, AppConfig.v2rayNGIssues)
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.v2ray.ang.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import android.arch.lifecycle.AndroidViewModel
|
||||
import android.arch.lifecycle.MutableLiveData
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.util.Log
|
||||
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.toast
|
||||
import com.v2ray.ang.util.AngConfigManager
|
||||
import com.v2ray.ang.util.MessageUtil
|
||||
import com.v2ray.ang.util.Utils
|
||||
import com.v2ray.ang.util.V2rayConfigUtil
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
class MainViewModel(application: Application) : AndroidViewModel(application) {
|
||||
val isRunning by lazy { MutableLiveData<Boolean>() }
|
||||
val updateListAction by lazy { MutableLiveData<Int>() }
|
||||
val updateTestResultAction by lazy { MutableLiveData<String>() }
|
||||
|
||||
private val tcpingTestScope by lazy { CoroutineScope(Dispatchers.IO) }
|
||||
|
||||
fun startListenBroadcast() {
|
||||
isRunning.value = false
|
||||
getApplication<AngApplication>().registerReceiver(mMsgReceiver, IntentFilter(AppConfig.BROADCAST_ACTION_ACTIVITY))
|
||||
MessageUtil.sendMsg2Service(getApplication(), AppConfig.MSG_REGISTER_CLIENT, "")
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
getApplication<AngApplication>().unregisterReceiver(mMsgReceiver)
|
||||
Log.i(AppConfig.ANG_PACKAGE, "Main ViewModel is cleared")
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
fun testAllTcping() {
|
||||
tcpingTestScope.coroutineContext[Job]?.cancelChildren()
|
||||
Utils.closeAllTcpSockets()
|
||||
for (k in 0 until AngConfigManager.configs.vmess.count()) {
|
||||
AngConfigManager.configs.vmess[k].testResult = ""
|
||||
updateListAction.value = -1 // update all
|
||||
}
|
||||
for (k in 0 until AngConfigManager.configs.vmess.count()) {
|
||||
var serverAddress = AngConfigManager.configs.vmess[k].address
|
||||
var serverPort = AngConfigManager.configs.vmess[k].port
|
||||
if (AngConfigManager.configs.vmess[k].configType == EConfigType.CUSTOM.value) {
|
||||
val serverOutbound = V2rayConfigUtil.getCustomConfigServerOutbound(getApplication(),
|
||||
AngConfigManager.configs.vmess[k].guid) ?: continue
|
||||
serverAddress = serverOutbound.getServerAddress() ?: continue
|
||||
serverPort = serverOutbound.getServerPort() ?: continue
|
||||
}
|
||||
tcpingTestScope.launch {
|
||||
AngConfigManager.configs.vmess.getOrNull(k)?.let { // check null in case array is modified during testing
|
||||
it.testResult = Utils.tcping(serverAddress, serverPort)
|
||||
launch(Dispatchers.Main) {
|
||||
updateListAction.value = k
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun testCurrentServerRealPing() {
|
||||
val socksPort = 10808//Utils.parseInt(defaultDPreference.getPrefString(SettingsActivity.PREF_SOCKS_PORT, "10808"))
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
val result = Utils.testConnection(getApplication(), socksPort)
|
||||
launch(Dispatchers.Main) {
|
||||
updateTestResultAction.value = result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val mMsgReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(ctx: Context?, intent: Intent?) {
|
||||
when (intent?.getIntExtra("key", 0)) {
|
||||
AppConfig.MSG_STATE_RUNNING -> {
|
||||
isRunning.value = true
|
||||
}
|
||||
AppConfig.MSG_STATE_NOT_RUNNING -> {
|
||||
isRunning.value = false
|
||||
}
|
||||
AppConfig.MSG_STATE_START_SUCCESS -> {
|
||||
getApplication<AngApplication>().toast(R.string.toast_services_success)
|
||||
isRunning.value = true
|
||||
}
|
||||
AppConfig.MSG_STATE_START_FAILURE -> {
|
||||
getApplication<AngApplication>().toast(R.string.toast_services_failure)
|
||||
isRunning.value = false
|
||||
}
|
||||
AppConfig.MSG_STATE_STOP_SUCCESS -> {
|
||||
isRunning.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user