Compare commits

...

44 Commits

Author SHA1 Message Date
2dust
50d9057f1a Merge pull request #750 from yuhan6665/viewmodel-test
Add ViewModel
2020-11-16 13:22:08 +08:00
2dust
2a563e7884 Merge pull request #747 from liyufan/new_template
Use new issue template
2020-11-16 13:21:40 +08:00
2dust
c69cd18842 Merge pull request #732 from rurirei/isTun2socksRunningi
isTun2socksRunning bool
2020-11-16 13:20:48 +08:00
2dust
7f2ced85a8 Merge pull request #730 from rurirei/stoploop
stoploop update
2020-11-16 13:18:46 +08:00
yuhan6665
6c5eef99b5 Move tests and broadcast listener to ViewModel 2020-11-15 18:37:46 -05:00
yuhan6665
d7c3bae8cc Add MainViewModel
ViewModel is the recommend approach for asynchronous loading
for Activity.
The variable stays even if the Activity is killed temporarily.
2020-11-15 18:37:46 -05:00
LYF
57c98f7c50 Use new issue template 2020-11-13 22:21:35 +08:00
rurirei
49be23c56a bool in return 2020-11-08 11:40:02 +08:00
rurirei
9b658e9a22 IsTun2socksRunning bool 2020-11-08 11:34:49 +08:00
rurirei
aaa84d081f stoploop update 2020-11-08 10:53:23 +08:00
2dust
5628cbee3a Merge pull request #725 from mzz2017/patch-1
fix: the problem that importing SS URL not support standard format
2020-11-05 14:30:56 +08:00
2dust
3dd663d927 Merge pull request #698 from yuhan6665/master
Release AndroidLibV2rayLite 22
2020-11-05 14:30:41 +08:00
mzz
9e49a2dbd9 fix: the problem that importing SS URL not support standard format 2020-11-02 12:37:26 +08:00
2dust
6c199c1687 Merge pull request #662 from yuhan6665/ext-geo
Add external geofile replacement help
2020-10-24 13:35:21 +08:00
yuhan6665
39af5fdb86 Release AndroidLibV2rayLite 22 2020-10-21 21:31:23 -04:00
2dust
7b2794f6be Merge pull request #695 from rurirei/proxyOnly
proxyOnly update
2020-10-22 07:59:19 +08:00
2dust
411d9e5c9a Merge pull request #691 from rurirei/api30
target 30
2020-10-22 07:58:41 +08:00
Rurirei
a57aee9424 proxyOnly update
* do not run Tun2socks under proxyOnly
2020-10-21 15:19:55 +08:00
Rurirei
4602afc67e call stopV2ray on onDestroy 2020-10-21 15:14:44 +08:00
Rurirei
ceb29840f2 BuildTools 30 fix 2020-10-20 09:49:16 +08:00
Rurirei
1c1f130ca7 update badge 2020-10-20 09:42:48 +08:00
Rurirei
afa0eb9375 package visibility 2020-10-20 07:20:37 +08:00
Rurirei
49b682f0f3 target 30
* update dependencies
2020-10-20 07:10:19 +08:00
Rurirei
d5def3bf2f useless anko 2020-10-20 07:06:36 +08:00
2dust
51b97b64f2 Merge pull request #670 from yuhan6665/fix-gson
Fix crash when custom config cannot be parsed by Gson
2020-10-15 08:18:59 +08:00
2dust
3af9ce1a1a Merge pull request #657 from rurirei/native
native fixes
2020-10-15 08:18:48 +08:00
yuhan6665
a5d3dda941 Fix crash when custom config cannot be parsed by Gson 2020-10-14 11:28:32 -04:00
yuhan6665
71a3e300d8 Add external geofile replacement help 2020-10-09 21:34:15 -04:00
Rurirei
030b9a3900 native fixes
* call sendFd() before tun2socks start
2020-10-08 15:50:51 +08:00
Rurirei
24d105a53c catch logs to checkout this error 2020-10-08 15:49:30 +08:00
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
yuhan6665
94f2bec329 Clean up tun2socks 2020-09-27 23:17:47 -04:00
49 changed files with 466 additions and 537 deletions

View File

@@ -1,3 +1,8 @@
---
name: v2rayNG程序问题
about: 创建一个报告来帮助我们改进
---
在提出问题前请先自行排除服务器端问题,同时也请通过搜索确认是否有人提出过相同问题。 在提出问题前请先自行排除服务器端问题,同时也请通过搜索确认是否有人提出过相同问题。
@@ -14,7 +19,8 @@
### 日志信息 ### 日志信息
<details> <details>
通过 `adb logcat -s com.v2ray.ang GoLog V2rayConfigUtilGoLog Main` 获取日志。请自行删减日志中可能出现的敏感信息。
通过`adb logcat -s com.v2ray.ang GoLog V2rayConfigUtilGoLog Main`获取日志。请自行删减日志中可能出现的敏感信息。
如果问题可重现,建议先执行`adb logcat -c`清空系统日志再执行上述命令,再操作重现问题。 如果问题可重现,建议先执行`adb logcat -c`清空系统日志再执行上述命令,再操作重现问题。
``` ```

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: V2Ray程序问题
url: https://github.com/v2fly/v2ray-core/
about: 如果您有V2Ray而非v2rayNG的问题请至这个链接讨论。

View File

@@ -6,6 +6,7 @@ import (
type Status struct { type Status struct {
IsRunning bool IsRunning bool
IsTRunning bool
PackageName string PackageName string
PackageCodePath string PackageCodePath string
@@ -13,7 +14,7 @@ type Status struct {
} }
func CheckVersion() int { func CheckVersion() int {
return 21 return 22
} }
func (v *Status) GetDataDir() string { func (v *Status) GetDataDir() string {

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

View File

@@ -3,14 +3,13 @@ package Escort
import ( import (
"os" "os"
"os/exec" "os/exec"
"time"
"log" "log"
"github.com/2dust/AndroidLibV2rayLite/CoreI" "github.com/2dust/AndroidLibV2rayLite/CoreI"
) )
func (v *Escorting) EscortRun(proc string, pt []string, additionalEnv string, sendFd func() int) { func (v *Escorting) EscortRun(proc string, pt []string, additionalEnv string) {
log.Println(proc, pt) log.Println(proc, pt)
count := 0 count := 0
for count <= 42 { for count <= 42 {
@@ -37,13 +36,6 @@ func (v *Escorting) EscortRun(proc string, pt []string, additionalEnv string, se
*v.escortProcess = append(*v.escortProcess, cmd.Process) *v.escortProcess = append(*v.escortProcess, cmd.Process)
log.Println("EscortRun Waiting....") log.Println("EscortRun Waiting....")
if count > 0 {
go func() {
time.Sleep(time.Second)
sendFd()
}()
}
if err := cmd.Wait(); err != nil { if err := cmd.Wait(); err != nil {
log.Println("EscortRun cmd.Wait err:", err) log.Println("EscortRun cmd.Wait err:", err)
} }

View File

@@ -34,14 +34,10 @@ $NDK_HOME/ndk-build \
NDK_OUT=$TMPDIR/tmp \ NDK_OUT=$TMPDIR/tmp \
APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -j4 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/armeabi-v7a/tun2socks $__dir/../V2rayNG/app/src/main/jniLibs/armeabi-v7a/libtun2socks.so
install -v -m755 libs/arm64-v8a/tun2socks $__dir/shippedBinarys/ArchDep/arm64/ install -v -m755 libs/arm64-v8a/tun2socks $__dir/../V2rayNG/app/src/main/jniLibs/arm64-v8a/libtun2socks.so
install -v -m755 libs/x86/tun2socks $__dir/shippedBinarys/ArchDep/386/ install -v -m755 libs/x86/tun2socks $__dir/../V2rayNG/app/src/main/jniLibs/x86/libtun2socks.so
install -v -m755 libs/x86_64/tun2socks $__dir/shippedBinarys/ArchDep/amd64/ 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 popd
rm -rf $TMPDIR rm -rf $TMPDIR

View File

@@ -11,7 +11,6 @@ import (
"github.com/2dust/AndroidLibV2rayLite/CoreI" "github.com/2dust/AndroidLibV2rayLite/CoreI"
"github.com/2dust/AndroidLibV2rayLite/Process/Escort" "github.com/2dust/AndroidLibV2rayLite/Process/Escort"
"github.com/2dust/AndroidLibV2rayLite/VPN" "github.com/2dust/AndroidLibV2rayLite/VPN"
"github.com/2dust/AndroidLibV2rayLite/shippedBinarys"
mobasset "golang.org/x/mobile/asset" mobasset "golang.org/x/mobile/asset"
v2core "v2ray.com/core" v2core "v2ray.com/core"
@@ -49,6 +48,7 @@ type V2RayPoint struct {
ConfigureFileContent string ConfigureFileContent string
EnableLocalDNS bool EnableLocalDNS bool
ForwardIpv6 bool ForwardIpv6 bool
ProxyOnly bool
} }
/*V2RayVPNServiceSupportsSet To support Android VPN mode*/ /*V2RayVPNServiceSupportsSet To support Android VPN mode*/
@@ -58,7 +58,6 @@ type V2RayVPNServiceSupportsSet interface {
Shutdown() int Shutdown() int
Protect(int) int Protect(int) int
OnEmitStatus(int, string) int OnEmitStatus(int, string) int
SendFd() int
} }
/*RunLoop Run V2Ray main loop /*RunLoop Run V2Ray main loop
@@ -82,7 +81,6 @@ func (v *V2RayPoint) RunLoop() (err error) {
if !v.dialer.IsVServerReady() { if !v.dialer.IsVServerReady() {
log.Println("vServer cannot resolved, shutdown") log.Println("vServer cannot resolved, shutdown")
v.StopLoop() v.StopLoop()
v.SupportSet.Shutdown()
} }
// stop waiting if manually closed // stop waiting if manually closed
@@ -101,9 +99,7 @@ func (v *V2RayPoint) StopLoop() (err error) {
v.v2rayOP.Lock() v.v2rayOP.Lock()
defer v.v2rayOP.Unlock() defer v.v2rayOP.Unlock()
if v.status.IsRunning { if v.status.IsRunning {
close(v.closeChan)
v.shutdownInit() v.shutdownInit()
v.SupportSet.OnEmitStatus(0, "Closed")
} }
return return
} }
@@ -113,6 +109,10 @@ func (v *V2RayPoint) GetIsRunning() bool {
return v.status.IsRunning return v.status.IsRunning
} }
func (v *V2RayPoint) GetIsTRunning() bool {
return v.status.IsTRunning
}
//Delegate Funcation //Delegate Funcation
func (v V2RayPoint) QueryStats(tag string, direct string) int64 { func (v V2RayPoint) QueryStats(tag string, direct string) int64 {
if v.statsManager == nil { if v.statsManager == nil {
@@ -126,24 +126,19 @@ func (v V2RayPoint) QueryStats(tag string, direct string) int64 {
} }
func (v *V2RayPoint) shutdownInit() { func (v *V2RayPoint) shutdownInit() {
v.status.IsRunning = false close(v.closeChan)
v.statsManager = nil
v.status.Vpoint.Close() v.status.Vpoint.Close()
v.status.Vpoint = nil v.status.Vpoint = nil
v.statsManager = nil v.status.IsRunning = false
v.escorter.EscortingDown() v.escorter.EscortingDown()
v.SupportSet.Shutdown()
v.SupportSet.OnEmitStatus(0, "Closed")
} }
func (v *V2RayPoint) pointloop() error { func (v *V2RayPoint) pointloop() error {
if err := v.runTun2socks(); err != nil {
log.Println(err)
return err
}
log.Printf("EnableLocalDNS: %v\nForwardIpv6: %v\nDomainName: %s",
v.EnableLocalDNS,
v.ForwardIpv6,
v.DomainName)
log.Println("loading v2ray config") log.Println("loading v2ray config")
config, err := v2serial.LoadJSONConfig(strings.NewReader(v.ConfigureFileContent)) config, err := v2serial.LoadJSONConfig(strings.NewReader(v.ConfigureFileContent))
if err != nil { if err != nil {
@@ -171,6 +166,21 @@ func (v *V2RayPoint) pointloop() error {
v.SupportSet.Prepare() v.SupportSet.Prepare()
v.SupportSet.Setup(v.status.GetVPNSetupArg(v.EnableLocalDNS, v.ForwardIpv6)) v.SupportSet.Setup(v.status.GetVPNSetupArg(v.EnableLocalDNS, v.ForwardIpv6))
v.SupportSet.OnEmitStatus(0, "Running") 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,
v.ForwardIpv6,
v.DomainName)
}
return nil return nil
} }
@@ -227,17 +237,10 @@ func NewV2RayPoint(s V2RayVPNServiceSupportsSet) *V2RayPoint {
} }
func (v V2RayPoint) runTun2socks() error { 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() v.escorter.EscortingUp()
go v.escorter.EscortRun( go v.escorter.EscortRun(
v.status.GetApp("libtun2socks.so"), v.status.GetApp("libtun2socks.so"),
v.status.GetTun2socksArgs(v.EnableLocalDNS, v.ForwardIpv6), "", v.status.GetTun2socksArgs(v.EnableLocalDNS, v.ForwardIpv6), "")
v.SupportSet.SendFd)
return nil return nil
} }

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

@@ -3,7 +3,7 @@
A V2Ray client for Android 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) [![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) [![Kotlin Version](https://img.shields.io/badge/Kotlin-1.4.10-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) [![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) [![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) [![GitHub Releases](https://img.shields.io/github/downloads/2dust/v2rayNG/latest/total?logo=github)](https://github.com/2dust/v2rayNG/releases)
@@ -14,7 +14,16 @@ A V2Ray client for Android
### Usage ### Usage
See our [wiki](https://github.com/2dust/v2rayNG/wiki) #### Geoip and Geosite
v2rayNG release already embedded domain file `geoip.dat` and `geosite.dat`. However it is (probably) not the latest and not the most complete list.
For power user, the embedded files can be easily replaced with the following steps:
1. Launch v2rayNG (v1.4.9+)
2. Find existing geoip.dat and geosite.dat in `Android/data/com.v2ray.ang/files/assets` (path may differ on some Android device)
3. Replace them with the latest [domain list](https://github.com/v2fly/domain-list-community) and [ip list](https://github.com/v2fly/geoip)
4. Enhanced version can be found in this [repo](https://github.com/Loyalsoldier/v2ray-rules-dat) (recommend to use `geosite:geolocation-!cn` for proxy dns and routing)
5. It is also possible to use third party dat file in the same folder, like [h2y](https://guide.v2fly.org/routing/sitedata.html#%E5%A4%96%E7%BD%AE%E7%9A%84%E5%9F%9F%E5%90%8D%E6%96%87%E4%BB%B6)
#### See more in our [wiki](https://github.com/2dust/v2rayNG/wiki)
### Development guide ### Development guide

View File

@@ -38,6 +38,10 @@ android {
main.java.srcDirs += 'src/main/kotlin' main.java.srcDirs += 'src/main/kotlin'
} }
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
}
splits { splits {
abi { abi {
enable true enable true
@@ -70,6 +74,10 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android: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 // Android support library
implementation "com.android.support:support-v4:$supportLibVersion" implementation "com.android.support:support-v4:$supportLibVersion"
implementation "com.android.support:appcompat-v7:$supportLibVersion" implementation "com.android.support:appcompat-v7:$supportLibVersion"
@@ -81,20 +89,13 @@ dependencies {
implementation 'com.android.support.constraint:constraint-layout:2.0.1' implementation 'com.android.support.constraint:constraint-layout:2.0.1'
// DSL // 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.6' implementation 'com.google.code.gson:gson:2.8.6'
implementation 'io.reactivex:rxjava:1.3.4' implementation 'io.reactivex:rxjava:1.3.4'
implementation 'io.reactivex:rxandroid:1.2.1' implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'com.tbruyelle.rxpermissions:rxpermissions:0.9.4@aar' 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:core:1.9.8'
implementation 'me.dm7.barcodescanner:zxing:1.9.8' implementation 'me.dm7.barcodescanner:zxing:1.9.8'
implementation 'com.github.jorgecastilloprz:fabprogresscircle:1.01@aar' implementation 'com.github.jorgecastilloprz:fabprogresscircle:1.01@aar'
implementation 'com.beust:klaxon:3.0.1'
implementation(name: 'libv2ray', ext: 'aar') implementation(name: 'libv2ray', ext: 'aar')
//implementation(name: 'tun2socks', ext: 'aar') //implementation(name: 'tun2socks', ext: 'aar')

Binary file not shown.

View File

@@ -44,9 +44,6 @@
static void throwUninitializedPropertyAccessException(java.lang.String); static void throwUninitializedPropertyAccessException(java.lang.String);
} }
-dontwarn org.jetbrains.anko.internals.**
-keep class org.jetbrains.anko.internals.** { *;}
-dontwarn rx.internal.util.unsafe.** -dontwarn rx.internal.util.unsafe.**
-keep class rx.internal.util.unsafe.** { *;} -keep class rx.internal.util.unsafe.** { *;}

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.v2ray.ang"> package="com.v2ray.ang">
<supports-screens <supports-screens
@@ -12,6 +13,11 @@
<uses-feature android:name="android.hardware.camera" android:required="false"/> <uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<!-- https://developer.android.com/about/versions/11/privacy/package-visibility -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
@@ -21,12 +27,14 @@
<uses-permission android:name="com.android.vending.BILLING" /> <uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> --> <!-- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> -->
<application <application
android:name=".AngApplication" android:name=".AngApplication"
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:supportsRtl="true" android:supportsRtl="true"
android:extractNativeLibs="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity <activity
android:name=".ui.MainActivity" android:name=".ui.MainActivity"
@@ -34,20 +42,16 @@
android:launchMode="singleTask"> android:launchMode="singleTask">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" /> <data android:mimeType="text/plain" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" /> <action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
</intent-filter> </intent-filter>
<meta-data <meta-data
android:name="android.app.shortcuts" android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" /> android:resource="@xml/shortcuts" />

View File

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

View File

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

View File

@@ -11,5 +11,4 @@ interface ServiceControl {
fun vpnProtect(socket: Int): Boolean fun vpnProtect(socket: Int): Boolean
fun vpnSendFd()
} }

View File

@@ -37,10 +37,6 @@ class V2RayProxyOnlyService : Service(), ServiceControl {
return true return true
} }
override fun vpnSendFd() {
// do nothing
}
override fun onBind(intent: Intent?): IBinder? { override fun onBind(intent: Intent?): IBinder? {
return null return null
} }

View File

@@ -111,16 +111,6 @@ object V2RayServiceManager {
} }
} }
override fun sendFd(): Long {
val serviceControl = serviceControl?.get() ?: return -1
try {
serviceControl.vpnSendFd()
} catch (e: Exception) {
Log.d(serviceControl.getService().packageName, e.toString())
return -1
}
return 0
}
} }
fun startV2rayPoint() { fun startV2rayPoint() {
@@ -141,6 +131,7 @@ object V2RayServiceManager {
v2rayPoint.enableLocalDNS = service.defaultDPreference.getPrefBoolean(SettingsActivity.PREF_LOCAL_DNS_ENABLED, false) v2rayPoint.enableLocalDNS = service.defaultDPreference.getPrefBoolean(SettingsActivity.PREF_LOCAL_DNS_ENABLED, false)
v2rayPoint.forwardIpv6 = service.defaultDPreference.getPrefBoolean(SettingsActivity.PREF_FORWARD_IPV6, false) v2rayPoint.forwardIpv6 = service.defaultDPreference.getPrefBoolean(SettingsActivity.PREF_FORWARD_IPV6, false)
v2rayPoint.domainName = service.defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG_DOMAIN, "") v2rayPoint.domainName = service.defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG_DOMAIN, "")
v2rayPoint.proxyOnly = service.defaultDPreference.getPrefString(AppConfig.PREF_MODE, "VPN") != "VPN"
try { try {
v2rayPoint.runLoop() v2rayPoint.runLoop()

View File

@@ -16,7 +16,9 @@ import com.v2ray.ang.extension.defaultDPreference
import com.v2ray.ang.ui.PerAppProxyActivity import com.v2ray.ang.ui.PerAppProxyActivity
import com.v2ray.ang.ui.SettingsActivity import com.v2ray.ang.ui.SettingsActivity
import com.v2ray.ang.util.Utils 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.io.File
import java.lang.ref.SoftReference import java.lang.ref.SoftReference
@@ -48,7 +50,7 @@ class V2RayVpnService : VpnService(), ServiceControl {
override fun onAvailable(network: Network) { override fun onAvailable(network: Network) {
setUnderlyingNetworks(arrayOf(network)) setUnderlyingNetworks(arrayOf(network))
} }
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities?) { override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
// it's a good idea to refresh capabilities // it's a good idea to refresh capabilities
setUnderlyingNetworks(arrayOf(network)) setUnderlyingNetworks(arrayOf(network))
} }
@@ -58,8 +60,6 @@ class V2RayVpnService : VpnService(), ServiceControl {
} }
} }
private var listeningForDefaultNetwork = false
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
@@ -79,7 +79,7 @@ class V2RayVpnService : VpnService(), ServiceControl {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
V2RayServiceManager.cancelNotification() stopV2Ray()
} }
private fun setup(parameters: String) { private fun setup(parameters: String) {
@@ -153,8 +153,11 @@ class V2RayVpnService : VpnService(), ServiceControl {
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback) connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
listeningForDefaultNetwork = true } catch (e: Exception) {
e.printStackTrace()
}
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
@@ -162,7 +165,14 @@ class V2RayVpnService : VpnService(), ServiceControl {
} }
// Create a new interface using the builder and save the parameters. // Create a new interface using the builder and save the parameters.
mInterface = builder.establish() try {
mInterface = builder.establish()!!
} catch (e: Exception) {
// non-nullable lateinit var
e.printStackTrace()
stopV2Ray()
}
sendFd() sendFd()
} }
@@ -170,10 +180,10 @@ class V2RayVpnService : VpnService(), ServiceControl {
val fd = mInterface.fileDescriptor val fd = mInterface.fileDescriptor
val path = File(Utils.packagePath(applicationContext), "sock_path").absolutePath val path = File(Utils.packagePath(applicationContext), "sock_path").absolutePath
doAsync { GlobalScope.launch(Dispatchers.IO) {
var tries = 0 var tries = 0
while (true) try { while (true) try {
Thread.sleep(50L shl tries) Thread.sleep(1000L shl tries)
Log.d(packageName, "sendFd tries: $tries") Log.d(packageName, "sendFd tries: $tries")
LocalSocket().use { localSocket -> LocalSocket().use { localSocket ->
localSocket.connect(LocalSocketAddress(path, LocalSocketAddress.Namespace.FILESYSTEM)) localSocket.connect(LocalSocketAddress(path, LocalSocketAddress.Namespace.FILESYSTEM))
@@ -200,9 +210,12 @@ class V2RayVpnService : VpnService(), ServiceControl {
// val emptyInfo = VpnNetworkInfo() // val emptyInfo = VpnNetworkInfo()
// val info = loadVpnNetworkInfo(configName, emptyInfo)!! + (lastNetworkInfo ?: emptyInfo) // val info = loadVpnNetworkInfo(configName, emptyInfo)!! + (lastNetworkInfo ?: emptyInfo)
// saveVpnNetworkInfo(configName, info) // saveVpnNetworkInfo(configName, info)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && listeningForDefaultNetwork) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
connectivity.unregisterNetworkCallback(defaultNetworkCallback) connectivity.unregisterNetworkCallback(defaultNetworkCallback)
listeningForDefaultNetwork = false } catch (ignored: Exception) {
// ignored
}
} }
V2RayServiceManager.stopV2rayPoint() V2RayServiceManager.stopV2rayPoint()
@@ -240,7 +253,4 @@ class V2RayVpnService : VpnService(), ServiceControl {
return protect(socket) return protect(socket)
} }
override fun vpnSendFd() {
sendFd()
}
} }

View File

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

View File

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

View File

@@ -1,43 +1,41 @@
package com.v2ray.ang.ui package com.v2ray.ang.ui
import android.Manifest import android.Manifest
import android.content.* import android.arch.lifecycle.ViewModelProviders
import android.content.Intent
import android.net.Uri import android.net.Uri
import android.net.VpnService 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.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 org.jetbrains.anko.*
import java.lang.ref.SoftReference
import java.net.URL
import android.content.IntentFilter
import android.support.design.widget.NavigationView import android.support.design.widget.NavigationView
import android.support.v4.view.GravityCompat import android.support.v4.view.GravityCompat
import android.support.v7.app.ActionBarDrawerToggle import android.support.v7.app.ActionBarDrawerToggle
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.helper.ItemTouchHelper import android.support.v7.widget.helper.ItemTouchHelper
import android.text.TextUtils
import android.util.Log 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.BuildConfig
import com.v2ray.ang.dto.EConfigType import com.v2ray.ang.R
import com.v2ray.ang.extension.defaultDPreference import com.v2ray.ang.extension.defaultDPreference
//import com.v2ray.ang.InappBuyActivity 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.Observable
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import java.net.URL
import java.util.concurrent.TimeUnit 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 { class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener {
companion object { companion object {
@@ -47,23 +45,9 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
private const val REQUEST_SCAN_URL = 3 private const val REQUEST_SCAN_URL = 3
} }
var isRunning = false
set(value) {
field = value
adapter.changeable = !value
if (value) {
fab.imageResource = R.drawable.ic_v
tv_test_state.text = getString(R.string.connection_connected)
} else {
fab.imageResource = R.drawable.ic_v_idle
tv_test_state.text = getString(R.string.connection_not_connected)
}
hideCircle()
}
private val adapter by lazy { MainRecyclerAdapter(this) } private val adapter by lazy { MainRecyclerAdapter(this) }
private var mItemTouchHelper: ItemTouchHelper? = null private var mItemTouchHelper: ItemTouchHelper? = null
private val testingJobs = ArrayList<Job>() private val mainViewModel: MainViewModel by lazy { ViewModelProviders.of(this).get(MainViewModel::class.java) }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -72,7 +56,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
setSupportActionBar(toolbar) setSupportActionBar(toolbar)
fab.setOnClickListener { fab.setOnClickListener {
if (isRunning) { if (mainViewModel.isRunning.value == true) {
Utils.stopVService(this) Utils.stopVService(this)
} else if (defaultDPreference.getPrefString(AppConfig.PREF_MODE, "VPN") == "VPN") { } else if (defaultDPreference.getPrefString(AppConfig.PREF_MODE, "VPN") == "VPN") {
val intent = VpnService.prepare(this) val intent = VpnService.prepare(this)
@@ -86,16 +70,9 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
} }
} }
layout_test.setOnClickListener { layout_test.setOnClickListener {
if (isRunning) { if (mainViewModel.isRunning.value == true) {
val socksPort = 10808//Utils.parseInt(defaultDPreference.getPrefString(SettingsActivity.PREF_SOCKS_PORT, "10808"))
tv_test_state.text = getString(R.string.connection_test_testing) tv_test_state.text = getString(R.string.connection_test_testing)
doAsync { mainViewModel.testCurrentServerRealPing()
val result = Utils.testConnection(this@MainActivity, socksPort)
uiThread {
tv_test_state.text = Utils.getEditable(result)
}
}
} else { } else {
// tv_test_state.text = getString(R.string.connection_test_fail) // tv_test_state.text = getString(R.string.connection_test_fail)
} }
@@ -116,6 +93,33 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
toggle.syncState() toggle.syncState()
nav_view.setNavigationItemSelectedListener(this) nav_view.setNavigationItemSelectedListener(this)
version.text = "v${BuildConfig.VERSION_NAME} (${Libv2ray.checkVersionX()})" 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() { fun startV2Ray() {
@@ -129,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() { public override fun onResume() {
super.onResume() super.onResume()
adapter.updateConfigList() adapter.updateConfigList()
@@ -188,6 +171,9 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
return true return true
} }
private fun getOptionIntent() = Intent().putExtra("position", -1)
.putExtra("isRunning", mainViewModel.isRunning.value == true)
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.import_qrcode -> { R.id.import_qrcode -> {
importQRcode(REQUEST_SCAN) importQRcode(REQUEST_SCAN)
@@ -198,17 +184,17 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
true true
} }
R.id.import_manually_vmess -> { R.id.import_manually_vmess -> {
startActivity<ServerActivity>("position" to -1, "isRunning" to isRunning) startActivity(getOptionIntent().setClass(this, ServerActivity::class.java))
adapter.updateConfigList() adapter.updateConfigList()
true true
} }
R.id.import_manually_ss -> { R.id.import_manually_ss -> {
startActivity<Server3Activity>("position" to -1, "isRunning" to isRunning) startActivity(getOptionIntent().setClass(this, Server3Activity::class.java))
adapter.updateConfigList() adapter.updateConfigList()
true true
} }
R.id.import_manually_socks -> { R.id.import_manually_socks -> {
startActivity<Server4Activity>("position" to -1, "isRunning" to isRunning) startActivity(getOptionIntent().setClass(this, Server4Activity::class.java))
adapter.updateConfigList() adapter.updateConfigList()
true true
} }
@@ -249,35 +235,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
} }
R.id.ping_all -> { R.id.ping_all -> {
testingJobs.forEach { mainViewModel.testAllTcping()
it.cancel()
}
testingJobs.clear()
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
}
testingJobs.add(GlobalScope.launch(Dispatchers.IO) {
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 true
} }
@@ -306,7 +264,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
.request(Manifest.permission.CAMERA) .request(Manifest.permission.CAMERA)
.subscribe { .subscribe {
if (it) if (it)
startActivityForResult<ScannerActivity>(requestCode) startActivityForResult(Intent(this, ScannerActivity::class.java), requestCode)
else else
toast(R.string.toast_permission_denied) toast(R.string.toast_permission_denied)
} }
@@ -392,9 +350,14 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
toast(R.string.toast_invalid_url) toast(R.string.toast_invalid_url)
return false return false
} }
doAsync { GlobalScope.launch(Dispatchers.IO) {
val configText = URL(url).readText() val configText = try {
uiThread { URL(url).readText()
} catch (e: Exception) {
e.printStackTrace()
""
}
launch(Dispatchers.Main) {
importCustomizeConfig(configText) importCustomizeConfig(configText)
} }
} }
@@ -426,9 +389,14 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
continue continue
} }
Log.d("Main", url) Log.d("Main", url)
doAsync { GlobalScope.launch(Dispatchers.IO) {
val configText = URL(url).readText() val configText = try {
uiThread { URL(url).readText()
} catch (e: Exception) {
e.printStackTrace()
""
}
launch(Dispatchers.Main) {
importBatchConfig(Utils.decode(configText), id) importBatchConfig(Utils.decode(configText), id)
} }
} }
@@ -507,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 { override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK) { if (keyCode == KeyEvent.KEYCODE_BACK) {
moveTaskToBack(false) moveTaskToBack(false)
@@ -574,10 +513,11 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
when (item.itemId) { when (item.itemId) {
//R.id.server_profile -> activityClass = MainActivity::class.java //R.id.server_profile -> activityClass = MainActivity::class.java
R.id.sub_setting -> { R.id.sub_setting -> {
startActivity<SubSettingActivity>() startActivity(Intent(this, SubSettingActivity::class.java))
} }
R.id.settings -> { R.id.settings -> {
startActivity<SettingsActivity>("isRunning" to isRunning) startActivity(Intent(this, SettingsActivity::class.java)
.putExtra("isRunning", mainViewModel.isRunning.value == true))
} }
R.id.feedback -> { R.id.feedback -> {
Utils.openUri(this, AppConfig.v2rayNGIssues) Utils.openUri(this, AppConfig.v2rayNGIssues)
@@ -589,7 +529,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
// startActivity<InappBuyActivity>() // startActivity<InappBuyActivity>()
} }
R.id.logcat -> { R.id.logcat -> {
startActivity<LogcatActivity>() startActivity(Intent(this, LogcatActivity::class.java))
} }
} }
drawer_layout.closeDrawer(GravityCompat.START) drawer_layout.closeDrawer(GravityCompat.START)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,23 +7,13 @@ import com.google.zxing.Result
import me.dm7.barcodescanner.zxing.ZXingScannerView import me.dm7.barcodescanner.zxing.ZXingScannerView
import android.content.Intent import android.content.Intent
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.icu.util.TimeUnit
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import com.google.zxing.BarcodeFormat import com.google.zxing.BarcodeFormat
import com.tbruyelle.rxpermissions.RxPermissions import com.tbruyelle.rxpermissions.RxPermissions
import com.v2ray.ang.R import com.v2ray.ang.R
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.QRCodeDecoder 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 { class ScannerActivity : BaseActivity(), ZXingScannerView.ResultHandler {
companion object { companion object {

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,14 +1,13 @@
package com.v2ray.ang.ui package com.v2ray.ang.ui
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v7.preference.* import android.support.v7.preference.*
import android.view.View import android.view.View
import com.v2ray.ang.R import com.v2ray.ang.R
import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.Utils import com.v2ray.ang.util.Utils
import org.jetbrains.anko.defaultSharedPreferences
import org.jetbrains.anko.startActivity
import org.jetbrains.anko.toast
class SettingsActivity : BaseActivity() { class SettingsActivity : BaseActivity() {
companion object { companion object {
@@ -89,7 +88,7 @@ class SettingsActivity : BaseActivity() {
if (isRunning()) { if (isRunning()) {
Utils.stopVService(requireContext()) Utils.stopVService(requireContext())
} }
activity?.startActivity<PerAppProxyActivity>() startActivity(Intent(activity, PerAppProxyActivity::class.java))
perAppProxy.isChecked = true perAppProxy.isChecked = true
true true
} }
@@ -126,7 +125,7 @@ class SettingsActivity : BaseActivity() {
routingCustom.setOnPreferenceClickListener { routingCustom.setOnPreferenceClickListener {
if (isRunning()) if (isRunning())
Utils.stopVService(requireContext()) Utils.stopVService(requireContext())
activity?.startActivity<RoutingSettingsActivity>() startActivity(Intent(activity, RoutingSettingsActivity::class.java))
false false
} }
@@ -206,9 +205,10 @@ class SettingsActivity : BaseActivity() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
updatePerAppProxy(activity?.defaultSharedPreferences?.getString(AppConfig.PREF_MODE, "VPN")) val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(activity)
remoteDns.summary = activity?.defaultSharedPreferences?.getString(PREF_REMOTE_DNS, "") updatePerAppProxy(defaultSharedPreferences.getString(AppConfig.PREF_MODE, "VPN"))
domesticDns.summary = activity?.defaultSharedPreferences?.getString(PREF_DOMESTIC_DNS, "") remoteDns.summary = defaultSharedPreferences.getString(PREF_REMOTE_DNS, "")
domesticDns.summary = defaultSharedPreferences.getString(PREF_DOMESTIC_DNS, "")
if (remoteDns.summary == "") { if (remoteDns.summary == "") {
remoteDns.summary = AppConfig.DNS_AGENT remoteDns.summary = AppConfig.DNS_AGENT
@@ -223,10 +223,10 @@ class SettingsActivity : BaseActivity() {
} }
private fun updatePerAppProxy(mode: String?) { private fun updatePerAppProxy(mode: String?) {
val preference = activity?.defaultSharedPreferences ?: return
if (mode == "VPN") { if (mode == "VPN") {
perAppProxy.isEnabled = true perAppProxy.isEnabled = true
perAppProxy.isChecked = preference.getBoolean(PREF_PER_APP_PROXY, false) perAppProxy.isChecked = PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(PREF_PER_APP_PROXY, false)
} else { } else {
perAppProxy.isEnabled = false perAppProxy.isEnabled = false
perAppProxy.isChecked = false perAppProxy.isChecked = false

View File

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

View File

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

View File

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

View File

@@ -318,7 +318,7 @@ object AngConfigManager {
result = Utils.decode(result) result = Utils.decode(result)
} }
val legacyPattern = "^(.+?):(.*)@(.+?):(\\d+?)$".toRegex() val legacyPattern = "^(.+?):(.*)@(.+?):(\\d+?)/?$".toRegex()
val match = legacyPattern.matchEntire(result) val match = legacyPattern.matchEntire(result)
if (match == null) { if (match == null) {
return R.string.toast_incorrect_protocol return R.string.toast_incorrect_protocol

View File

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

View File

@@ -3,9 +3,7 @@ package com.v2ray.ang.util
import android.content.Context import android.content.Context
import android.text.TextUtils import android.text.TextUtils
import android.util.Log import android.util.Log
import com.google.gson.Gson import com.google.gson.*
import com.google.gson.GsonBuilder
import com.google.gson.JsonArray
import com.v2ray.ang.AngApplication import com.v2ray.ang.AngApplication
import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig
import com.v2ray.ang.dto.AngConfig.VmessBean import com.v2ray.ang.dto.AngConfig.VmessBean
@@ -14,7 +12,6 @@ import com.v2ray.ang.ui.SettingsActivity
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
import org.json.JSONArray import org.json.JSONArray
import com.google.gson.JsonObject
import com.v2ray.ang.dto.EConfigType import com.v2ray.ang.dto.EConfigType
import com.v2ray.ang.extension.defaultDPreference import com.v2ray.ang.extension.defaultDPreference
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@@ -64,11 +61,16 @@ object V2rayConfigUtil {
if (TextUtils.isEmpty(jsonConfig)) { if (TextUtils.isEmpty(jsonConfig)) {
return null return null
} }
val v2rayConfig = Gson().fromJson(jsonConfig, V2rayConfig::class.java) ?: return null val v2rayConfig: V2rayConfig? = try {
for (outbound in v2rayConfig.outbounds) { Gson().fromJson(jsonConfig, V2rayConfig::class.java)
if (outbound.protocol.equals(EConfigType.VMESS.name.toLowerCase()) || } catch (e: JsonSyntaxException) {
outbound.protocol.equals(EConfigType.SHADOWSOCKS.name.toLowerCase()) || e.printStackTrace()
outbound.protocol.equals(EConfigType.SOCKS.name.toLowerCase())) { null
}
v2rayConfig?.outbounds?.forEach { outbound ->
if (outbound.protocol.equals(EConfigType.VMESS.name, true) ||
outbound.protocol.equals(EConfigType.SHADOWSOCKS.name, true) ||
outbound.protocol.equals(EConfigType.SOCKS.name, true)) {
return outbound return outbound
} }
} }

View File

@@ -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
}
}
}
}
}

View File

@@ -17,17 +17,6 @@
<copyright>Copyright(C) 2008-2011 The Android Open Source Project</copyright> <copyright>Copyright(C) 2008-2011 The Android Open Source Project</copyright>
<license>Apache Software License 2.0</license> <license>Apache Software License 2.0</license>
</notice> </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> <notice>
<name>Google Gson</name> <name>Google Gson</name>
<url>https://github.com/google/gson</url> <url>https://github.com/google/gson</url>
@@ -52,33 +41,9 @@
<copyright>Copyright 2015 Square, Inc.</copyright> <copyright>Copyright 2015 Square, Inc.</copyright>
<license>Apache Software License 2.0</license> <license>Apache Software License 2.0</license>
</notice> </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> <notice>
<name>RxPermissions</name> <name>RxPermissions</name>
<url>https://github.com/tbruyelle/RxPermissions</url> <url>https://github.com/tbruyelle/RxPermissions</url>
<license>Apache Software License 2.0</license> <license>Apache Software License 2.0</license>
</notice> </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

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

View File

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