Compare commits

..

21 Commits
1.4.1 ... 1.4.6

Author SHA1 Message Date
2dust
45805d6df7 Merge pull request #644 from yuhan6665/clean-dependency
Clean dependency
2020-10-04 19:16:27 +08:00
2dust
4437e6699b Merge pull request #635 from rurirei/diff
issues of VPNService.kt
2020-10-04 19:16:14 +08:00
2dust
fa409f91e4 Merge pull request #626 from yuhan6665/go
Clean up tun2socks
2020-10-04 19:16:00 +08:00
yuhan6665
89be5f077b Say goodbye to Anko
replace with support lib PreferenceManager
replace LayoutInflater
2020-10-03 11:19:46 -04:00
yuhan6665
896889778f Replace Anko with support lib AlertDialog
replace some property setter
2020-10-03 11:19:46 -04:00
yuhan6665
10f705a8b2 Use standard startActivity 2020-10-03 11:19:46 -04:00
yuhan6665
2956fa2030 Replace doasync with Kotlin coroutine
Using a custom coroutine scope, we don't need to keep track of the
running job. We can simply call cancel children for the scope.
2020-10-03 11:19:46 -04:00
yuhan6665
c2a704a6ea Deprecate some anko function
- Replace toast with inline function
- Use standard startActivityForResult
2020-10-03 11:19:46 -04:00
yuhan6665
78cac0cd90 Replace divider with standard library
Also, cleanup some unused classes
2020-10-03 11:19:46 -04:00
Rurirei
3ffb2e8e05 catch exception for lateinit
PropertyNotInitialized exception needs catch for lateinit var
2020-10-03 20:23:43 +08:00
Rurirei
e2d667e0bb sendFd() should not called twice 2020-10-01 17:36:07 +08:00
Rurirei
3ae0777d7f useless bool 2020-10-01 17:07:51 +08:00
Rurirei
5e6348676c ignore err of registerNetworkConnectivity 2020-10-01 15:32:08 +08:00
2dust
df3f1ca3ef Merge pull request #620 from yuhan6665/up-version
Update dependencies
2020-09-29 08:05:46 +08:00
yuhan6665
94f2bec329 Clean up tun2socks 2020-09-27 23:17:47 -04:00
yuhan6665
c54d8fa43a Update dependencies
Fix a delegate annotation for Kotlin 1.4
2020-09-25 18:37:29 -04:00
2dust
5bbbdcf6f2 Merge pull request #610 from yuhan6665/fix-protect
Fix protect() when there is no service
2020-09-21 07:59:55 +08:00
yuhan6665
4abf20fa32 Fix protect() when there is no service 2020-09-20 19:00:14 -04:00
2dust
723727feb9 Merge pull request #607 from yuhan6665/help-proxy-mode
Help proxy mode
2020-09-19 18:56:15 +08:00
yuhan6665
2efd4b741c Add badge, wiki link and dev guide 2020-09-18 17:48:54 -04:00
yuhan6665
83aab0f880 Add help link in mode setting 2020-09-18 17:48:54 -04:00
43 changed files with 284 additions and 366 deletions

View File

@@ -8,9 +8,6 @@ asset:
# cd assets;curl https://raw.githubusercontent.com/2dust/AndroidLibV2rayLite/master/data/geosite.dat > geosite.dat
# cd assets;curl https://raw.githubusercontent.com/2dust/AndroidLibV2rayLite/master/data/geoip.dat > geoip.dat
shippedBinary:
cd shippedBinarys; $(MAKE) shippedBinary
fetchDep:
-go get github.com/2dust/AndroidLibV2rayLite
go get github.com/2dust/AndroidLibV2rayLite
@@ -30,5 +27,5 @@ downloadGoMobile:
BuildMobile:
@echo Stub
all: asset pb shippedBinary fetchDep
all: asset pb fetchDep
@echo DONE

View File

@@ -34,14 +34,10 @@ $NDK_HOME/ndk-build \
NDK_OUT=$TMPDIR/tmp \
APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -j4
install -v -m755 libs/armeabi-v7a/tun2socks $__dir/shippedBinarys/ArchDep/arm/
install -v -m755 libs/arm64-v8a/tun2socks $__dir/shippedBinarys/ArchDep/arm64/
install -v -m755 libs/x86/tun2socks $__dir/shippedBinarys/ArchDep/386/
install -v -m755 libs/x86_64/tun2socks $__dir/shippedBinarys/ArchDep/amd64/
install -v -m755 libs/armeabi-v7a/tun2socks $__dir/../V2rayNG/app/src/main/jniLibs/armeabi-v7a/libtun2socks.so
install -v -m755 libs/arm64-v8a/tun2socks $__dir/../V2rayNG/app/src/main/jniLibs/arm64-v8a/libtun2socks.so
install -v -m755 libs/x86/tun2socks $__dir/../V2rayNG/app/src/main/jniLibs/x86/libtun2socks.so
install -v -m755 libs/x86_64/tun2socks $__dir/../V2rayNG/app/src/main/jniLibs/x86_64/libtun2socks.so
popd
pushd $__dir/shippedBinarys
make clean && make shippedBinary
popd
rm -rf $TMPDIR
rm -rf $TMPDIR

View File

@@ -11,7 +11,6 @@ import (
"github.com/2dust/AndroidLibV2rayLite/CoreI"
"github.com/2dust/AndroidLibV2rayLite/Process/Escort"
"github.com/2dust/AndroidLibV2rayLite/VPN"
"github.com/2dust/AndroidLibV2rayLite/shippedBinarys"
mobasset "golang.org/x/mobile/asset"
v2core "v2ray.com/core"
@@ -227,12 +226,6 @@ func NewV2RayPoint(s V2RayVPNServiceSupportsSet) *V2RayPoint {
}
func (v V2RayPoint) runTun2socks() error {
shipb := shippedBinarys.FirstRun{Status: v.status}
if err := shipb.CheckAndExport(); err != nil {
log.Println(err)
return err
}
v.escorter.EscortingUp()
go v.escorter.EscortRun(
v.status.GetApp("libtun2socks.so"),

View File

@@ -1,13 +0,0 @@
Platdep=shippedBinary.386 shippedBinary.amd64 shippedBinary.arm64 shippedBinary.arm
shippedBinaryDep:
go get -u github.com/jteeuwen/go-bindata/...
shippedBinary.%:
go-bindata -nometadata -nomemcopy -pkg shippedBinarys -o ./binary_$*.go -tags $* ArchIndep/ ArchDep/$*/
shippedBinary:shippedBinaryDep $(Platdep)
@echo "Done"
clean:
-rm binary*

View File

@@ -1,69 +0,0 @@
package shippedBinarys
import (
"log"
"os"
"strconv"
"github.com/2dust/AndroidLibV2rayLite/CoreI"
)
type FirstRun struct {
Status *CoreI.Status
}
func (v *FirstRun) checkIfRcExist() error {
datadir := v.Status.GetDataDir()
if _, err := os.Stat(datadir + strconv.Itoa(CoreI.CheckVersion())); !os.IsNotExist(err) {
log.Println("file exists")
return nil
}
IndepDir, err := AssetDir("ArchIndep")
log.Println(IndepDir)
if err != nil {
return err
}
for _, fn := range IndepDir {
log.Println(datadir+"ArchIndep/"+fn)
err := RestoreAsset(datadir, "ArchIndep/"+fn)
log.Println(err)
//GrantPremission
os.Chmod(datadir+"ArchIndep/"+fn, 0700)
log.Println(os.Remove(datadir + fn))
log.Println(os.Symlink(datadir+"ArchIndep/"+fn, datadir + fn))
}
DepDir, err := AssetDir("ArchDep")
log.Println(DepDir)
if err != nil {
return err
}
for _, fn := range DepDir {
DepDir2, err := AssetDir("ArchDep/" + fn)
log.Println("ArchDep/" + fn)
if err != nil {
return err
}
for _, FND := range DepDir2 {
log.Println(datadir+"ArchDep/"+fn+"/"+FND)
RestoreAsset(datadir, "ArchDep/"+fn+"/"+FND)
os.Chmod(datadir+"ArchDep/"+fn+"/"+FND, 0700)
log.Println(os.Remove(datadir + FND))
log.Println(os.Symlink(datadir+"ArchDep/"+fn+"/"+FND, datadir+FND))
}
}
s, _ := os.Create(datadir + strconv.Itoa(CoreI.CheckVersion()))
s.Close()
return nil
}
func (v *FirstRun) CheckAndExport() error {
return v.checkIfRcExist()
}

View File

@@ -1,5 +1,25 @@
# v2rayNG
A V2Ray client for Android
[![API](https://img.shields.io/badge/API-17%2B-yellow.svg?style=flat)](https://developer.android.com/about/versions/jelly-bean#android-4.2)
[![Kotlin Version](https://img.shields.io/badge/Kotlin-1.4.0-blue.svg)](https://kotlinlang.org)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/2dust/v2rayNG)](https://github.com/2dust/v2rayNG/commits/master)
[![CodeFactor](https://www.codefactor.io/repository/github/2dust/v2rayng/badge)](https://www.codefactor.io/repository/github/2dust/v2rayng)
[![GitHub Releases](https://img.shields.io/github/downloads/2dust/v2rayNG/latest/total?logo=github)](https://github.com/2dust/v2rayNG/releases)
<a href="https://play.google.com/store/apps/details?id=com.v2ray.ang">
<img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" width="165" height="64" />
</a>
### Usage
See our [wiki](https://github.com/2dust/v2rayNG/wiki)
### Development guide
Android project under V2rayNG folder can be compiled directly in Android Studio, or using Gradle wrapper. But the v2ray core inside the aar is (probably) outdated.
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/)
v2rayNG can run on Android Emulators, with minimum Android 5.0

View File

@@ -62,14 +62,13 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
testImplementation 'junit:junit:4.13'
implementation project(':dpreference')
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.2" // 1.3.x has compile error:
// More than one file was found with OS independent path 'META-INF/proguard/coroutines.pro'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9"
// Android support library
implementation "com.android.support:support-v4:$supportLibVersion"
@@ -79,22 +78,16 @@ dependencies {
implementation "com.android.support:preference-v7:$supportLibVersion"
implementation "com.android.support:recyclerview-v7:$supportLibVersion"
implementation "com.android.support:multidex:1.0.3"
implementation 'com.android.support.constraint:constraint-layout:2.0.1'
// DSL
implementation "org.jetbrains.anko:anko-sdk15:$ankoVersion"
implementation "org.jetbrains.anko:anko-support-v4:$ankoVersion"
implementation "org.jetbrains.anko:anko-appcompat-v7:$ankoVersion"
implementation "org.jetbrains.anko:anko-design:$ankoVersion"
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'io.reactivex:rxjava:1.3.4'
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'com.tbruyelle.rxpermissions:rxpermissions:0.9.4@aar'
implementation 'com.dinuscxj:recycleritemdecoration:1.0.0'
implementation 'io.reactivex:rxkotlin:0.60.0'
implementation 'me.dm7.barcodescanner:core:1.9.8'
implementation 'me.dm7.barcodescanner:zxing:1.9.8'
implementation 'com.github.jorgecastilloprz:fabprogresscircle:1.01@aar'
implementation 'com.beust:klaxon:3.0.1'
implementation 'com.android.support:multidex:1.0.3'
implementation(name: 'libv2ray', ext: 'aar')
//implementation(name: 'tun2socks', ext: 'aar')

View File

@@ -1,10 +1,9 @@
package com.v2ray.ang
//import com.squareup.leakcanary.LeakCanary
import android.support.multidex.MultiDexApplication
import android.support.v7.preference.PreferenceManager
import com.v2ray.ang.util.AngConfigManager
import me.dozen.dpreference.DPreference
import org.jetbrains.anko.defaultSharedPreferences
class AngApplication : MultiDexApplication() {
companion object {
@@ -22,6 +21,7 @@ class AngApplication : MultiDexApplication() {
// LeakCanary.install(this)
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
firstRun = defaultSharedPreferences.getInt(PREF_LAST_VERSION, 0) != BuildConfig.VERSION_CODE
if (firstRun)
defaultSharedPreferences.edit().putInt(PREF_LAST_VERSION, BuildConfig.VERSION_CODE).apply()

View File

@@ -38,6 +38,7 @@ object AppConfig {
const val androidpackagenamelistUrl = "https://raw.githubusercontent.com/2dust/androidpackagenamelist/master/proxy.txt"
const val v2rayCustomRoutingListUrl = "https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/"
const val v2rayNGIssues = "https://github.com/2dust/v2rayNG/issues"
const val v2rayNGWikiMode = "https://github.com/2dust/v2rayNG/wiki/Mode"
const val promotionUrl = "https://1.2345345.xyz/ads.html"
const val DNS_AGENT = "1.1.1.1"

View File

@@ -2,6 +2,7 @@ package com.v2ray.ang.extension
import android.content.Context
import android.os.Build
import android.widget.Toast
import com.v2ray.ang.AngApplication
import me.dozen.dpreference.DPreference
import org.json.JSONObject
@@ -17,6 +18,17 @@ val Context.v2RayApplication: AngApplication
val Context.defaultDPreference: DPreference
get() = v2RayApplication.defaultDPreference
inline fun Context.toast(message: Int): Toast = Toast
.makeText(this, message, Toast.LENGTH_SHORT)
.apply {
show()
}
inline fun Context.toast(message: CharSequence): Toast = Toast
.makeText(this, message, Toast.LENGTH_SHORT)
.apply {
show()
}
fun JSONObject.putOpt(pair: Pair<String, Any>) = putOpt(pair.first, pair.second)!!
fun JSONObject.putOpt(pairs: Map<String, Any>) = pairs.forEach { putOpt(it.key to it.value) }

View File

@@ -88,7 +88,7 @@ object V2RayServiceManager {
}
override fun protect(l: Long): Long {
val serviceControl = serviceControl?.get() ?: return 1
val serviceControl = serviceControl?.get() ?: return 0
return if (serviceControl.vpnProtect(l.toInt())) 0 else 1
}

View File

@@ -16,7 +16,9 @@ import com.v2ray.ang.extension.defaultDPreference
import com.v2ray.ang.ui.PerAppProxyActivity
import com.v2ray.ang.ui.SettingsActivity
import com.v2ray.ang.util.Utils
import org.jetbrains.anko.doAsync
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.File
import java.lang.ref.SoftReference
@@ -32,7 +34,8 @@ class V2RayVpnService : VpnService(), ServiceControl {
*
* Source: https://android.googlesource.com/platform/frameworks/base/+/2df4c7d/services/core/java/com/android/server/ConnectivityService.java#887
*/
private val defaultNetworkRequest by lazy @RequiresApi(Build.VERSION_CODES.P) {
@delegate:RequiresApi(Build.VERSION_CODES.P)
private val defaultNetworkRequest by lazy {
NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
@@ -41,7 +44,8 @@ class V2RayVpnService : VpnService(), ServiceControl {
private val connectivity by lazy { getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager }
private val defaultNetworkCallback by lazy @RequiresApi(Build.VERSION_CODES.P) {
@delegate:RequiresApi(Build.VERSION_CODES.P)
private val defaultNetworkCallback by lazy {
object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
setUnderlyingNetworks(arrayOf(network))
@@ -56,8 +60,6 @@ class V2RayVpnService : VpnService(), ServiceControl {
}
}
private var listeningForDefaultNetwork = false
override fun onCreate() {
super.onCreate()
@@ -151,8 +153,11 @@ class V2RayVpnService : VpnService(), ServiceControl {
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
listeningForDefaultNetwork = true
try {
connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
} catch (ignored: Exception) {
// ignored
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
@@ -160,15 +165,20 @@ class V2RayVpnService : VpnService(), ServiceControl {
}
// Create a new interface using the builder and save the parameters.
mInterface = builder.establish()
sendFd()
try {
mInterface = builder.establish()!!
} catch (e: Exception) {
// non-nullable lateinit var
e.printStackTrace()
stopV2Ray()
}
}
private fun sendFd() {
val fd = mInterface.fileDescriptor
val path = File(Utils.packagePath(applicationContext), "sock_path").absolutePath
doAsync {
GlobalScope.launch(Dispatchers.IO) {
var tries = 0
while (true) try {
Thread.sleep(50L shl tries)
@@ -198,9 +208,12 @@ class V2RayVpnService : VpnService(), ServiceControl {
// val emptyInfo = VpnNetworkInfo()
// val info = loadVpnNetworkInfo(configName, emptyInfo)!! + (lastNetworkInfo ?: emptyInfo)
// saveVpnNetworkInfo(configName, info)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && listeningForDefaultNetwork) {
connectivity.unregisterNetworkCallback(defaultNetworkCallback)
listeningForDefaultNetwork = false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
connectivity.unregisterNetworkCallback(defaultNetworkCallback)
} catch (ignored: Exception) {
// ignored
}
}
V2RayServiceManager.stopV2rayPoint()

View File

@@ -13,11 +13,7 @@ import android.support.v7.widget.Toolbar
import android.util.Log
import android.view.MenuItem
import android.view.View
//import com.v2ray.ang.InappBuyActivity
import com.v2ray.ang.R
import org.jetbrains.anko.startActivity
abstract class BaseDrawerActivity : BaseActivity() {
companion object {
@@ -58,7 +54,7 @@ abstract class BaseDrawerActivity : BaseActivity() {
R.id.sub_setting -> activityClass = SubSettingActivity::class.java
R.id.settings -> activityClass = SettingsActivity::class.java
R.id.logcat -> {
startActivity<LogcatActivity>()
startActivity(Intent(this@BaseDrawerActivity, LogcatActivity::class.java))
return
}
R.id.donate -> {

View File

@@ -8,12 +8,12 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import com.v2ray.ang.R
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.activity_logcat.*
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.toast
import org.jetbrains.anko.uiThread
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.IOException
import java.util.LinkedHashSet
@@ -34,7 +34,7 @@ class LogcatActivity : BaseActivity() {
try {
pb_waiting.visibility = View.VISIBLE
doAsync {
GlobalScope.launch(Dispatchers.Default) {
if (shouldFlushLog) {
val lst = LinkedHashSet<String>()
lst.add("logcat")
@@ -54,7 +54,7 @@ class LogcatActivity : BaseActivity() {
// InputStreamReader(process.inputStream))
// val allText = bufferedReader.use(BufferedReader::readText)
val allText = process.inputStream.bufferedReader().use { it.readText() }
uiThread {
launch(Dispatchers.Main) {
tv_logcat.text = allText
tv_logcat.movementMethod = ScrollingMovementMethod()
pb_waiting.visibility = View.GONE

View File

@@ -18,7 +18,6 @@ import android.view.KeyEvent
import com.v2ray.ang.AppConfig
import com.v2ray.ang.util.MessageUtil
import com.v2ray.ang.util.V2rayConfigUtil
import org.jetbrains.anko.*
import java.lang.ref.SoftReference
import java.net.URL
import android.content.IntentFilter
@@ -30,7 +29,7 @@ import android.util.Log
import com.v2ray.ang.BuildConfig
import com.v2ray.ang.dto.EConfigType
import com.v2ray.ang.extension.defaultDPreference
//import com.v2ray.ang.InappBuyActivity
import com.v2ray.ang.extension.toast
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import java.util.concurrent.TimeUnit
@@ -52,10 +51,10 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
field = value
adapter.changeable = !value
if (value) {
fab.imageResource = R.drawable.ic_v
fab.setImageResource(R.drawable.ic_v)
tv_test_state.text = getString(R.string.connection_connected)
} else {
fab.imageResource = R.drawable.ic_v_idle
fab.setImageResource(R.drawable.ic_v_idle)
tv_test_state.text = getString(R.string.connection_not_connected)
}
hideCircle()
@@ -63,7 +62,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
private val adapter by lazy { MainRecyclerAdapter(this) }
private var mItemTouchHelper: ItemTouchHelper? = null
private val testingJobs = ArrayList<Job>()
private val tcpingTestScope by lazy { CoroutineScope(Dispatchers.IO) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -90,9 +89,9 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
val socksPort = 10808//Utils.parseInt(defaultDPreference.getPrefString(SettingsActivity.PREF_SOCKS_PORT, "10808"))
tv_test_state.text = getString(R.string.connection_test_testing)
doAsync {
GlobalScope.launch(Dispatchers.IO) {
val result = Utils.testConnection(this@MainActivity, socksPort)
uiThread {
launch(Dispatchers.Main) {
tv_test_state.text = Utils.getEditable(result)
}
}
@@ -188,6 +187,9 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
return true
}
private fun getOptionIntent() = Intent().putExtra("position", -1)
.putExtra("isRunning", isRunning)
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.import_qrcode -> {
importQRcode(REQUEST_SCAN)
@@ -198,17 +200,17 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
true
}
R.id.import_manually_vmess -> {
startActivity<ServerActivity>("position" to -1, "isRunning" to isRunning)
startActivity(getOptionIntent().setClass(this, ServerActivity::class.java))
adapter.updateConfigList()
true
}
R.id.import_manually_ss -> {
startActivity<Server3Activity>("position" to -1, "isRunning" to isRunning)
startActivity(getOptionIntent().setClass(this, Server3Activity::class.java))
adapter.updateConfigList()
true
}
R.id.import_manually_socks -> {
startActivity<Server4Activity>("position" to -1, "isRunning" to isRunning)
startActivity(getOptionIntent().setClass(this, Server4Activity::class.java))
adapter.updateConfigList()
true
}
@@ -249,10 +251,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
}
R.id.ping_all -> {
testingJobs.forEach {
it.cancel()
}
testingJobs.clear()
tcpingTestScope.coroutineContext[Job]?.cancelChildren()
Utils.closeAllTcpSockets()
for (k in 0 until configs.vmess.count()) {
configs.vmess[k].testResult = ""
@@ -267,16 +266,14 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
serverAddress = serverOutbound.getServerAddress() ?: continue
serverPort = serverOutbound.getServerPort() ?: continue
}
testingJobs.add(GlobalScope.launch(Dispatchers.IO) {
tcpingTestScope.launch {
configs.vmess.getOrNull(k)?.let { // check null in case array is modified during testing
it.testResult = Utils.tcping(serverAddress, serverPort)
val myJob = coroutineContext[Job]
launch(Dispatchers.Main) {
testingJobs.remove(myJob)
adapter.updateSelectedItem(k)
}
}
})
}
}
true
}
@@ -306,7 +303,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
.request(Manifest.permission.CAMERA)
.subscribe {
if (it)
startActivityForResult<ScannerActivity>(requestCode)
startActivityForResult(Intent(this, ScannerActivity::class.java), requestCode)
else
toast(R.string.toast_permission_denied)
}
@@ -392,9 +389,14 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
toast(R.string.toast_invalid_url)
return false
}
doAsync {
val configText = URL(url).readText()
uiThread {
GlobalScope.launch(Dispatchers.IO) {
val configText = try {
URL(url).readText()
} catch (e: Exception) {
e.printStackTrace()
""
}
launch(Dispatchers.Main) {
importCustomizeConfig(configText)
}
}
@@ -426,9 +428,14 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
continue
}
Log.d("Main", url)
doAsync {
val configText = URL(url).readText()
uiThread {
GlobalScope.launch(Dispatchers.IO) {
val configText = try {
URL(url).readText()
} catch (e: Exception) {
e.printStackTrace()
""
}
launch(Dispatchers.Main) {
importBatchConfig(Utils.decode(configText), id)
}
}
@@ -574,10 +581,11 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
when (item.itemId) {
//R.id.server_profile -> activityClass = MainActivity::class.java
R.id.sub_setting -> {
startActivity<SubSettingActivity>()
startActivity(Intent(this, SubSettingActivity::class.java))
}
R.id.settings -> {
startActivity<SettingsActivity>("isRunning" to isRunning)
startActivity(Intent(this, SettingsActivity::class.java)
.putExtra("isRunning", isRunning))
}
R.id.feedback -> {
Utils.openUri(this, AppConfig.v2rayNGIssues)
@@ -589,7 +597,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
// startActivity<InappBuyActivity>()
}
R.id.logcat -> {
startActivity<LogcatActivity>()
startActivity(Intent(this, LogcatActivity::class.java))
}
}
drawer_layout.closeDrawer(GravityCompat.START)

View File

@@ -1,15 +1,18 @@
package com.v2ray.ang.ui
import android.content.Intent
import android.graphics.Color
import android.support.v7.app.AlertDialog
import android.support.v7.widget.RecyclerView
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
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.extension.toast
import com.v2ray.ang.helper.ItemTouchHelperAdapter
import com.v2ray.ang.helper.ItemTouchHelperViewHolder
import com.v2ray.ang.util.AngConfigManager
@@ -17,7 +20,6 @@ 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
@@ -60,7 +62,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
holder.name.text = remarks
holder.radio.isChecked = (position == configs.index)
holder.itemView.backgroundColor = Color.TRANSPARENT
holder.itemView.setBackgroundColor(Color.TRANSPARENT)
holder.test_result.text = test_result
if (TextUtils.isEmpty(subid)) {
@@ -85,7 +87,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
}
holder.layout_share.setOnClickListener {
mActivity.selector(null, shareOptions) { dialogInterface, i ->
AlertDialog.Builder(mActivity).setItems(shareOptions.toTypedArray()) { _, i ->
try {
when (i) {
0 -> {
@@ -94,14 +96,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
} else {
val iv = mActivity.layoutInflater.inflate(R.layout.item_qrcode, null)
iv.iv_qcode.setImageBitmap(AngConfigManager.share2QRCode(position))
mActivity.alert {
customView {
linearLayout {
addView(iv)
}
}
}.show()
AlertDialog.Builder(mActivity).setView(iv).show()
}
}
1 -> {
@@ -117,18 +112,20 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
} catch (e: Exception) {
e.printStackTrace()
}
}
}.show()
}
holder.layout_edit.setOnClickListener {
val intent = Intent().putExtra("position", position)
.putExtra("isRunning", !changeable)
if (configType == EConfigType.VMESS) {
mActivity.startActivity<ServerActivity>("position" to position, "isRunning" to !changeable)
mActivity.startActivity(intent.setClass(mActivity, ServerActivity::class.java))
} else if (configType == EConfigType.CUSTOM) {
mActivity.startActivity<Server2Activity>("position" to position, "isRunning" to !changeable)
mActivity.startActivity(intent.setClass(mActivity, Server2Activity::class.java))
} else if (configType == EConfigType.SHADOWSOCKS) {
mActivity.startActivity<Server3Activity>("position" to position, "isRunning" to !changeable)
mActivity.startActivity(intent.setClass(mActivity, Server3Activity::class.java))
} else if (configType == EConfigType.SOCKS) {
mActivity.startActivity<Server4Activity>("position" to position, "isRunning" to !changeable)
mActivity.startActivity(intent.setClass(mActivity, Server4Activity::class.java))
}
}
holder.layout_remove.setOnClickListener {
@@ -183,10 +180,10 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
when (viewType) {
VIEW_TYPE_ITEM ->
return MainViewHolder(parent.context.layoutInflater
return MainViewHolder(LayoutInflater.from(parent.context)
.inflate(R.layout.item_recycler_main, parent, false))
else ->
return FooterViewHolder(parent.context.layoutInflater
return FooterViewHolder(LayoutInflater.from(parent.context)
.inflate(R.layout.item_recycler_footer, parent, false))
}
}

View File

@@ -4,6 +4,8 @@ import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.content.Context
import android.os.Bundle
import android.support.v7.widget.DividerItemDecoration
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.text.TextUtils
import android.util.Log
@@ -12,7 +14,6 @@ import android.view.MenuItem
import android.view.View
import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator
import com.dinuscxj.itemdecoration.LinearDividerItemDecoration
import com.v2ray.ang.R
import com.v2ray.ang.extension.defaultDPreference
import com.v2ray.ang.util.AppManagerUtil
@@ -25,11 +26,12 @@ import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import com.v2ray.ang.AppConfig
import com.v2ray.ang.dto.AppInfo
import com.v2ray.ang.extension.toast
import com.v2ray.ang.extension.v2RayApplication
import com.v2ray.ang.util.Utils
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.toast
import org.jetbrains.anko.uiThread
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.net.URL
class PerAppProxyActivity : BaseActivity() {
@@ -47,8 +49,7 @@ class PerAppProxyActivity : BaseActivity() {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val dividerItemDecoration = LinearDividerItemDecoration(
this, LinearDividerItemDecoration.LINEAR_DIVIDER_VERTICAL)
val dividerItemDecoration = DividerItemDecoration(this, LinearLayoutManager.VERTICAL)
recycler_view.addItemDecoration(dividerItemDecoration)
val blacklist = defaultDPreference.getPrefStringSet(PREF_PER_APP_PROXY_SET, null)
@@ -220,9 +221,14 @@ class PerAppProxyActivity : BaseActivity() {
private fun selectProxyApp() {
toast(R.string.msg_downloading_content)
val url = AppConfig.androidpackagenamelistUrl
doAsync {
val content = URL(url).readText()
uiThread {
GlobalScope.launch(Dispatchers.IO) {
val content = try {
URL(url).readText()
} catch (e: Exception) {
e.printStackTrace()
""
}
launch(Dispatchers.Main) {
Log.d("selectProxyApp", content)
selectProxyApp(content)
toast(R.string.toast_success)
@@ -276,4 +282,4 @@ class PerAppProxyActivity : BaseActivity() {
}
return true
}
}
}

View File

@@ -2,14 +2,12 @@ package com.v2ray.ang.ui
import android.graphics.Color
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.v2ray.ang.R
import com.v2ray.ang.dto.AppInfo
import kotlinx.android.synthetic.main.item_recycler_bypass_list.view.*
import org.jetbrains.anko.image
import org.jetbrains.anko.layoutInflater
import org.jetbrains.anko.textColor
import java.util.*
class PerAppProxyAdapter(val activity: BaseActivity, val apps: List<AppInfo>, blacklist: MutableSet<String>?) :
@@ -45,7 +43,7 @@ class PerAppProxyAdapter(val activity: BaseActivity, val apps: List<AppInfo>, bl
// VIEW_TYPE_ITEM -> AppViewHolder(ctx.layoutInflater
// .inflate(R.layout.item_recycler_bypass_list, parent, false))
else -> AppViewHolder(ctx.layoutInflater
else -> AppViewHolder(LayoutInflater.from(ctx)
.inflate(R.layout.item_recycler_bypass_list, parent, false))
}
@@ -68,17 +66,17 @@ class PerAppProxyAdapter(val activity: BaseActivity, val apps: List<AppInfo>, bl
fun bind(appInfo: AppInfo) {
this.appInfo = appInfo
icon.image = appInfo.appIcon
icon.setImageDrawable(appInfo.appIcon)
// name.text = appInfo.appName
checkBox.isChecked = inBlacklist
package_name.text = appInfo.packageName
if (appInfo.isSystemApp) {
name.text = String.format("** %1s", appInfo.appName)
name.textColor = Color.RED
name.setTextColor(Color.RED)
} else {
name.text = appInfo.appName
name.textColor = Color.DKGRAY
name.setTextColor(Color.DKGRAY)
}
itemView.setOnClickListener(this)
@@ -94,4 +92,4 @@ class PerAppProxyAdapter(val activity: BaseActivity, val apps: List<AppInfo>, bl
}
}
}
}
}

View File

@@ -1,30 +1,24 @@
package com.v2ray.ang.ui
import android.Manifest
import android.app.Activity.RESULT_OK
import android.content.Intent
import android.os.Bundle
import android.support.v4.app.Fragment
import android.text.TextUtils
import android.util.Log
import android.view.*
import com.v2ray.ang.R
import com.v2ray.ang.extension.defaultDPreference
import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.fragment_routing_settings.*
import org.jetbrains.anko.toast
import android.view.MenuInflater
import com.tbruyelle.rxpermissions.RxPermissions
import com.v2ray.ang.AppConfig
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.startActivityForResult
import org.jetbrains.anko.support.v4.startActivityForResult
import org.jetbrains.anko.support.v4.toast
import org.jetbrains.anko.uiThread
import com.v2ray.ang.extension.toast
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.net.URL
class RoutingSettingsFragment : Fragment() {
companion object {
private const val routing_arg = "routing_arg"
@@ -96,7 +90,7 @@ class RoutingSettingsFragment : Fragment() {
.request(Manifest.permission.CAMERA)
.subscribe {
if (it)
startActivityForResult<ScannerActivity>(requestCode)
startActivityForResult(Intent(activity, ScannerActivity::class.java), requestCode)
else
activity?.toast(R.string.toast_permission_denied)
}
@@ -118,12 +112,17 @@ class RoutingSettingsFragment : Fragment() {
}
}
toast(R.string.msg_downloading_content)
doAsync {
val content = URL(url).readText()
uiThread {
et_routing_content.text = Utils.getEditable(content!!)
toast(R.string.toast_success)
activity?.toast(R.string.msg_downloading_content)
GlobalScope.launch(Dispatchers.IO) {
val content = try {
URL(url).readText()
} catch (e: Exception) {
e.printStackTrace()
""
}
launch(Dispatchers.Main) {
et_routing_content.text = Utils.getEditable(content)
activity?.toast(R.string.toast_success)
}
}
return true

View File

@@ -6,7 +6,7 @@ import com.tbruyelle.rxpermissions.RxPermissions
import com.v2ray.ang.R
import com.v2ray.ang.util.AngConfigManager
import android.os.Bundle
import org.jetbrains.anko.*
import com.v2ray.ang.extension.toast
class ScScannerActivity : BaseActivity() {
companion object {
@@ -24,7 +24,7 @@ class ScScannerActivity : BaseActivity() {
.request(Manifest.permission.CAMERA)
.subscribe {
if (it)
startActivityForResult<ScannerActivity>(requestCode)
startActivityForResult(Intent(this, ScannerActivity::class.java), requestCode)
else
toast(R.string.toast_permission_denied)
}
@@ -43,10 +43,10 @@ class ScScannerActivity : BaseActivity() {
} else {
toast(R.string.toast_failure)
}
startActivity<MainActivity>()
startActivity(Intent(this, MainActivity::class.java))
}
}
finish()
}
}
}

View File

@@ -7,23 +7,13 @@ import com.google.zxing.Result
import me.dm7.barcodescanner.zxing.ZXingScannerView
import android.content.Intent
import android.graphics.BitmapFactory
import android.icu.util.TimeUnit
import android.view.Menu
import android.view.MenuItem
import com.google.zxing.BarcodeFormat
import com.tbruyelle.rxpermissions.RxPermissions
import com.v2ray.ang.R
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.QRCodeDecoder
import org.jetbrains.anko.toast
import rx.Observable
import android.os.SystemClock
import kotlinx.android.synthetic.main.activity_main.*
import rx.Observer
import rx.android.schedulers.AndroidSchedulers
import javax.xml.datatype.DatatypeConstants.SECONDS
class ScannerActivity : BaseActivity(), ZXingScannerView.ResultHandler {
companion object {

View File

@@ -1,6 +1,7 @@
package com.v2ray.ang.ui
import android.os.Bundle
import android.support.v7.app.AlertDialog
import android.text.Editable
import android.text.TextUtils
import android.view.Menu
@@ -10,13 +11,12 @@ import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.extension.defaultDPreference
import com.v2ray.ang.dto.AngConfig
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.AngConfigManager
import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.activity_server2.*
import org.jetbrains.anko.*
import java.lang.Exception
class Server2Activity : BaseActivity() {
companion object {
private const val REQUEST_SCAN = 1
@@ -112,17 +112,16 @@ class Server2Activity : BaseActivity() {
*/
fun deleteServer(): Boolean {
if (edit_index >= 0) {
alert(R.string.del_config_comfirm) {
positiveButton(android.R.string.ok) {
if (AngConfigManager.removeServer(edit_index) == 0) {
toast(R.string.toast_success)
finish()
} else {
toast(R.string.toast_failure)
AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm)
.setPositiveButton(android.R.string.ok) { _, _ ->
if (AngConfigManager.removeServer(edit_index) == 0) {
toast(R.string.toast_success)
finish()
} else {
toast(R.string.toast_failure)
}
}
}
show()
}
.show()
} else {
}
return true
@@ -158,4 +157,4 @@ class Server2Activity : BaseActivity() {
}
else -> super.onOptionsItemSelected(item)
}
}
}

View File

@@ -1,16 +1,16 @@
package com.v2ray.ang.ui
import android.os.Bundle
import android.support.v7.app.AlertDialog
import android.text.TextUtils
import android.view.Menu
import android.view.MenuItem
import com.v2ray.ang.R
import com.v2ray.ang.dto.AngConfig
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.AngConfigManager
import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.activity_server3.*
import org.jetbrains.anko.*
class Server3Activity : BaseActivity() {
companion object {
@@ -126,17 +126,16 @@ class Server3Activity : BaseActivity() {
*/
fun deleteServer(): Boolean {
if (edit_index >= 0) {
alert(R.string.del_config_comfirm) {
positiveButton(android.R.string.ok) {
if (AngConfigManager.removeServer(edit_index) == 0) {
toast(R.string.toast_success)
finish()
} else {
toast(R.string.toast_failure)
AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm)
.setPositiveButton(android.R.string.ok) { _, _ ->
if (AngConfigManager.removeServer(edit_index) == 0) {
toast(R.string.toast_success)
finish()
} else {
toast(R.string.toast_failure)
}
}
}
show()
}
.show()
} else {
}
return true
@@ -172,4 +171,4 @@ class Server3Activity : BaseActivity() {
}
else -> super.onOptionsItemSelected(item)
}
}
}

View File

@@ -1,16 +1,16 @@
package com.v2ray.ang.ui
import android.os.Bundle
import android.support.v7.app.AlertDialog
import android.text.TextUtils
import android.view.Menu
import android.view.MenuItem
import com.v2ray.ang.R
import com.v2ray.ang.dto.AngConfig
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.AngConfigManager
import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.activity_server4.*
import org.jetbrains.anko.*
class Server4Activity : BaseActivity() {
companion object {
@@ -110,17 +110,16 @@ class Server4Activity : BaseActivity() {
*/
fun deleteServer(): Boolean {
if (edit_index >= 0) {
alert(R.string.del_config_comfirm) {
positiveButton(android.R.string.ok) {
if (AngConfigManager.removeServer(edit_index) == 0) {
toast(R.string.toast_success)
finish()
} else {
toast(R.string.toast_failure)
AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm)
.setPositiveButton(android.R.string.ok) { _, _ ->
if (AngConfigManager.removeServer(edit_index) == 0) {
toast(R.string.toast_success)
finish()
} else {
toast(R.string.toast_failure)
}
}
}
show()
}
.show()
} else {
}
return true
@@ -156,4 +155,4 @@ class Server4Activity : BaseActivity() {
}
else -> super.onOptionsItemSelected(item)
}
}
}

View File

@@ -1,16 +1,16 @@
package com.v2ray.ang.ui
import android.os.Bundle
import android.support.v7.app.AlertDialog
import android.text.TextUtils
import android.view.Menu
import android.view.MenuItem
import com.v2ray.ang.R
import com.v2ray.ang.dto.AngConfig
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.AngConfigManager
import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.activity_server.*
import org.jetbrains.anko.*
class ServerActivity : BaseActivity() {
companion object {
@@ -169,17 +169,16 @@ class ServerActivity : BaseActivity() {
*/
fun deleteServer(): Boolean {
if (edit_index >= 0) {
alert(R.string.del_config_comfirm) {
positiveButton(android.R.string.ok) {
if (AngConfigManager.removeServer(edit_index) == 0) {
toast(R.string.toast_success)
finish()
} else {
toast(R.string.toast_failure)
AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm)
.setPositiveButton(android.R.string.ok) { _, _ ->
if (AngConfigManager.removeServer(edit_index) == 0) {
toast(R.string.toast_success)
finish()
} else {
toast(R.string.toast_failure)
}
}
}
show()
}
.show()
} else {
}
return true
@@ -215,4 +214,4 @@ class ServerActivity : BaseActivity() {
}
else -> super.onOptionsItemSelected(item)
}
}
}

View File

@@ -1,13 +1,13 @@
package com.v2ray.ang.ui
import android.content.Intent
import android.os.Bundle
import android.support.v7.preference.*
import android.view.View
import com.v2ray.ang.R
import com.v2ray.ang.AppConfig
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.Utils
import org.jetbrains.anko.defaultSharedPreferences
import org.jetbrains.anko.startActivity
import org.jetbrains.anko.toast
class SettingsActivity : BaseActivity() {
companion object {
@@ -70,7 +70,7 @@ class SettingsActivity : BaseActivity() {
// val feedback: Preference by lazy { findPreference(PREF_FEEDBACK) }
// val tgGroup: Preference by lazy { findPreference(PREF_TG_GROUP) }
private val mode: Preference by lazy { findPreference(AppConfig.PREF_MODE) }
private val mode by lazy { findPreference(AppConfig.PREF_MODE) as ListPreference }
private fun restartProxy() {
Utils.stopVService(requireContext())
@@ -88,7 +88,7 @@ class SettingsActivity : BaseActivity() {
if (isRunning()) {
Utils.stopVService(requireContext())
}
activity?.startActivity<PerAppProxyActivity>()
startActivity(Intent(activity, PerAppProxyActivity::class.java))
perAppProxy.isChecked = true
true
}
@@ -125,7 +125,7 @@ class SettingsActivity : BaseActivity() {
routingCustom.setOnPreferenceClickListener {
if (isRunning())
Utils.stopVService(requireContext())
activity?.startActivity<RoutingSettingsActivity>()
startActivity(Intent(activity, RoutingSettingsActivity::class.java))
false
}
@@ -164,6 +164,7 @@ class SettingsActivity : BaseActivity() {
updatePerAppProxy(newValue.toString())
true
}
mode.dialogLayoutResource = R.layout.preference_with_help_link
// donate.onClick {
// startActivity<InappBuyActivity>()
@@ -204,9 +205,10 @@ class SettingsActivity : BaseActivity() {
override fun onStart() {
super.onStart()
updatePerAppProxy(activity?.defaultSharedPreferences?.getString(AppConfig.PREF_MODE, "VPN"))
remoteDns.summary = activity?.defaultSharedPreferences?.getString(PREF_REMOTE_DNS, "")
domesticDns.summary = activity?.defaultSharedPreferences?.getString(PREF_DOMESTIC_DNS, "")
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(activity)
updatePerAppProxy(defaultSharedPreferences.getString(AppConfig.PREF_MODE, "VPN"))
remoteDns.summary = defaultSharedPreferences.getString(PREF_REMOTE_DNS, "")
domesticDns.summary = defaultSharedPreferences.getString(PREF_DOMESTIC_DNS, "")
if (remoteDns.summary == "") {
remoteDns.summary = AppConfig.DNS_AGENT
@@ -221,14 +223,18 @@ class SettingsActivity : BaseActivity() {
}
private fun updatePerAppProxy(mode: String?) {
val preference = activity?.defaultSharedPreferences ?: return
if (mode == "VPN") {
perAppProxy.isEnabled = true
perAppProxy.isChecked = preference.getBoolean(PREF_PER_APP_PROXY, false)
perAppProxy.isChecked = PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(PREF_PER_APP_PROXY, false)
} else {
perAppProxy.isEnabled = false
perAppProxy.isChecked = false
}
}
}
fun onModeHelpClicked(view: View) {
Utils.openUri(this, AppConfig.v2rayNGWikiMode)
}
}

View File

@@ -1,16 +1,16 @@
package com.v2ray.ang.ui
import android.os.Bundle
import android.support.v7.app.AlertDialog
import android.text.TextUtils
import android.view.Menu
import android.view.MenuItem
import com.v2ray.ang.R
import com.v2ray.ang.dto.AngConfig
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.AngConfigManager
import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.activity_sub_edit.*
import org.jetbrains.anko.*
class SubEditActivity : BaseActivity() {
@@ -95,17 +95,16 @@ class SubEditActivity : BaseActivity() {
*/
fun deleteServer(): Boolean {
if (edit_index >= 0) {
alert(R.string.del_config_comfirm) {
positiveButton(android.R.string.ok) {
if (AngConfigManager.removeSubItem(edit_index) == 0) {
toast(R.string.toast_success)
finish()
} else {
toast(R.string.toast_failure)
AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm)
.setPositiveButton(android.R.string.ok) { _, _ ->
if (AngConfigManager.removeSubItem(edit_index) == 0) {
toast(R.string.toast_success)
finish()
} else {
toast(R.string.toast_failure)
}
}
}
show()
}
.show()
} else {
}
return true
@@ -135,4 +134,4 @@ class SubEditActivity : BaseActivity() {
}
else -> super.onOptionsItemSelected(item)
}
}
}

View File

@@ -1,12 +1,12 @@
package com.v2ray.ang.ui
import android.content.Intent
import android.support.v7.widget.LinearLayoutManager
import android.view.Menu
import android.view.MenuItem
import com.v2ray.ang.R
import kotlinx.android.synthetic.main.activity_sub_setting.*
import android.os.Bundle
import org.jetbrains.anko.startActivity
class SubSettingActivity : BaseActivity() {
@@ -40,7 +40,9 @@ class SubSettingActivity : BaseActivity() {
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.add_config -> {
startActivity<SubEditActivity>("position" to -1)
startActivity(Intent(this, SubEditActivity::class.java)
.putExtra("position", -1)
)
adapter.updateConfigList()
true
}
@@ -48,4 +50,4 @@ class SubSettingActivity : BaseActivity() {
}
}
}

View File

@@ -1,14 +1,15 @@
package com.v2ray.ang.ui
import android.content.Intent
import android.graphics.Color
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.v2ray.ang.R
import com.v2ray.ang.dto.AngConfig
import com.v2ray.ang.util.AngConfigManager
import kotlinx.android.synthetic.main.item_recycler_sub_setting.view.*
import org.jetbrains.anko.*
class SubSettingRecyclerAdapter(val activity: SubSettingActivity) : RecyclerView.Adapter<SubSettingRecyclerAdapter.BaseViewHolder>() {
@@ -28,17 +29,19 @@ class SubSettingRecyclerAdapter(val activity: SubSettingActivity) : RecyclerView
holder.name.text = remarks
holder.url.text = url
holder.itemView.backgroundColor = Color.TRANSPARENT
holder.itemView.setBackgroundColor(Color.TRANSPARENT)
holder.layout_edit.setOnClickListener {
mActivity.startActivity<SubEditActivity>("position" to position)
mActivity.startActivity(Intent(mActivity, SubEditActivity::class.java)
.putExtra("position", position)
)
}
} else {
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
return MainViewHolder(parent.context.layoutInflater
return MainViewHolder(LayoutInflater.from(parent.context)
.inflate(R.layout.item_recycler_sub_setting, parent, false))
}

View File

@@ -24,18 +24,17 @@ 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.toast
import com.v2ray.ang.extension.v2RayApplication
import com.v2ray.ang.service.V2RayServiceManager
import com.v2ray.ang.ui.SettingsActivity
import kotlinx.coroutines.isActive
import me.dozen.dpreference.DPreference
import org.jetbrains.anko.toast
import java.io.IOException
import java.net.*
import libv2ray.Libv2ray
import kotlin.coroutines.coroutineContext
object Utils {
val tcpTestingSockets = ArrayList<Socket?>()

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:onClick="onModeHelpClicked"
android:text="@string/title_mode_help"
android:textAlignment="textStart"
android:textStyle="italic" />

View File

@@ -17,17 +17,6 @@
<copyright>Copyright(C) 2008-2011 The Android Open Source Project</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>Apache Commons Validator</name>
<url>http://commons.apache.org/proper/commons-collections/</url>
<copyright>Copyright(C) 2001-2014 The Apache Software Foundation</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>anko</name>
<url>https://github.com/Kotlin/anko</url>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>Google Gson</name>
<url>https://github.com/google/gson</url>
@@ -52,33 +41,9 @@
<copyright>Copyright 2015 Square, Inc.</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>ReactiveNetwork</name>
<url>https://github.com/pwittchen/ReactiveNetwork</url>
<copyright>Copyright 2016 Piotr Wittchen</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>RecyclerItemDecoration</name>
<url>https://github.com/dinuscxj/RecyclerItemDecoration</url>
<copyright>Copyright 2015-2019 dinus</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>RxKotlin</name>
<url>https://github.com/ReactiveX/RxKotlin</url>
<copyright>Copyright 2012 Netflix, Inc.</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>RxPermissions</name>
<url>https://github.com/tbruyelle/RxPermissions</url>
<license>Apache Software License 2.0</license>
</notice>
<notice>
<name>RecyclerItemDecoration</name>
<url>https://github.com/dinuscxj/RecyclerItemDecoration</url>
<copyright>Copyright 2015-2019 dinus</copyright>
<license>Apache Software License 2.0</license>
</notice>
</notices>
</notices>

View File

@@ -123,6 +123,7 @@
<string name="summary_pref_promotion">一些推广,点击查看详情(捐赠可去除)</string>
<string name="title_mode">模式</string>
<string name="title_mode_help">点此查看更多帮助</string>
<string name="donate_error_setup">初始化错误:</string>
<string name="donate_error_inventory">无法查询到项目</string>

View File

@@ -125,6 +125,7 @@
<string name="summary_pref_promotion">一些推廣,點擊查看詳情(捐款可去除)</string>
<string name="title_mode">模式</string>
<string name="title_mode_help">點此查看更多幫助</string>
<string name="donate_error_setup">錯誤設定:</string>
<string name="donate_error_inventory">Error querying inventory</string>

View File

@@ -125,6 +125,7 @@
<string name="summary_pref_promotion">Promotion,click for details(Donation can be removed)</string>
<string name="title_mode">Mode</string>
<string name="title_mode_help">Click me for more help</string>
<string name="donate_error_setup">Error Setup:</string>
<string name="donate_error_inventory">Error querying inventory</string>

View File

@@ -7,7 +7,7 @@ buildscript {
maven { url 'https://maven.google.com' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.3'
classpath 'com.android.tools.build:gradle:4.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
// NOTE: Do not place your application dependencies here; they belong

View File

@@ -19,7 +19,7 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
testImplementation 'junit:junit:4.12'
testImplementation 'junit:junit:4.13'
implementation "com.android.support:support-annotations:$supportLibVersion"
implementation 'com.google.code.gson:gson:2.7'
implementation 'com.google.code.gson:gson:2.8.6'
}

View File

@@ -13,8 +13,7 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryErro
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Fri Jun 02 14:08:42 CST 2017
ankoVersion=0.10.8
kotlinVersion=1.3.40
kotlinVersion=1.4.0
supportLibVersion=28.0.0
buildToolsVer=29.0.3
compileSdkVer=29