diff --git a/V2rayNG/app/build.gradle b/V2rayNG/app/build.gradle
index e025b84a8..085b77a8b 100644
--- a/V2rayNG/app/build.gradle
+++ b/V2rayNG/app/build.gradle
@@ -12,7 +12,7 @@ android {
}
defaultConfig {
- applicationId "com.v2ray.ang"
+ applicationId "free.v2ray.proxy.VPN"
minSdkVersion 17
targetSdkVersion Integer.parseInt("$targetSdkVer")
multiDexEnabled true
@@ -85,6 +85,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
// Android support library
+ implementation "com.google.android.gms:play-services-ads:12.0.1"
implementation "com.android.support:support-v4:$supportLibVersion"
implementation "com.android.support:appcompat-v7:$supportLibVersion"
implementation "com.android.support:design:$supportLibVersion"
diff --git a/V2rayNG/app/src/androidTest/java/com/v2ray/ang/ApplicationTest.java b/V2rayNG/app/src/androidTest/java/com/v2ray/ang/ApplicationTest.java
deleted file mode 100644
index e221e7142..000000000
--- a/V2rayNG/app/src/androidTest/java/com/v2ray/ang/ApplicationTest.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.v2ray.ang;
-
-import android.app.Application;
-import android.test.ApplicationTestCase;
-
-/**
- * Testing Fundamentals
- */
-public class ApplicationTest extends ApplicationTestCase {
- public ApplicationTest() {
- super(Application.class);
- }
-}
\ No newline at end of file
diff --git a/V2rayNG/app/src/main/AndroidManifest.xml b/V2rayNG/app/src/main/AndroidManifest.xml
index 3fe099409..0fd5f3981 100644
--- a/V2rayNG/app/src/main/AndroidManifest.xml
+++ b/V2rayNG/app/src/main/AndroidManifest.xml
@@ -119,7 +119,9 @@
-
+
\ No newline at end of file
diff --git a/V2rayNG/app/src/main/kotlin/SpeedUpVPN/VpnEncrypt.kt b/V2rayNG/app/src/main/kotlin/SpeedUpVPN/VpnEncrypt.kt
new file mode 100644
index 000000000..2ecbb97bf
--- /dev/null
+++ b/V2rayNG/app/src/main/kotlin/SpeedUpVPN/VpnEncrypt.kt
@@ -0,0 +1,65 @@
+package SpeedUpVPN
+
+import android.os.Build
+import android.support.annotation.RequiresApi
+import android.util.Log
+import java.io.File
+import javax.crypto.Cipher
+import javax.crypto.spec.IvParameterSpec
+import javax.crypto.spec.SecretKeySpec
+
+
+object VpnEncrypt{
+ private const val theKey="your key"
+ const val vpnRemark="v2ray.vpn"
+ val vpnGroupName="SpeedUp.VPN"
+ @JvmField var builtinServersUpdated=false
+ @JvmField var builtinSubID="999"
+ @JvmStatic fun aesEncrypt(v:String, secretKey:String=theKey) = AES256.encrypt(v, secretKey)
+ @JvmStatic fun aesDecrypt(v:String, secretKey:String=theKey) = AES256.decrypt(v, secretKey)
+ @JvmStatic fun readFileAsTextUsingInputStream(fileName: String) = File(fileName).inputStream().readBytes().toString(Charsets.UTF_8)
+}
+
+
+private object AES256{
+ private fun cipher(opmode:Int, secretKey:String):Cipher{
+ if(secretKey.length != 32) throw RuntimeException("SecretKey length is not 32 chars")
+ val c = Cipher.getInstance("AES/CBC/PKCS5Padding")
+ val sk = SecretKeySpec(secretKey.toByteArray(Charsets.UTF_8), "AES")
+ val iv = IvParameterSpec(secretKey.substring(0, 16).toByteArray(Charsets.UTF_8))
+ c.init(opmode, sk, iv)
+ return c
+ }
+ fun encrypt(str:String, secretKey:String):String{
+ val encrypted = cipher(Cipher.ENCRYPT_MODE, secretKey).doFinal(str.toByteArray(Charsets.UTF_8))
+ var encstr: String
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O || isWindows())
+ encstr = java.util.Base64.getEncoder().encodeToString(encrypted)
+ else
+ encstr = android.util.Base64.encodeToString(encrypted, android.util.Base64.DEFAULT)
+
+ return encstr
+ }
+ fun decrypt(str:String, secretKey:String):String{
+ try {
+ val byteStr: ByteArray;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O || isWindows())
+ byteStr = java.util.Base64.getDecoder().decode(str.toByteArray(Charsets.UTF_8))
+ else
+ byteStr = android.util.Base64.decode(str.toByteArray(Charsets.UTF_8), android.util.Base64.DEFAULT)
+
+ return String(cipher(Cipher.DECRYPT_MODE, secretKey).doFinal(byteStr))
+ } catch (e: Exception) {
+ Log.e("VpnEncrypt","decrypt failed",e)
+ return ""
+ }
+ }
+ fun isWindows(): Boolean {
+ var os= System.getProperty("os.name")
+ if(os.isNullOrEmpty())
+ return false
+ else
+ return os.contains("Windows")
+ }
+}
+
diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt
index 9f2278db6..4ccf244ea 100644
--- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt
+++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt
@@ -5,7 +5,7 @@ package com.v2ray.ang
* App Config Const
*/
object AppConfig {
- const val ANG_PACKAGE = "com.v2ray.ang"
+ const val ANG_PACKAGE = "free.v2ray.proxy.VPN"
const val ANG_CONFIG = "ang_config"
const val PREF_CURR_CONFIG = "pref_v2ray_config"
const val PREF_CURR_CONFIG_GUID = "pref_v2ray_config_guid"
@@ -14,6 +14,7 @@ object AppConfig {
const val PREF_INAPP_BUY_IS_PREMIUM = "pref_inapp_buy_is_premium"
const val VMESS_PROTOCOL: String = "vmess://"
const val SS_PROTOCOL: String = "ss://"
+ const val SSR_PROTOCOL: String = "ssr://"
const val SOCKS_PROTOCOL: String = "socks://"
const val BROADCAST_ACTION_SERVICE = "com.v2ray.ang.action.service"
const val BROADCAST_ACTION_ACTIVITY = "com.v2ray.ang.action.activity"
@@ -34,8 +35,9 @@ object AppConfig {
const val androidpackagenamelistUrl = "https://raw.githubusercontent.com/2dust/androidpackagenamelist/master/proxy.txt"
const val v2rayCustomRoutingListUrl = "https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/"
- const val v2rayNGIssues = "https://github.com/2dust/v2rayNG/issues"
- const val promotionUrl = "https://1.2345345.xyz/ads.html"
+ const val v2rayNGIssues = "https://github.com/bannedbook/v2ray.vpn/issues"
+ const val promotionUrl = "https://lihi1.com/mWZJL"
+ const val abloutUrl = "https://github.com/bannedbook/v2ray.vpn"
const val DNS_AGENT = "1.1.1.1"
const val DNS_DIRECT = "223.5.5.5"
diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt
index 045f681e9..66ddb2229 100644
--- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt
+++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt
@@ -1,5 +1,6 @@
package com.v2ray.ang.ui
+import SpeedUpVPN.VpnEncrypt
import android.Manifest
import android.content.*
import android.net.Uri
@@ -22,6 +23,7 @@ import org.jetbrains.anko.*
import java.lang.ref.SoftReference
import java.net.URL
import android.content.IntentFilter
+import android.graphics.Color
import android.support.design.widget.NavigationView
import android.support.v4.view.GravityCompat
import android.support.v7.app.ActionBarDrawerToggle
@@ -33,6 +35,7 @@ import rx.android.schedulers.AndroidSchedulers
import java.util.concurrent.TimeUnit
import com.v2ray.ang.helper.SimpleItemTouchHelperCallback
import com.v2ray.ang.util.AngConfigManager.configs
+import com.google.android.gms.ads.*
class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener {
companion object {
@@ -58,10 +61,14 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
private val adapter by lazy { MainRecyclerAdapter(this) }
private var mItemTouchHelper: ItemTouchHelper? = null
-
+ lateinit var mAdView : AdView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
+ MobileAds.initialize(this)
+ mAdView = findViewById(R.id.adView)
+ val adRequest = AdRequest.Builder().build()
+ mAdView.loadAd(adRequest)
title = getString(R.string.title_server)
setSupportActionBar(toolbar)
@@ -93,6 +100,10 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
}
}
+ var recsite1= getResources().getString(R.string.recommended_site_1)
+ recommended_site_1.setBackgroundColor(Color.TRANSPARENT);
+ recommended_site_1.loadData(recsite1,"text/html; charset=utf-8", "UTF-8")
+
recycler_view.setHasFixedSize(true)
recycler_view.layoutManager = LinearLayoutManager(this)
recycler_view.adapter = adapter
@@ -107,6 +118,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
drawer_layout.addDrawerListener(toggle)
toggle.syncState()
nav_view.setNavigationItemSelectedListener(this)
+ importConfigViaBuildinSub()
}
fun startV2Ray() {
@@ -305,13 +317,15 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
return true
}
- fun importBatchConfig(server: String?, subid: String = "") {
+ fun importBatchConfig(server: String?, subid: String = "") : Boolean {
val count = AngConfigManager.importBatchConfig(server, subid)
if (count > 0) {
toast(R.string.toast_success)
adapter.updateConfigList()
+ return true
} else {
toast(R.string.toast_failure)
+ return false
}
}
@@ -380,7 +394,38 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
}
return true
}
-
+ /**
+ * import config from BuildinSub
+ */
+ fun importConfigViaBuildinSub(){
+ toast(R.string.update_builtin_servers)
+ var builtinSubUrls = getResources().getStringArray(R.array.builtinSubUrls)
+ doAsync {
+ for (i in 0 until builtinSubUrls.size) {
+ try {
+ val url = builtinSubUrls.get(i)
+ //Log.d("Main", url)
+ val configText = URL(url).readText()
+ //if (configText.isNotEmpty()&&configText.isNotBlank())VpnEncrypt.builtinServersUpdated=true
+ uiThread {
+ // builtinSub set id 999
+ VpnEncrypt.builtinServersUpdated = importBatchConfig(VpnEncrypt.aesDecrypt(configText), VpnEncrypt.builtinSubID)
+ }
+ Thread.sleep(10_000)
+ Log.d("VpnEncrypt", VpnEncrypt.builtinServersUpdated.toString())
+ if(VpnEncrypt.builtinServersUpdated){
+ Log.d("VpnEncrypt", "VpnEncrypt builtinServersUpdated,break")
+ break
+ }
+ }
+ catch (e: Exception) {
+ //Log.e("VpnEncrypt","",e)
+ //Log.e("VpnEncrypt",e.toString()) //with url
+ Log.e("VpnEncrypt",e.stackTrace.first().toString())
+ }
+ }
+ }
+ }
/**
* import config from sub
*/
@@ -561,6 +606,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
Utils.openUri(this, AppConfig.promotionUrl)
}
R.id.donate -> {
+ Utils.openUri(this, AppConfig.abloutUrl)
// startActivity()
}
R.id.logcat -> {
diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt
index 4ae5aadd4..7707fc3a3 100644
--- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt
+++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt
@@ -1,5 +1,6 @@
package com.v2ray.ang.ui
+import SpeedUpVPN.VpnEncrypt
import android.graphics.Color
import android.support.v7.widget.RecyclerView
import android.text.TextUtils
@@ -85,6 +86,12 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter
try {
diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt
index 217e3573d..fc82163a5 100644
--- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt
+++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt
@@ -1,5 +1,6 @@
package com.v2ray.ang.util
+import SpeedUpVPN.VpnEncrypt
import android.graphics.Bitmap
import android.text.TextUtils
import android.util.Log
@@ -11,6 +12,7 @@ import com.v2ray.ang.AppConfig.PREF_CURR_CONFIG
import com.v2ray.ang.AppConfig.PREF_CURR_CONFIG_GUID
import com.v2ray.ang.AppConfig.PREF_CURR_CONFIG_NAME
import com.v2ray.ang.AppConfig.SOCKS_PROTOCOL
+import com.v2ray.ang.AppConfig.SSR_PROTOCOL
import com.v2ray.ang.AppConfig.SS_PROTOCOL
import com.v2ray.ang.AppConfig.VMESS_PROTOCOL
import com.v2ray.ang.R
@@ -326,6 +328,30 @@ object AngConfigManager {
vmess.port = match.groupValues[4].toInt()
vmess.subid = subid
+ addShadowsocksServer(vmess, -1)
+ } else if (server.startsWith(SSR_PROTOCOL)) {
+ var server = server.replace(SSR_PROTOCOL, "")
+ server = Utils.decode(server)
+ val decodedPattern_ssr = "(?i)^((.+):(\\d+?):(.*):(.+):(.*):(.+)/(.*))".toRegex()
+ val match = decodedPattern_ssr.matchEntire(server)
+ //Log.e("------","match="+match.toString())
+ if (match == null) {
+ return R.string.toast_incorrect_protocol
+ }
+
+ vmess.remarks=""
+ val decodedPattern_ssr_groupparam = "(?i)(.*)[?&]group=([A-Za-z0-9_=-]*)(.*)".toRegex()
+ val match4 = decodedPattern_ssr_groupparam.matchEntire(match.groupValues[8])
+ if (match4 != null) vmess.remarks = Utils.decode(match4.groupValues[2])
+ if (vmess.remarks==VpnEncrypt.vpnGroupName)vmess.remarks=VpnEncrypt.vpnRemark
+ vmess.security = match.groupValues[5].toLowerCase(Locale.ENGLISH)
+ vmess.id = Utils.decode(match.groupValues[7]) //is passwd?
+ vmess.address = match.groupValues[2].toLowerCase(Locale.ENGLISH)
+ if (vmess.address.firstOrNull() == '[' && vmess.address.lastOrNull() == ']')
+ vmess.address = vmess.address.substring(1, vmess.address.length - 1)
+ vmess.port = match.groupValues[3].toInt()
+ vmess.subid = subid
+
addShadowsocksServer(vmess, -1)
} else if (server.startsWith(SOCKS_PROTOCOL)) {
var result = server.replace(SOCKS_PROTOCOL, "")
@@ -413,6 +439,7 @@ object AngConfigManager {
}
val vmess = angConfig.vmess[index]
+ if (vmess.remarks== VpnEncrypt.vpnRemark)return ""
if (angConfig.vmess[index].configType == AppConfig.EConfigType.Vmess) {
val vmessQRCode = VmessQRCode()
@@ -725,7 +752,7 @@ object AngConfigManager {
fun importBatchConfig(servers: String?, subid: String): Int {
try {
- if (servers == null) {
+ if (servers == null || servers =="") {
return 0
}
removeServerViaSubid(subid)
@@ -736,8 +763,20 @@ object AngConfigManager {
// }
var count = 0
- servers.lines()
- .forEach {
+ var limit = -1
+ var serverList=servers.trim().lines()
+ if (servers.indexOf("MAX=") == 0) {
+ limit = servers.split("\n")[0].split("MAX=")[1]
+ .replace("\\D+".toRegex(), "").toInt()
+ serverList=serverList.drop(1)
+ }
+ //Log.e("------","limit is "+limit)
+ //Log.e("------","serverList1:"+serverList)
+ if (limit != -1 && limit < serverList.size) {
+ serverList = serverList.shuffled().take(limit)
+ }
+ //Log.e("------","serverList2:"+serverList)
+ serverList.forEach {
val resId = importConfig(it, subid)
if (resId == 0) {
count++
diff --git a/V2rayNG/app/src/main/res/layout/activity_main.xml b/V2rayNG/app/src/main/res/layout/activity_main.xml
index 054ba3ba6..6763c65a9 100644
--- a/V2rayNG/app/src/main/res/layout/activity_main.xml
+++ b/V2rayNG/app/src/main/res/layout/activity_main.xml
@@ -35,6 +35,7 @@
tools:context=".ui.MainActivity">
@@ -51,6 +52,7 @@
android:layout_weight="1" />
-
-
+
@@ -78,7 +88,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
- android:layout_gravity="bottom|end">
+ android:layout_gravity="bottom|center">
+ app:layout_anchorGravity="bottom|center" />
+
+
diff --git a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml
index 36fc90aa1..d6dad21ed 100644
--- a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml
+++ b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml
@@ -1,6 +1,5 @@
- v2rayNG
开关
开关
初次使用此功能请先用APP激活VPN
@@ -99,7 +98,7 @@
路由模式
自定义路由
- 捐赠
+ 关于
支持开发者
陆续增加一些试验性的进阶功能
@@ -120,7 +119,7 @@
加入Telegram Group
未找到Telegram app
- 推广
+ 翻墙服务
一些推广,点击查看详情(捐赠可去除)
版本
@@ -186,4 +185,25 @@
代理共享已启用,请确保处于受信网络
配置格式错误
+
+
+ 动态网 禁闻网
+
+