Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45805d6df7 | ||
|
|
4437e6699b | ||
|
|
fa409f91e4 | ||
|
|
89be5f077b | ||
|
|
896889778f | ||
|
|
10f705a8b2 | ||
|
|
2956fa2030 | ||
|
|
c2a704a6ea | ||
|
|
78cac0cd90 | ||
|
|
3ffb2e8e05 | ||
|
|
e2d667e0bb | ||
|
|
3ae0777d7f | ||
|
|
5e6348676c | ||
|
|
df3f1ca3ef | ||
|
|
94f2bec329 | ||
|
|
c54d8fa43a | ||
|
|
5bbbdcf6f2 | ||
|
|
4abf20fa32 | ||
|
|
723727feb9 | ||
|
|
2efd4b741c | ||
|
|
83aab0f880 |
@@ -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
|
||||||
|
|||||||
@@ -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
|
popd
|
||||||
|
|
||||||
pushd $__dir/shippedBinarys
|
rm -rf $TMPDIR
|
||||||
make clean && make shippedBinary
|
|
||||||
popd
|
|
||||||
|
|
||||||
rm -rf $TMPDIR
|
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -227,12 +226,6 @@ 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"),
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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*
|
|
||||||
@@ -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()
|
|
||||||
}
|
|
||||||
20
README.md
20
README.md
@@ -1,5 +1,25 @@
|
|||||||
# v2rayNG
|
# v2rayNG
|
||||||
|
|
||||||
|
A V2Ray client for Android
|
||||||
|
|
||||||
|
[](https://developer.android.com/about/versions/jelly-bean#android-4.2)
|
||||||
|
[](https://kotlinlang.org)
|
||||||
|
[](https://github.com/2dust/v2rayNG/commits/master)
|
||||||
|
[](https://www.codefactor.io/repository/github/2dust/v2rayng)
|
||||||
|
[](https://github.com/2dust/v2rayNG/releases)
|
||||||
|
|
||||||
<a href="https://play.google.com/store/apps/details?id=com.v2ray.ang">
|
<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" />
|
<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>
|
</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
|
||||||
|
|||||||
@@ -62,14 +62,13 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
testImplementation 'junit:junit:4.13'
|
||||||
testImplementation 'junit:junit:4.12'
|
|
||||||
implementation project(':dpreference')
|
implementation project(':dpreference')
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.2"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.2" // 1.3.x has compile error:
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9"
|
||||||
// More than one file was found with OS independent path 'META-INF/proguard/coroutines.pro'
|
|
||||||
|
|
||||||
// Android support library
|
// Android support library
|
||||||
implementation "com.android.support:support-v4:$supportLibVersion"
|
implementation "com.android.support:support-v4:$supportLibVersion"
|
||||||
@@ -79,22 +78,16 @@ dependencies {
|
|||||||
implementation "com.android.support:preference-v7:$supportLibVersion"
|
implementation "com.android.support:preference-v7:$supportLibVersion"
|
||||||
implementation "com.android.support:recyclerview-v7:$supportLibVersion"
|
implementation "com.android.support:recyclerview-v7:$supportLibVersion"
|
||||||
implementation "com.android.support:multidex:1.0.3"
|
implementation "com.android.support:multidex:1.0.3"
|
||||||
|
implementation 'com.android.support.constraint:constraint-layout:2.0.1'
|
||||||
|
|
||||||
// DSL
|
// DSL
|
||||||
implementation "org.jetbrains.anko:anko-sdk15:$ankoVersion"
|
implementation 'com.google.code.gson:gson:2.8.6'
|
||||||
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 '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 'com.android.support:multidex:1.0.3'
|
|
||||||
|
|
||||||
implementation(name: 'libv2ray', ext: 'aar')
|
implementation(name: 'libv2ray', ext: 'aar')
|
||||||
//implementation(name: 'tun2socks', ext: 'aar')
|
//implementation(name: 'tun2socks', ext: 'aar')
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ object AppConfig {
|
|||||||
const val androidpackagenamelistUrl = "https://raw.githubusercontent.com/2dust/androidpackagenamelist/master/proxy.txt"
|
const val androidpackagenamelistUrl = "https://raw.githubusercontent.com/2dust/androidpackagenamelist/master/proxy.txt"
|
||||||
const val v2rayCustomRoutingListUrl = "https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/"
|
const val v2rayCustomRoutingListUrl = "https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/"
|
||||||
const val v2rayNGIssues = "https://github.com/2dust/v2rayNG/issues"
|
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 promotionUrl = "https://1.2345345.xyz/ads.html"
|
||||||
|
|
||||||
const val DNS_AGENT = "1.1.1.1"
|
const val DNS_AGENT = "1.1.1.1"
|
||||||
|
|||||||
@@ -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) }
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ object V2RayServiceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun protect(l: Long): Long {
|
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
|
return if (serviceControl.vpnProtect(l.toInt())) 0 else 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
* 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()
|
NetworkRequest.Builder()
|
||||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
|
.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 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() {
|
object : ConnectivityManager.NetworkCallback() {
|
||||||
override fun onAvailable(network: Network) {
|
override fun onAvailable(network: Network) {
|
||||||
setUnderlyingNetworks(arrayOf(network))
|
setUnderlyingNetworks(arrayOf(network))
|
||||||
@@ -56,8 +60,6 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var listeningForDefaultNetwork = false
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
@@ -151,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) {
|
||||||
connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
|
try {
|
||||||
listeningForDefaultNetwork = true
|
connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
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.
|
// Create a new interface using the builder and save the parameters.
|
||||||
mInterface = builder.establish()
|
try {
|
||||||
sendFd()
|
mInterface = builder.establish()!!
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// non-nullable lateinit var
|
||||||
|
e.printStackTrace()
|
||||||
|
stopV2Ray()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendFd() {
|
private fun sendFd() {
|
||||||
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(50L shl tries)
|
||||||
@@ -198,9 +208,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) {
|
||||||
connectivity.unregisterNetworkCallback(defaultNetworkCallback)
|
try {
|
||||||
listeningForDefaultNetwork = false
|
connectivity.unregisterNetworkCallback(defaultNetworkCallback)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
V2RayServiceManager.stopV2rayPoint()
|
V2RayServiceManager.stopV2rayPoint()
|
||||||
|
|||||||
@@ -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 -> {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import android.view.KeyEvent
|
|||||||
import com.v2ray.ang.AppConfig
|
import com.v2ray.ang.AppConfig
|
||||||
import com.v2ray.ang.util.MessageUtil
|
import com.v2ray.ang.util.MessageUtil
|
||||||
import com.v2ray.ang.util.V2rayConfigUtil
|
import com.v2ray.ang.util.V2rayConfigUtil
|
||||||
import org.jetbrains.anko.*
|
|
||||||
import java.lang.ref.SoftReference
|
import java.lang.ref.SoftReference
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
@@ -30,7 +29,7 @@ import android.util.Log
|
|||||||
import com.v2ray.ang.BuildConfig
|
import com.v2ray.ang.BuildConfig
|
||||||
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 com.v2ray.ang.InappBuyActivity
|
import com.v2ray.ang.extension.toast
|
||||||
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
|
||||||
@@ -52,10 +51,10 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
|||||||
field = value
|
field = value
|
||||||
adapter.changeable = !value
|
adapter.changeable = !value
|
||||||
if (value) {
|
if (value) {
|
||||||
fab.imageResource = R.drawable.ic_v
|
fab.setImageResource(R.drawable.ic_v)
|
||||||
tv_test_state.text = getString(R.string.connection_connected)
|
tv_test_state.text = getString(R.string.connection_connected)
|
||||||
} else {
|
} 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)
|
tv_test_state.text = getString(R.string.connection_not_connected)
|
||||||
}
|
}
|
||||||
hideCircle()
|
hideCircle()
|
||||||
@@ -63,7 +62,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
|||||||
|
|
||||||
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 tcpingTestScope by lazy { CoroutineScope(Dispatchers.IO) }
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -90,9 +89,9 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
|||||||
val socksPort = 10808//Utils.parseInt(defaultDPreference.getPrefString(SettingsActivity.PREF_SOCKS_PORT, "10808"))
|
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 {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
val result = Utils.testConnection(this@MainActivity, socksPort)
|
val result = Utils.testConnection(this@MainActivity, socksPort)
|
||||||
uiThread {
|
launch(Dispatchers.Main) {
|
||||||
tv_test_state.text = Utils.getEditable(result)
|
tv_test_state.text = Utils.getEditable(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,6 +187,9 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getOptionIntent() = Intent().putExtra("position", -1)
|
||||||
|
.putExtra("isRunning", isRunning)
|
||||||
|
|
||||||
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 +200,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,10 +251,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
|||||||
}
|
}
|
||||||
|
|
||||||
R.id.ping_all -> {
|
R.id.ping_all -> {
|
||||||
testingJobs.forEach {
|
tcpingTestScope.coroutineContext[Job]?.cancelChildren()
|
||||||
it.cancel()
|
|
||||||
}
|
|
||||||
testingJobs.clear()
|
|
||||||
Utils.closeAllTcpSockets()
|
Utils.closeAllTcpSockets()
|
||||||
for (k in 0 until configs.vmess.count()) {
|
for (k in 0 until configs.vmess.count()) {
|
||||||
configs.vmess[k].testResult = ""
|
configs.vmess[k].testResult = ""
|
||||||
@@ -267,16 +266,14 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
|||||||
serverAddress = serverOutbound.getServerAddress() ?: continue
|
serverAddress = serverOutbound.getServerAddress() ?: continue
|
||||||
serverPort = serverOutbound.getServerPort() ?: 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
|
configs.vmess.getOrNull(k)?.let { // check null in case array is modified during testing
|
||||||
it.testResult = Utils.tcping(serverAddress, serverPort)
|
it.testResult = Utils.tcping(serverAddress, serverPort)
|
||||||
val myJob = coroutineContext[Job]
|
|
||||||
launch(Dispatchers.Main) {
|
launch(Dispatchers.Main) {
|
||||||
testingJobs.remove(myJob)
|
|
||||||
adapter.updateSelectedItem(k)
|
adapter.updateSelectedItem(k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@@ -306,7 +303,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 +389,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 +428,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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -574,10 +581,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", isRunning))
|
||||||
}
|
}
|
||||||
R.id.feedback -> {
|
R.id.feedback -> {
|
||||||
Utils.openUri(this, AppConfig.v2rayNGIssues)
|
Utils.openUri(this, AppConfig.v2rayNGIssues)
|
||||||
@@ -589,7 +597,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)
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -276,4 +282,4 @@ class PerAppProxyActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -94,4 +92,4 @@ class PerAppProxyAdapter(val activity: BaseActivity, val apps: List<AppInfo>, bl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,10 +43,10 @@ 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()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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,17 +112,16 @@ 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()
|
||||||
} else {
|
} else {
|
||||||
toast(R.string.toast_failure)
|
toast(R.string.toast_failure)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
.show()
|
||||||
show()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -158,4 +157,4 @@ class Server2Activity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,17 +126,16 @@ 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()
|
||||||
} else {
|
} else {
|
||||||
toast(R.string.toast_failure)
|
toast(R.string.toast_failure)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
.show()
|
||||||
show()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -172,4 +171,4 @@ class Server3Activity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,17 +110,16 @@ 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()
|
||||||
} else {
|
} else {
|
||||||
toast(R.string.toast_failure)
|
toast(R.string.toast_failure)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
.show()
|
||||||
show()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -156,4 +155,4 @@ class Server4Activity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,17 +169,16 @@ 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()
|
||||||
} else {
|
} else {
|
||||||
toast(R.string.toast_failure)
|
toast(R.string.toast_failure)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
.show()
|
||||||
show()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -215,4 +214,4 @@ class ServerActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +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 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 {
|
||||||
@@ -70,7 +70,7 @@ class SettingsActivity : BaseActivity() {
|
|||||||
// val feedback: Preference by lazy { findPreference(PREF_FEEDBACK) }
|
// val feedback: Preference by lazy { findPreference(PREF_FEEDBACK) }
|
||||||
// val tgGroup: Preference by lazy { findPreference(PREF_TG_GROUP) }
|
// 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() {
|
private fun restartProxy() {
|
||||||
Utils.stopVService(requireContext())
|
Utils.stopVService(requireContext())
|
||||||
@@ -88,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
|
||||||
}
|
}
|
||||||
@@ -125,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,6 +164,7 @@ class SettingsActivity : BaseActivity() {
|
|||||||
updatePerAppProxy(newValue.toString())
|
updatePerAppProxy(newValue.toString())
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
mode.dialogLayoutResource = R.layout.preference_with_help_link
|
||||||
|
|
||||||
// donate.onClick {
|
// donate.onClick {
|
||||||
// startActivity<InappBuyActivity>()
|
// startActivity<InappBuyActivity>()
|
||||||
@@ -204,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
|
||||||
@@ -221,14 +223,18 @@ 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onModeHelpClicked(view: View) {
|
||||||
|
Utils.openUri(this, AppConfig.v2rayNGWikiMode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,17 +95,16 @@ 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()
|
||||||
} else {
|
} else {
|
||||||
toast(R.string.toast_failure)
|
toast(R.string.toast_failure)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
.show()
|
||||||
show()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -135,4 +134,4 @@ class SubEditActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
@@ -48,4 +50,4 @@ class SubSettingActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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?>()
|
||||||
|
|||||||
@@ -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" />
|
||||||
@@ -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>
|
</notices>
|
||||||
<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>
|
|
||||||
|
|||||||
@@ -123,6 +123,7 @@
|
|||||||
<string name="summary_pref_promotion">一些推广,点击查看详情(捐赠可去除)</string>
|
<string name="summary_pref_promotion">一些推广,点击查看详情(捐赠可去除)</string>
|
||||||
|
|
||||||
<string name="title_mode">模式</string>
|
<string name="title_mode">模式</string>
|
||||||
|
<string name="title_mode_help">点此查看更多帮助</string>
|
||||||
|
|
||||||
<string name="donate_error_setup">初始化错误:</string>
|
<string name="donate_error_setup">初始化错误:</string>
|
||||||
<string name="donate_error_inventory">无法查询到项目</string>
|
<string name="donate_error_inventory">无法查询到项目</string>
|
||||||
|
|||||||
@@ -125,6 +125,7 @@
|
|||||||
<string name="summary_pref_promotion">一些推廣,點擊查看詳情(捐款可去除)</string>
|
<string name="summary_pref_promotion">一些推廣,點擊查看詳情(捐款可去除)</string>
|
||||||
|
|
||||||
<string name="title_mode">模式</string>
|
<string name="title_mode">模式</string>
|
||||||
|
<string name="title_mode_help">點此查看更多幫助</string>
|
||||||
|
|
||||||
<string name="donate_error_setup">錯誤設定:</string>
|
<string name="donate_error_setup">錯誤設定:</string>
|
||||||
<string name="donate_error_inventory">Error querying inventory</string>
|
<string name="donate_error_inventory">Error querying inventory</string>
|
||||||
|
|||||||
@@ -125,6 +125,7 @@
|
|||||||
<string name="summary_pref_promotion">Promotion,click for details(Donation can be removed)</string>
|
<string name="summary_pref_promotion">Promotion,click for details(Donation can be removed)</string>
|
||||||
|
|
||||||
<string name="title_mode">Mode</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_setup">Error Setup:</string>
|
||||||
<string name="donate_error_inventory">Error querying inventory</string>
|
<string name="donate_error_inventory">Error querying inventory</string>
|
||||||
|
|||||||
@@ -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:3.1.3'
|
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||||
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
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
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.android.support:support-annotations:$supportLibVersion"
|
||||||
implementation 'com.google.code.gson:gson:2.7'
|
implementation 'com.google.code.gson:gson:2.8.6'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
# 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.0
|
||||||
kotlinVersion=1.3.40
|
|
||||||
supportLibVersion=28.0.0
|
supportLibVersion=28.0.0
|
||||||
buildToolsVer=29.0.3
|
buildToolsVer=29.0.3
|
||||||
compileSdkVer=29
|
compileSdkVer=29
|
||||||
|
|||||||
Reference in New Issue
Block a user