Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f25aaf43d7 | |||
| 3b365533fc | |||
| a982327030 | |||
| 6ce12b2ea5 | |||
| d7f3ed5182 | |||
| f519103b3e | |||
| d7c40ee883 | |||
| 809d50689b | |||
| 042def7e83 | |||
| 8bb0d6b175 | |||
| 3ae76fab72 | |||
| 46a63e8704 | |||
| 12f8b1584c | |||
| 2b571e2a94 | |||
| ba30697309 | |||
| 879e25bb82 | |||
| 17c858d24c | |||
| 71a6531835 | |||
| 5d760382d7 | |||
| 4dda36673a | |||
| 5aca55cb8f | |||
| 82f14f0d07 | |||
| c0e968ac34 | |||
| 29d3fb710b |
+5
-3
@@ -2,8 +2,10 @@ V2rayNG/app/src/main/res/layout/activity_inapp_buy.xml
|
|||||||
V2rayNG/app/src/main/assets/geoip.dat
|
V2rayNG/app/src/main/assets/geoip.dat
|
||||||
V2rayNG/app/src/main/assets/geosite.dat
|
V2rayNG/app/src/main/assets/geosite.dat
|
||||||
V2rayNG/app/src/main/java/com/v2ray/ang/InappBuyActivity.java
|
V2rayNG/app/src/main/java/com/v2ray/ang/InappBuyActivity.java
|
||||||
|
V2rayNG/gradle/wrapper/gradle-wrapper.properties
|
||||||
|
V2rayNG/gradle/wrapper/gradle-wrapper.properties
|
||||||
*.dat
|
*.dat
|
||||||
*.jks
|
*.jks
|
||||||
V2rayNG/app/release/output.json
|
V2rayNG/gradle/wrapper/gradle-wrapper.properties
|
||||||
.idea/
|
V2rayNG/gradle/wrapper/gradle-wrapper.properties
|
||||||
.gradle/
|
V2rayNG/app/release/output.json
|
||||||
@@ -116,7 +116,7 @@ func (v V2RayPoint) QueryStats(tag string, direct string) int64 {
|
|||||||
if v.statsManager == nil {
|
if v.statsManager == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
counter := v.statsManager.GetCounter(fmt.Sprintf("outbound>>>%s>>>traffic>>>%s", tag, direct))
|
counter := v.statsManager.GetCounter(fmt.Sprintf("inbound>>>%s>>>traffic>>>%s", tag, direct))
|
||||||
if counter == nil {
|
if counter == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,3 +3,4 @@
|
|||||||
<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>
|
||||||
|
|
||||||
|
|||||||
@@ -20,17 +20,34 @@ android {
|
|||||||
versionName "1.0.2"
|
versionName "1.0.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signingConfigs {
|
||||||
|
release {
|
||||||
|
storeFile file("../key.jks")
|
||||||
|
keyAlias 'ang'
|
||||||
|
keyPassword '123456'
|
||||||
|
storePassword '123456'
|
||||||
|
}
|
||||||
|
debug {
|
||||||
|
storeFile file("../key.jks")
|
||||||
|
keyAlias 'ang'
|
||||||
|
keyPassword '123456'
|
||||||
|
storePassword '123456'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
zipAlignEnabled false
|
zipAlignEnabled false
|
||||||
shrinkResources false
|
shrinkResources false
|
||||||
|
signingConfig signingConfigs.release
|
||||||
// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
debug {
|
debug {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
zipAlignEnabled false
|
zipAlignEnabled false
|
||||||
shrinkResources false
|
shrinkResources false
|
||||||
|
signingConfig signingConfigs.release
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,10 +84,6 @@ dependencies {
|
|||||||
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-android:1.2.2" // 1.3.x has compile error:
|
|
||||||
// More than one file was found with OS independent path 'META-INF/proguard/coroutines.pro'
|
|
||||||
|
|
||||||
// Android support library
|
// Android support library
|
||||||
implementation "com.android.support:support-v4:$supportLibVersion"
|
implementation "com.android.support:support-v4:$supportLibVersion"
|
||||||
implementation "com.android.support:appcompat-v7:$supportLibVersion"
|
implementation "com.android.support:appcompat-v7:$supportLibVersion"
|
||||||
@@ -78,7 +91,6 @@ dependencies {
|
|||||||
implementation "com.android.support:cardview-v7:$supportLibVersion"
|
implementation "com.android.support:cardview-v7:$supportLibVersion"
|
||||||
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"
|
|
||||||
// DSL
|
// DSL
|
||||||
implementation "org.jetbrains.anko:anko-sdk15:$ankoVersion"
|
implementation "org.jetbrains.anko:anko-sdk15:$ankoVersion"
|
||||||
implementation "org.jetbrains.anko:anko-support-v4:$ankoVersion"
|
implementation "org.jetbrains.anko:anko-support-v4:$ankoVersion"
|
||||||
@@ -114,4 +126,4 @@ repositories {
|
|||||||
flatDir {
|
flatDir {
|
||||||
dirs 'libs'
|
dirs 'libs'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,16 +2,6 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.v2ray.ang">
|
package="com.v2ray.ang">
|
||||||
|
|
||||||
<supports-screens
|
|
||||||
android:anyDensity="true"
|
|
||||||
android:smallScreens="true"
|
|
||||||
android:normalScreens="true"
|
|
||||||
android:largeScreens="true"
|
|
||||||
android:xlargeScreens="true"/>
|
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.camera" android:required="false"/>
|
|
||||||
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
@@ -76,10 +66,7 @@
|
|||||||
|
|
||||||
<activity android:name=".ui.SubEditActivity" />
|
<activity android:name=".ui.SubEditActivity" />
|
||||||
<activity android:name=".ui.ScScannerActivity" />
|
<activity android:name=".ui.ScScannerActivity" />
|
||||||
<activity
|
<activity android:name=".ui.ScSwitchActivity" />
|
||||||
android:name=".ui.ScSwitchActivity"
|
|
||||||
android:excludeFromRecents="true"
|
|
||||||
android:theme="@style/AppTheme.NoActionBar.Translucent" />
|
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".service.V2RayVpnService"
|
android:name=".service.V2RayVpnService"
|
||||||
@@ -96,16 +83,16 @@
|
|||||||
android:value="true" />
|
android:value="true" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<receiver android:name=".receiver.WidgetProvider"
|
<!--<receiver android:name=".receiver.WidgetProvider">-->
|
||||||
android:process=":RunSoLibV2RayDaemon">
|
<!--<meta-data-->
|
||||||
<meta-data
|
<!--android:name="android.appwidget.provider"-->
|
||||||
android:name="android.appwidget.provider"
|
<!--android:resource="@xml/app_widget_provider" />-->
|
||||||
android:resource="@xml/app_widget_provider" />
|
|
||||||
<intent-filter>
|
<!--<intent-filter>-->
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
<!--<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />-->
|
||||||
<action android:name="com.v2ray.ang.action.widget.click" />
|
<!--<action android:name="com.v2ray.ang.action.widget.click" />-->
|
||||||
</intent-filter>
|
<!--</intent-filter>-->
|
||||||
</receiver>
|
<!--</receiver>-->
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".service.QSTileService"
|
android:name=".service.QSTileService"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
android
|
|
||||||
com.android.chrome
|
com.android.chrome
|
||||||
com.google.android.googlequicksearchbox
|
com.google.android.googlequicksearchbox
|
||||||
com.google.android.apps.photos
|
com.google.android.apps.photos
|
||||||
@@ -194,4 +193,4 @@ tv.twitch.android.app
|
|||||||
com.shanga.walli
|
com.shanga.walli
|
||||||
com.whatsapp
|
com.whatsapp
|
||||||
com.wire
|
com.wire
|
||||||
com.simplehabit.simplehabitapp
|
com.simplehabit.simplehabitapp
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"statsOutboundUplink": true,
|
"statsInboundUplink": true,
|
||||||
"statsOutboundDownlink": true
|
"statsInboundDownlink": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"inbounds": [{
|
"inbounds": [{
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ public interface ItemTouchHelperAdapter {
|
|||||||
boolean onItemMove(int fromPosition, int toPosition);
|
boolean onItemMove(int fromPosition, int toPosition);
|
||||||
|
|
||||||
|
|
||||||
void onItemMoveCompleted();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an item has been dismissed by a swipe.<br/>
|
* Called when an item has been dismissed by a swipe.<br/>
|
||||||
* <br/>
|
* <br/>
|
||||||
|
|||||||
@@ -112,8 +112,6 @@ public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
|
|||||||
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
|
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
|
||||||
super.clearView(recyclerView, viewHolder);
|
super.clearView(recyclerView, viewHolder);
|
||||||
|
|
||||||
mAdapter.onItemMoveCompleted();
|
|
||||||
|
|
||||||
viewHolder.itemView.setAlpha(ALPHA_FULL);
|
viewHolder.itemView.setAlpha(ALPHA_FULL);
|
||||||
|
|
||||||
if (viewHolder instanceof ItemTouchHelperViewHolder) {
|
if (viewHolder instanceof ItemTouchHelperViewHolder) {
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
package com.v2ray.ang
|
package com.v2ray.ang
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
//import com.squareup.leakcanary.LeakCanary
|
//import com.squareup.leakcanary.LeakCanary
|
||||||
import android.support.multidex.MultiDexApplication
|
|
||||||
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
|
import org.jetbrains.anko.defaultSharedPreferences
|
||||||
|
|
||||||
class AngApplication : MultiDexApplication() {
|
class AngApplication : Application() {
|
||||||
companion object {
|
companion object {
|
||||||
const val PREF_LAST_VERSION = "pref_last_version"
|
const val PREF_LAST_VERSION = "pref_last_version"
|
||||||
}
|
}
|
||||||
|
|
||||||
var curIndex = -1 //Current proxy that is opened. (Used to implement restart feature)
|
|
||||||
var firstRun = false
|
var firstRun = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|||||||
@@ -64,21 +64,22 @@ data class V2rayConfig(
|
|||||||
|
|
||||||
data class StreamSettingsBean(var network: String,
|
data class StreamSettingsBean(var network: String,
|
||||||
var security: String,
|
var security: String,
|
||||||
var tcpSettings: TcpSettingsBean?,
|
var tcpSettings: TcpsettingsBean?,
|
||||||
var kcpSettings: KcpSettingsBean?,
|
var kcpsettings: KcpsettingsBean?,
|
||||||
var wsSettings: WsSettingsBean?,
|
var wssettings: WssettingsBean?,
|
||||||
var httpSettings: HttpSettingsBean?,
|
var httpsettings: HttpsettingsBean?,
|
||||||
var tlsSettings: TlsSettingsBean?,
|
var tlssettings: TlssettingsBean?,
|
||||||
var quicSettings: QuicSettingBean?
|
var quicsettings: QuicsettingBean?
|
||||||
) {
|
) {
|
||||||
|
|
||||||
data class TcpSettingsBean(var header: HeaderBean = HeaderBean()) {
|
data class TcpsettingsBean(var connectionReuse: Boolean = true,
|
||||||
|
var header: HeaderBean = HeaderBean()) {
|
||||||
data class HeaderBean(var type: String = "none",
|
data class HeaderBean(var type: String = "none",
|
||||||
var request: Any? = null,
|
var request: Any? = null,
|
||||||
var response: Any? = null)
|
var response: Any? = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class KcpSettingsBean(var mtu: Int = 1350,
|
data class KcpsettingsBean(var mtu: Int = 1350,
|
||||||
var tti: Int = 20,
|
var tti: Int = 20,
|
||||||
var uplinkCapacity: Int = 12,
|
var uplinkCapacity: Int = 12,
|
||||||
var downlinkCapacity: Int = 100,
|
var downlinkCapacity: Int = 100,
|
||||||
@@ -89,20 +90,20 @@ data class V2rayConfig(
|
|||||||
data class HeaderBean(var type: String = "none")
|
data class HeaderBean(var type: String = "none")
|
||||||
}
|
}
|
||||||
|
|
||||||
data class WsSettingsBean(var path: String = "",
|
data class WssettingsBean(var connectionReuse: Boolean = true,
|
||||||
|
var path: String = "",
|
||||||
var headers: HeadersBean = HeadersBean()) {
|
var headers: HeadersBean = HeadersBean()) {
|
||||||
data class HeadersBean(var Host: String = "")
|
data class HeadersBean(var Host: String = "")
|
||||||
}
|
}
|
||||||
|
|
||||||
data class HttpSettingsBean(var host: List<String> = ArrayList(),
|
data class HttpsettingsBean(var host: List<String> = ArrayList<String>(), var path: String = "")
|
||||||
var path: String = "")
|
|
||||||
|
|
||||||
data class TlsSettingsBean(var allowInsecure: Boolean = true,
|
data class TlssettingsBean(var allowInsecure: Boolean = true,
|
||||||
var serverName: String = "")
|
var serverName: String = "")
|
||||||
|
|
||||||
data class QuicSettingBean(var security: String = "none",
|
data class QuicsettingBean(var security: String = "none",
|
||||||
var key: String = "",
|
var key: String = "",
|
||||||
var header: HeaderBean = HeaderBean()) {
|
var header: HeaderBean = HeaderBean()) {
|
||||||
data class HeaderBean(var type: String = "none")
|
data class HeaderBean(var type: String = "none")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,37 +27,34 @@ const val divisor = 1024F
|
|||||||
fun Long.toSpeedString() = toTrafficString() + "/s"
|
fun Long.toSpeedString() = toTrafficString() + "/s"
|
||||||
|
|
||||||
fun Long.toTrafficString(): String {
|
fun Long.toTrafficString(): String {
|
||||||
if (this == 0L)
|
|
||||||
return "\t\t\t0\t B"
|
|
||||||
|
|
||||||
if (this < threshold)
|
if (this < threshold)
|
||||||
return "${this.toFloat().toShortString()}\t B"
|
return "$this B"
|
||||||
|
|
||||||
val kib = this / divisor
|
val kib = this / divisor
|
||||||
if (kib < threshold)
|
if (kib < threshold)
|
||||||
return "${kib.toShortString()}\t KB"
|
return "${kib.toShortString()} KB"
|
||||||
|
|
||||||
val mib = kib / divisor
|
val mib = kib / divisor
|
||||||
if (mib < threshold)
|
if (mib < threshold)
|
||||||
return "${mib.toShortString()}\t MB"
|
return "${mib.toShortString()} MB"
|
||||||
|
|
||||||
val gib = mib / divisor
|
val gib = mib / divisor
|
||||||
if (gib < threshold)
|
if (gib < threshold)
|
||||||
return "${gib.toShortString()}\t GB"
|
return "${gib.toShortString()} GB"
|
||||||
|
|
||||||
val tib = gib / divisor
|
val tib = gib / divisor
|
||||||
if (tib < threshold)
|
if (tib < threshold)
|
||||||
return "${tib.toShortString()}\t TB"
|
return "${tib.toShortString()} TB"
|
||||||
|
|
||||||
val pib = tib / divisor
|
val pib = tib / divisor
|
||||||
if (pib < threshold)
|
if (pib < threshold)
|
||||||
return "${pib.toShortString()}\t PB"
|
return "${pib.toShortString()} PB"
|
||||||
|
|
||||||
return "∞"
|
return "∞"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Float.toShortString(): String {
|
private fun Float.toShortString(): String {
|
||||||
val s = "%.2f".format(this)
|
val s = toString()
|
||||||
if (s.length <= 4)
|
if (s.length <= 4)
|
||||||
return s
|
return s
|
||||||
return s.substring(0, 4).removeSuffix(".")
|
return s.substring(0, 4).removeSuffix(".")
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ package com.v2ray.ang.receiver
|
|||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.appwidget.AppWidgetProvider
|
import android.appwidget.AppWidgetProvider
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
import android.widget.RemoteViews
|
import android.widget.RemoteViews
|
||||||
import com.v2ray.ang.R
|
import com.v2ray.ang.R
|
||||||
import com.v2ray.ang.AppConfig
|
import com.v2ray.ang.AppConfig
|
||||||
import com.v2ray.ang.util.Utils
|
import com.v2ray.ang.util.Utils
|
||||||
|
import org.jetbrains.anko.toast
|
||||||
|
|
||||||
class WidgetProvider : AppWidgetProvider() {
|
class WidgetProvider : AppWidgetProvider() {
|
||||||
/**
|
/**
|
||||||
@@ -18,21 +19,10 @@ class WidgetProvider : AppWidgetProvider() {
|
|||||||
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
||||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||||
|
|
||||||
val isRunning = Utils.isServiceRun(context, "com.v2ray.ang.service.V2RayVpnService")
|
|
||||||
updateWidgetBackground(context, appWidgetManager, appWidgetIds, isRunning)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateWidgetBackground(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, isRunning: Boolean) {
|
|
||||||
val remoteViews = RemoteViews(context.packageName, R.layout.widget_switch)
|
val remoteViews = RemoteViews(context.packageName, R.layout.widget_switch)
|
||||||
val intent = Intent(context, WidgetProvider::class.java)
|
val intent = Intent(AppConfig.BROADCAST_ACTION_WIDGET_CLICK)
|
||||||
intent.setAction(AppConfig.BROADCAST_ACTION_WIDGET_CLICK)
|
|
||||||
val pendingIntent = PendingIntent.getBroadcast(context, R.id.layout_switch, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
val pendingIntent = PendingIntent.getBroadcast(context, R.id.layout_switch, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
remoteViews.setOnClickPendingIntent(R.id.layout_switch, pendingIntent)
|
remoteViews.setOnClickPendingIntent(R.id.layout_switch, pendingIntent)
|
||||||
if (isRunning) {
|
|
||||||
remoteViews.setInt(R.id.layout_switch, "setBackgroundResource", R.drawable.ic_rounded_corner_theme);
|
|
||||||
} else {
|
|
||||||
remoteViews.setInt(R.id.layout_switch, "setBackgroundResource", R.drawable.ic_rounded_corner_grey);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (appWidgetId in appWidgetIds) {
|
for (appWidgetId in appWidgetIds) {
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
|
appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
|
||||||
@@ -54,9 +44,7 @@ class WidgetProvider : AppWidgetProvider() {
|
|||||||
// context.toast(R.string.toast_services_start)
|
// context.toast(R.string.toast_services_start)
|
||||||
Utils.startVService(context)
|
Utils.startVService(context)
|
||||||
}
|
}
|
||||||
val manager = AppWidgetManager.getInstance(context)
|
|
||||||
updateWidgetBackground(context, manager, manager.getAppWidgetIds(ComponentName(context, WidgetProvider::class.java)),
|
|
||||||
!isRunning);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,15 @@ import libv2ray.Libv2ray
|
|||||||
import libv2ray.V2RayVPNServiceSupportsSet
|
import libv2ray.V2RayVPNServiceSupportsSet
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
|
import java.net.InetAddress
|
||||||
|
import java.io.IOException
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileDescriptor
|
||||||
|
import java.io.FileInputStream
|
||||||
import java.lang.ref.SoftReference
|
import java.lang.ref.SoftReference
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.annotation.TargetApi
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import go.Seq
|
|
||||||
import org.jetbrains.anko.doAsync
|
import org.jetbrains.anko.doAsync
|
||||||
|
|
||||||
class V2RayVpnService : VpnService() {
|
class V2RayVpnService : VpnService() {
|
||||||
@@ -40,7 +44,6 @@ class V2RayVpnService : VpnService() {
|
|||||||
const val NOTIFICATION_ID = 1
|
const val NOTIFICATION_ID = 1
|
||||||
const val NOTIFICATION_PENDING_INTENT_CONTENT = 0
|
const val NOTIFICATION_PENDING_INTENT_CONTENT = 0
|
||||||
const val NOTIFICATION_PENDING_INTENT_STOP_V2RAY = 1
|
const val NOTIFICATION_PENDING_INTENT_STOP_V2RAY = 1
|
||||||
const val NOTIFICATION_ICON_THRESHOLD = 3000
|
|
||||||
|
|
||||||
fun startV2Ray(context: Context) {
|
fun startV2Ray(context: Context) {
|
||||||
val intent = Intent(context.applicationContext, V2RayVpnService::class.java)
|
val intent = Intent(context.applicationContext, V2RayVpnService::class.java)
|
||||||
@@ -53,7 +56,6 @@ class V2RayVpnService : VpnService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val v2rayPoint = Libv2ray.newV2RayPoint(V2RayCallback())
|
private val v2rayPoint = Libv2ray.newV2RayPoint(V2RayCallback())
|
||||||
private var lastQueryTime = 0L
|
|
||||||
private lateinit var configContent: String
|
private lateinit var configContent: String
|
||||||
private lateinit var mInterface: ParcelFileDescriptor
|
private lateinit var mInterface: ParcelFileDescriptor
|
||||||
val fd: Int get() = mInterface.fd
|
val fd: Int get() = mInterface.fd
|
||||||
@@ -62,6 +64,7 @@ class V2RayVpnService : VpnService() {
|
|||||||
private var mNotificationManager: NotificationManager? = null
|
private var mNotificationManager: NotificationManager? = null
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unfortunately registerDefaultNetworkCallback is going to return our VPN interface: https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e
|
* Unfortunately registerDefaultNetworkCallback is going to return our VPN interface: https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e
|
||||||
*
|
*
|
||||||
@@ -71,28 +74,25 @@ class V2RayVpnService : VpnService() {
|
|||||||
*
|
*
|
||||||
* 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) {
|
@TargetApi(28)
|
||||||
NetworkRequest.Builder()
|
private val defaultNetworkRequest = NetworkRequest.Builder()
|
||||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
|
||||||
.build()
|
.build()
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private val connectivity by lazy { getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager }
|
private val connectivity by lazy { getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager }
|
||||||
|
@TargetApi(28)
|
||||||
private val defaultNetworkCallback by lazy @RequiresApi(Build.VERSION_CODES.P) {
|
private val defaultNetworkCallback = object : ConnectivityManager.NetworkCallback() {
|
||||||
object : ConnectivityManager.NetworkCallback() {
|
override fun onAvailable(network: Network) {
|
||||||
override fun onAvailable(network: Network) {
|
setUnderlyingNetworks(arrayOf(network))
|
||||||
setUnderlyingNetworks(arrayOf(network))
|
}
|
||||||
}
|
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities?) {
|
||||||
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities?) {
|
// it's a good idea to refresh capabilities
|
||||||
// it's a good idea to refresh capabilities
|
setUnderlyingNetworks(arrayOf(network))
|
||||||
setUnderlyingNetworks(arrayOf(network))
|
}
|
||||||
}
|
override fun onLost(network: Network) {
|
||||||
override fun onLost(network: Network) {
|
setUnderlyingNetworks(null)
|
||||||
setUnderlyingNetworks(null)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private var listeningForDefaultNetwork = false
|
private var listeningForDefaultNetwork = false
|
||||||
@@ -131,7 +131,6 @@ class V2RayVpnService : VpnService() {
|
|||||||
// Configure a builder while parsing the parameters.
|
// Configure a builder while parsing the parameters.
|
||||||
val builder = Builder()
|
val builder = Builder()
|
||||||
val enableLocalDns = defaultDPreference.getPrefBoolean(SettingsActivity.PREF_LOCAL_DNS_ENABLED, false)
|
val enableLocalDns = defaultDPreference.getPrefBoolean(SettingsActivity.PREF_LOCAL_DNS_ENABLED, false)
|
||||||
val routingMode = defaultDPreference.getPrefString(SettingsActivity.PREF_ROUTING_MODE, "0")
|
|
||||||
|
|
||||||
parameters.split(" ")
|
parameters.split(" ")
|
||||||
.map { it.split(",") }
|
.map { it.split(",") }
|
||||||
@@ -140,20 +139,7 @@ class V2RayVpnService : VpnService() {
|
|||||||
'm' -> builder.setMtu(java.lang.Short.parseShort(it[1]).toInt())
|
'm' -> builder.setMtu(java.lang.Short.parseShort(it[1]).toInt())
|
||||||
's' -> builder.addSearchDomain(it[1])
|
's' -> builder.addSearchDomain(it[1])
|
||||||
'a' -> builder.addAddress(it[1], Integer.parseInt(it[2]))
|
'a' -> builder.addAddress(it[1], Integer.parseInt(it[2]))
|
||||||
'r' -> {
|
'r' -> builder.addRoute(it[1], Integer.parseInt(it[2]))
|
||||||
if (routingMode == "1" || routingMode == "3") {
|
|
||||||
if (it[1] == "::") { //not very elegant, should move Vpn setting in Kotlin, simplify go code
|
|
||||||
builder.addRoute("2000::", 3)
|
|
||||||
} else {
|
|
||||||
resources.getStringArray(R.array.bypass_private_ip_address).forEach {
|
|
||||||
val addr = it.split('/')
|
|
||||||
builder.addRoute(addr[0], addr[1].toInt())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
builder.addRoute(it[1], Integer.parseInt(it[2]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'd' -> builder.addDnsServer(it[1])
|
'd' -> builder.addDnsServer(it[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +176,7 @@ class V2RayVpnService : VpnService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
if (Build.VERSION.SDK_INT >= 28) {
|
||||||
connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
|
connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
|
||||||
listeningForDefaultNetwork = true
|
listeningForDefaultNetwork = true
|
||||||
}
|
}
|
||||||
@@ -198,7 +184,6 @@ class V2RayVpnService : VpnService() {
|
|||||||
// 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()
|
mInterface = builder.establish()
|
||||||
sendFd()
|
sendFd()
|
||||||
lastQueryTime = System.currentTimeMillis()
|
|
||||||
startSpeedNotification()
|
startSpeedNotification()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +260,7 @@ class V2RayVpnService : VpnService() {
|
|||||||
// 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) {
|
if (Build.VERSION.SDK_INT >= 28) {
|
||||||
if (listeningForDefaultNetwork) {
|
if (listeningForDefaultNetwork) {
|
||||||
connectivity.unregisterNetworkCallback(defaultNetworkCallback)
|
connectivity.unregisterNetworkCallback(defaultNetworkCallback)
|
||||||
listeningForDefaultNetwork = false
|
listeningForDefaultNetwork = false
|
||||||
@@ -297,19 +282,12 @@ class V2RayVpnService : VpnService() {
|
|||||||
unregisterReceiver(mMsgReceive)
|
unregisterReceiver(mMsgReceive)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//stopSelf has to be called ahead of mInterface.close(). otherwise v2ray core cannot be stooped
|
|
||||||
//It's strage but true.
|
|
||||||
//This can be verified by putting stopself() behind and call stopLoop and startLoop
|
|
||||||
//in a row for several times. You will find that later created v2ray core report port in use
|
|
||||||
//which means the first v2ray core somehow failed to stop and release the port.
|
|
||||||
stopSelf()
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mInterface.close()
|
mInterface.close()
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stopSelf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,17 +352,9 @@ class V2RayVpnService : VpnService() {
|
|||||||
mSubscription = null
|
mSubscription = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateNotification(contentText: String, proxyTraffic: Long, directTraffic: Long) {
|
private fun updateNotification(contentText: String) {
|
||||||
if (mBuilder != null) {
|
if (mBuilder != null) {
|
||||||
if (proxyTraffic < NOTIFICATION_ICON_THRESHOLD && directTraffic < NOTIFICATION_ICON_THRESHOLD) {
|
mBuilder?.setContentTitle(contentText)
|
||||||
mBuilder?.setSmallIcon(R.drawable.ic_v)
|
|
||||||
} else if (proxyTraffic > directTraffic) {
|
|
||||||
mBuilder?.setSmallIcon(R.drawable.ic_stat_proxy)
|
|
||||||
} else {
|
|
||||||
mBuilder?.setSmallIcon(R.drawable.ic_stat_direct)
|
|
||||||
}
|
|
||||||
mBuilder?.setStyle(NotificationCompat.BigTextStyle().bigText(contentText))
|
|
||||||
mBuilder?.setContentText(contentText) // Emui4.1 need content text even if style is set as BigTextStyle
|
|
||||||
getNotificationManager().notify(NOTIFICATION_ID, mBuilder?.build())
|
getNotificationManager().notify(NOTIFICATION_ID, mBuilder?.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -405,22 +375,13 @@ class V2RayVpnService : VpnService() {
|
|||||||
|
|
||||||
mSubscription = Observable.interval(3, java.util.concurrent.TimeUnit.SECONDS)
|
mSubscription = Observable.interval(3, java.util.concurrent.TimeUnit.SECONDS)
|
||||||
.subscribe {
|
.subscribe {
|
||||||
val proxyUplink = v2rayPoint.queryStats("proxy", "uplink")
|
val uplink = v2rayPoint.queryStats("socks", "uplink")
|
||||||
val proxyDownlink = v2rayPoint.queryStats("proxy", "downlink")
|
val downlink = v2rayPoint.queryStats("socks", "downlink")
|
||||||
val directUplink = v2rayPoint.queryStats("direct", "uplink")
|
val zero_speed = (uplink == 0L && downlink == 0L)
|
||||||
val directDownlink = v2rayPoint.queryStats("direct", "downlink")
|
|
||||||
val zero_speed = (proxyUplink == 0L && proxyDownlink == 0L && directUplink == 0L && directDownlink == 0L)
|
|
||||||
val queryTime = System.currentTimeMillis()
|
|
||||||
if (!zero_speed || !last_zero_speed) {
|
if (!zero_speed || !last_zero_speed) {
|
||||||
val sinceLastQueryInSeconds = (queryTime - lastQueryTime) / 1000.0
|
updateNotification("${cf_name} • ${(uplink / 3).toSpeedString()}↑ ${(downlink / 3).toSpeedString()}↓")
|
||||||
updateNotification("proxy\t• ${(proxyUplink / sinceLastQueryInSeconds).toLong().toSpeedString()}↑ " +
|
|
||||||
"${(proxyDownlink / sinceLastQueryInSeconds).toLong().toSpeedString()}↓\n" +
|
|
||||||
"direct\t• ${(directUplink / sinceLastQueryInSeconds).toLong().toSpeedString()}↑ " +
|
|
||||||
"${(directDownlink / sinceLastQueryInSeconds).toLong().toSpeedString()}↓",
|
|
||||||
proxyDownlink + proxyUplink, directDownlink + directUplink)
|
|
||||||
}
|
}
|
||||||
last_zero_speed = zero_speed
|
last_zero_speed = zero_speed
|
||||||
lastQueryTime = queryTime
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,7 +393,7 @@ class V2RayVpnService : VpnService() {
|
|||||||
mSubscription = null
|
mSubscription = null
|
||||||
|
|
||||||
val cf_name = defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG_NAME, "")
|
val cf_name = defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG_NAME, "")
|
||||||
updateNotification(cf_name, 0, 0)
|
updateNotification(cf_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ abstract class BaseDrawerActivity : BaseActivity() {
|
|||||||
this@BaseDrawerActivity, R.anim.fade_in, R.anim.fade_out).toBundle()
|
this@BaseDrawerActivity, R.anim.fade_in, R.anim.fade_out).toBundle()
|
||||||
var activityClass: Class<*>? = null
|
var activityClass: Class<*>? = null
|
||||||
when (mItemToOpenWhenDrawerCloses) {
|
when (mItemToOpenWhenDrawerCloses) {
|
||||||
|
R.id.server_profile -> activityClass = MainActivity::class.java
|
||||||
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 -> {
|
||||||
@@ -194,7 +195,9 @@ abstract class BaseDrawerActivity : BaseActivity() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SubSettingActivity::class.java.isAssignableFrom(javaClass)) {
|
if (MainActivity::class.java.isAssignableFrom(javaClass)) {
|
||||||
|
navigationView.setCheckedItem(R.id.server_profile)
|
||||||
|
} else if (SubSettingActivity::class.java.isAssignableFrom(javaClass)) {
|
||||||
navigationView.setCheckedItem(R.id.sub_setting)
|
navigationView.setCheckedItem(R.id.sub_setting)
|
||||||
} else if (SettingsActivity::class.java.isAssignableFrom(javaClass)) {
|
} else if (SettingsActivity::class.java.isAssignableFrom(javaClass)) {
|
||||||
navigationView.setCheckedItem(R.id.settings)
|
navigationView.setCheckedItem(R.id.settings)
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package com.v2ray.ang.ui
|
package com.v2ray.ang.ui
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.text.method.ScrollingMovementMethod
|
import android.text.method.ScrollingMovementMethod
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
@@ -26,22 +24,15 @@ class LogcatActivity : BaseActivity() {
|
|||||||
title = getString(R.string.title_logcat)
|
title = getString(R.string.title_logcat)
|
||||||
|
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
logcat(false)
|
logcat()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun logcat(shouldFlushLog: Boolean) {
|
private fun logcat() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pb_waiting.visibility = View.VISIBLE
|
pb_waiting.visibility = View.VISIBLE
|
||||||
|
|
||||||
doAsync {
|
doAsync {
|
||||||
if (shouldFlushLog) {
|
|
||||||
val lst = LinkedHashSet<String>()
|
|
||||||
lst.add("logcat")
|
|
||||||
lst.add("-c")
|
|
||||||
val process = Runtime.getRuntime().exec(lst.toTypedArray())
|
|
||||||
process.waitFor()
|
|
||||||
}
|
|
||||||
val lst = LinkedHashSet<String>()
|
val lst = LinkedHashSet<String>()
|
||||||
lst.add("logcat")
|
lst.add("logcat")
|
||||||
lst.add("-d")
|
lst.add("-d")
|
||||||
@@ -58,11 +49,9 @@ class LogcatActivity : BaseActivity() {
|
|||||||
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
|
||||||
Handler(Looper.getMainLooper()).post { sv_logcat.fullScroll(View.FOCUS_DOWN) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,10 +66,7 @@ class LogcatActivity : BaseActivity() {
|
|||||||
toast(R.string.toast_success)
|
toast(R.string.toast_success)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.delete -> {
|
|
||||||
logcat(true)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import rx.android.schedulers.AndroidSchedulers
|
|||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import com.v2ray.ang.helper.SimpleItemTouchHelperCallback
|
import com.v2ray.ang.helper.SimpleItemTouchHelperCallback
|
||||||
import com.v2ray.ang.util.AngConfigManager.configs
|
import com.v2ray.ang.util.AngConfigManager.configs
|
||||||
import kotlinx.coroutines.*
|
|
||||||
|
|
||||||
class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener {
|
class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -59,7 +58,6 @@ 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>()
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -234,7 +232,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
|||||||
|
|
||||||
R.id.export_all -> {
|
R.id.export_all -> {
|
||||||
if (AngConfigManager.shareAll2Clipboard() == 0) {
|
if (AngConfigManager.shareAll2Clipboard() == 0) {
|
||||||
//remove toast, otherwise it will block previous warning message
|
toast(R.string.toast_success)
|
||||||
} else {
|
} else {
|
||||||
toast(R.string.toast_failure)
|
toast(R.string.toast_failure)
|
||||||
}
|
}
|
||||||
@@ -242,25 +240,18 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
|||||||
}
|
}
|
||||||
|
|
||||||
R.id.ping_all -> {
|
R.id.ping_all -> {
|
||||||
testingJobs.forEach {
|
|
||||||
it.cancel()
|
|
||||||
}
|
|
||||||
testingJobs.clear()
|
|
||||||
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 = ""
|
||||||
adapter.updateConfigList()
|
adapter.updateConfigList()
|
||||||
}
|
}
|
||||||
for (k in 0 until configs.vmess.count()) {
|
for (k in 0 until configs.vmess.count()) {
|
||||||
if (configs.vmess[k].configType != AppConfig.EConfigType.Custom) {
|
if (configs.vmess[k].configType != AppConfig.EConfigType.Custom) {
|
||||||
testingJobs.add(GlobalScope.launch(Dispatchers.IO) {
|
doAsync {
|
||||||
configs.vmess[k].testResult = Utils.tcping(configs.vmess[k].address, configs.vmess[k].port)
|
configs.vmess[k].testResult = Utils.tcping(configs.vmess[k].address, configs.vmess[k].port)
|
||||||
val myJob = coroutineContext[Job]
|
uiThread {
|
||||||
launch(Dispatchers.Main) {
|
|
||||||
testingJobs.remove(myJob)
|
|
||||||
adapter.updateSelectedItem(k)
|
adapter.updateSelectedItem(k)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
@@ -579,4 +570,4 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
|||||||
drawer_layout.closeDrawer(GravityCompat.START)
|
drawer_layout.closeDrawer(GravityCompat.START)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,8 +265,4 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
|
|||||||
updateSelectedItem(if (fromPosition < toPosition) fromPosition else toPosition)
|
updateSelectedItem(if (fromPosition < toPosition) fromPosition else toPosition)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemMoveCompleted() {
|
|
||||||
AngConfigManager.storeConfigFile()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
package com.v2ray.ang.ui
|
package com.v2ray.ang.ui
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
|
||||||
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.google.gson.Gson
|
|
||||||
import com.v2ray.ang.AppConfig
|
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
|
||||||
@@ -14,7 +12,6 @@ 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 org.jetbrains.anko.*
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
|
|
||||||
class Server2Activity : BaseActivity() {
|
class Server2Activity : BaseActivity() {
|
||||||
@@ -53,7 +50,7 @@ class Server2Activity : BaseActivity() {
|
|||||||
*/
|
*/
|
||||||
fun bindingServer(vmess: AngConfig.VmessBean): Boolean {
|
fun bindingServer(vmess: AngConfig.VmessBean): Boolean {
|
||||||
et_remarks.text = Utils.getEditable(vmess.remarks)
|
et_remarks.text = Utils.getEditable(vmess.remarks)
|
||||||
tv_content.text = Editable.Factory.getInstance().newEditable(defaultDPreference.getPrefString(AppConfig.ANG_CONFIG + edit_guid, ""))
|
tv_content.text = defaultDPreference.getPrefString(AppConfig.ANG_CONFIG + edit_guid, "")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,40 +66,21 @@ class Server2Activity : BaseActivity() {
|
|||||||
* save server config
|
* save server config
|
||||||
*/
|
*/
|
||||||
fun saveServer(): Boolean {
|
fun saveServer(): Boolean {
|
||||||
var saveSuccess: Boolean
|
|
||||||
val vmess = configs.vmess[edit_index]
|
val vmess = configs.vmess[edit_index]
|
||||||
|
|
||||||
vmess.remarks = et_remarks.text.toString()
|
vmess.remarks = et_remarks.text.toString()
|
||||||
|
|
||||||
if (TextUtils.isEmpty(vmess.remarks)) {
|
if (TextUtils.isEmpty(vmess.remarks)) {
|
||||||
toast(R.string.server_lab_remarks)
|
toast(R.string.server_lab_remarks)
|
||||||
saveSuccess = false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (AngConfigManager.addCustomServer(vmess, edit_index) == 0) {
|
if (AngConfigManager.addCustomServer(vmess, edit_index) == 0) {
|
||||||
toast(R.string.toast_success)
|
toast(R.string.toast_success)
|
||||||
saveSuccess = true
|
|
||||||
} else {
|
|
||||||
toast(R.string.toast_failure)
|
|
||||||
saveSuccess = false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
Gson().fromJson<Object>(tv_content.text.toString(), Object::class.java)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
toast(R.string.toast_malformed_josn)
|
|
||||||
saveSuccess = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (saveSuccess) {
|
|
||||||
//update config
|
|
||||||
defaultDPreference.setPrefString(AppConfig.ANG_CONFIG + edit_guid, tv_content.text.toString())
|
|
||||||
finish()
|
finish()
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
|
toast(R.string.toast_failure)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import android.content.Intent
|
|||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.preference.*
|
import android.preference.CheckBoxPreference
|
||||||
import com.v2ray.ang.AngApplication
|
import android.preference.EditTextPreference
|
||||||
|
import android.preference.Preference
|
||||||
|
import android.preference.PreferenceFragment
|
||||||
import com.v2ray.ang.BuildConfig
|
import com.v2ray.ang.BuildConfig
|
||||||
//import com.v2ray.ang.InappBuyActivity
|
//import com.v2ray.ang.InappBuyActivity
|
||||||
import com.v2ray.ang.R
|
import com.v2ray.ang.R
|
||||||
@@ -27,7 +29,6 @@ class SettingsActivity : BaseActivity() {
|
|||||||
// const val PREF_MUX_ENAimport libv2ray.Libv2rayBLED = "pref_mux_enabled"
|
// const val PREF_MUX_ENAimport libv2ray.Libv2rayBLED = "pref_mux_enabled"
|
||||||
const val PREF_SPEED_ENABLED = "pref_speed_enabled"
|
const val PREF_SPEED_ENABLED = "pref_speed_enabled"
|
||||||
const val PREF_SNIFFING_ENABLED = "pref_sniffing_enabled"
|
const val PREF_SNIFFING_ENABLED = "pref_sniffing_enabled"
|
||||||
const val PREF_PROXY_SHARING = "pref_proxy_sharing_enabled"
|
|
||||||
const val PREF_LOCAL_DNS_ENABLED = "pref_local_dns_enabled"
|
const val PREF_LOCAL_DNS_ENABLED = "pref_local_dns_enabled"
|
||||||
const val PREF_REMOTE_DNS = "pref_remote_dns"
|
const val PREF_REMOTE_DNS = "pref_remote_dns"
|
||||||
const val PREF_DOMESTIC_DNS = "pref_domestic_dns"
|
const val PREF_DOMESTIC_DNS = "pref_domestic_dns"
|
||||||
@@ -58,19 +59,12 @@ class SettingsActivity : BaseActivity() {
|
|||||||
|
|
||||||
class SettingsFragment : PreferenceFragment(), SharedPreferences.OnSharedPreferenceChangeListener {
|
class SettingsFragment : PreferenceFragment(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
val perAppProxy by lazy { findPreference(PREF_PER_APP_PROXY) as CheckBoxPreference }
|
val perAppProxy by lazy { findPreference(PREF_PER_APP_PROXY) as CheckBoxPreference }
|
||||||
val sppedEnabled by lazy { findPreference(PREF_SPEED_ENABLED) as CheckBoxPreference }
|
|
||||||
val sniffingEnabled by lazy { findPreference(PREF_SNIFFING_ENABLED) as CheckBoxPreference }
|
|
||||||
val proxySharing by lazy { findPreference(PREF_PROXY_SHARING) as CheckBoxPreference }
|
|
||||||
val domainStrategy by lazy { findPreference(PREF_ROUTING_DOMAIN_STRATEGY) as ListPreference }
|
|
||||||
val routingMode by lazy { findPreference(PREF_ROUTING_MODE) as ListPreference }
|
|
||||||
|
|
||||||
val forwardIpv6 by lazy { findPreference(PREF_FORWARD_IPV6) as CheckBoxPreference }
|
|
||||||
val enableLocalDns by lazy { findPreference(PREF_LOCAL_DNS_ENABLED) as CheckBoxPreference }
|
|
||||||
val domesticDns by lazy { findPreference(PREF_DOMESTIC_DNS) as EditTextPreference }
|
|
||||||
val remoteDns by lazy { findPreference(PREF_REMOTE_DNS) as EditTextPreference }
|
|
||||||
|
|
||||||
// val autoRestart by lazy { findPreference(PREF_AUTO_RESTART) as CheckBoxPreference }
|
// val autoRestart by lazy { findPreference(PREF_AUTO_RESTART) as CheckBoxPreference }
|
||||||
|
val remoteDns by lazy { findPreference(PREF_REMOTE_DNS) as EditTextPreference }
|
||||||
|
val domesticDns by lazy { findPreference(PREF_DOMESTIC_DNS) as EditTextPreference }
|
||||||
|
|
||||||
|
val enableLocalDns by lazy { findPreference(PREF_LOCAL_DNS_ENABLED) as CheckBoxPreference }
|
||||||
|
val forwardIpv6 by lazy { findPreference(PREF_FORWARD_IPV6) as CheckBoxPreference }
|
||||||
|
|
||||||
// val socksPort by lazy { findPreference(PREF_SOCKS_PORT) as EditTextPreference }
|
// val socksPort by lazy { findPreference(PREF_SOCKS_PORT) as EditTextPreference }
|
||||||
// val httpPort by lazy { findPreference(PREF_HTTP_PORT) as EditTextPreference }
|
// val httpPort by lazy { findPreference(PREF_HTTP_PORT) as EditTextPreference }
|
||||||
@@ -82,95 +76,14 @@ class SettingsActivity : BaseActivity() {
|
|||||||
// val tgGroup: Preference by lazy { findPreference(PREF_TG_GROUP) }
|
// val tgGroup: Preference by lazy { findPreference(PREF_TG_GROUP) }
|
||||||
val version: Preference by lazy { findPreference(PREF_VERSION) }
|
val version: Preference by lazy { findPreference(PREF_VERSION) }
|
||||||
|
|
||||||
private fun restartProxy() {
|
|
||||||
Utils.stopVService(activity)
|
|
||||||
Utils.startVService(activity)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isRunning(): Boolean {
|
|
||||||
return Utils.isServiceRun(activity, "com.v2ray.ang.service.V2RayVpnService")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
addPreferencesFromResource(R.xml.pref_settings)
|
addPreferencesFromResource(R.xml.pref_settings)
|
||||||
var app = activity.application as AngApplication
|
|
||||||
|
|
||||||
perAppProxy.setOnPreferenceClickListener {
|
|
||||||
if (isRunning()) {
|
|
||||||
Utils.stopVService(activity)
|
|
||||||
}
|
|
||||||
startActivity<PerAppProxyActivity>()
|
|
||||||
perAppProxy.isChecked = true
|
|
||||||
true
|
|
||||||
}
|
|
||||||
sppedEnabled.setOnPreferenceClickListener {
|
|
||||||
if (isRunning())
|
|
||||||
restartProxy()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
sniffingEnabled.setOnPreferenceClickListener {
|
|
||||||
if (isRunning())
|
|
||||||
restartProxy()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
proxySharing.setOnPreferenceClickListener {
|
|
||||||
if (proxySharing.isChecked)
|
|
||||||
toast(R.string.toast_warning_pref_proxysharing)
|
|
||||||
if (isRunning())
|
|
||||||
restartProxy()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
domainStrategy.setOnPreferenceChangeListener { _, _ ->
|
|
||||||
if (isRunning())
|
|
||||||
restartProxy()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
routingMode.setOnPreferenceChangeListener { _, _ ->
|
|
||||||
if (isRunning())
|
|
||||||
restartProxy()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
routingCustom.onClick {
|
routingCustom.onClick {
|
||||||
if (isRunning())
|
|
||||||
Utils.stopVService(activity)
|
|
||||||
startActivity<RoutingSettingsActivity>()
|
startActivity<RoutingSettingsActivity>()
|
||||||
}
|
}
|
||||||
|
|
||||||
forwardIpv6.setOnPreferenceClickListener {
|
|
||||||
if (isRunning())
|
|
||||||
restartProxy()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
enableLocalDns.setOnPreferenceClickListener {
|
|
||||||
if (isRunning())
|
|
||||||
restartProxy()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
domesticDns.setOnPreferenceChangeListener { preference, any ->
|
|
||||||
// domesticDns.summary = any as String
|
|
||||||
val nval = any as String
|
|
||||||
domesticDns.summary = if (nval == "") AppConfig.DNS_DIRECT else nval
|
|
||||||
if (isRunning())
|
|
||||||
restartProxy()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
remoteDns.setOnPreferenceChangeListener { preference, any ->
|
|
||||||
// remoteDns.summary = any as String
|
|
||||||
val nval = any as String
|
|
||||||
remoteDns.summary = if (nval == "") AppConfig.DNS_AGENT else nval
|
|
||||||
if (isRunning())
|
|
||||||
restartProxy()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
// donate.onClick {
|
// donate.onClick {
|
||||||
// startActivity<InappBuyActivity>()
|
// startActivity<InappBuyActivity>()
|
||||||
// }
|
// }
|
||||||
@@ -197,7 +110,24 @@ class SettingsActivity : BaseActivity() {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
perAppProxy.setOnPreferenceClickListener {
|
||||||
|
startActivity<PerAppProxyActivity>()
|
||||||
|
perAppProxy.isChecked = true
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteDns.setOnPreferenceChangeListener { preference, any ->
|
||||||
|
// remoteDns.summary = any as String
|
||||||
|
val nval = any as String
|
||||||
|
remoteDns.summary = if (nval == "") AppConfig.DNS_AGENT else nval
|
||||||
|
true
|
||||||
|
}
|
||||||
|
domesticDns.setOnPreferenceChangeListener { preference, any ->
|
||||||
|
// domesticDns.summary = any as String
|
||||||
|
val nval = any as String
|
||||||
|
domesticDns.summary = if (nval == "") AppConfig.DNS_DIRECT else nval
|
||||||
|
true
|
||||||
|
}
|
||||||
// socksPort.setOnPreferenceChangeListener { preference, any ->
|
// socksPort.setOnPreferenceChangeListener { preference, any ->
|
||||||
// socksPort.summary = any as String
|
// socksPort.summary = any as String
|
||||||
// true
|
// true
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.v2ray.ang.util
|
|||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
import android.util.Log
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.v2ray.ang.AngApplication
|
import com.v2ray.ang.AngApplication
|
||||||
import com.v2ray.ang.AppConfig
|
import com.v2ray.ang.AppConfig
|
||||||
@@ -15,9 +16,12 @@ import com.v2ray.ang.AppConfig.VMESS_PROTOCOL
|
|||||||
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.VmessQRCode
|
import com.v2ray.ang.dto.VmessQRCode
|
||||||
import java.net.URI
|
import com.v2ray.ang.extension.defaultDPreference
|
||||||
|
import org.jetbrains.anko.toast
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.net.*
|
||||||
|
import java.math.BigInteger
|
||||||
|
|
||||||
object AngConfigManager {
|
object AngConfigManager {
|
||||||
private lateinit var app: AngApplication
|
private lateinit var app: AngApplication
|
||||||
@@ -100,7 +104,16 @@ object AngConfigManager {
|
|||||||
angConfig.vmess.removeAt(index)
|
angConfig.vmess.removeAt(index)
|
||||||
|
|
||||||
//移除的是活动的
|
//移除的是活动的
|
||||||
adjustIndexForRemovalAt(index)
|
if (angConfig.index == index) {
|
||||||
|
if (angConfig.vmess.count() > 0) {
|
||||||
|
angConfig.index = 0
|
||||||
|
} else {
|
||||||
|
angConfig.index = -1
|
||||||
|
}
|
||||||
|
} else if (index < angConfig.index)//移除活动之前的
|
||||||
|
{
|
||||||
|
angConfig.index--
|
||||||
|
}
|
||||||
|
|
||||||
storeConfigFile()
|
storeConfigFile()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -110,19 +123,6 @@ object AngConfigManager {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun adjustIndexForRemovalAt(index: Int) {
|
|
||||||
if (angConfig.index == index) {
|
|
||||||
if (angConfig.vmess.count() > 0) {
|
|
||||||
angConfig.index = 0
|
|
||||||
} else {
|
|
||||||
angConfig.index = -1
|
|
||||||
}
|
|
||||||
} else if (index < angConfig.index)//移除活动之前的
|
|
||||||
{
|
|
||||||
angConfig.index--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun swapServer(fromPosition: Int, toPosition: Int): Int {
|
fun swapServer(fromPosition: Int, toPosition: Int): Int {
|
||||||
try {
|
try {
|
||||||
Collections.swap(angConfig.vmess, fromPosition, toPosition)
|
Collections.swap(angConfig.vmess, fromPosition, toPosition)
|
||||||
@@ -133,7 +133,7 @@ object AngConfigManager {
|
|||||||
} else if (index == toPosition) {
|
} else if (index == toPosition) {
|
||||||
angConfig.index = fromPosition
|
angConfig.index = fromPosition
|
||||||
}
|
}
|
||||||
//storeConfigFile()
|
storeConfigFile()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
return -1
|
return -1
|
||||||
@@ -147,15 +147,13 @@ object AngConfigManager {
|
|||||||
fun setActiveServer(index: Int): Int {
|
fun setActiveServer(index: Int): Int {
|
||||||
try {
|
try {
|
||||||
if (index < 0 || index > angConfig.vmess.count() - 1) {
|
if (index < 0 || index > angConfig.vmess.count() - 1) {
|
||||||
app.curIndex = -1
|
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
angConfig.index = index
|
angConfig.index = index
|
||||||
app.curIndex = index
|
|
||||||
storeConfigFile()
|
storeConfigFile()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
app.curIndex = -1
|
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
@@ -241,7 +239,7 @@ object AngConfigManager {
|
|||||||
/**
|
/**
|
||||||
* import config form qrcode or...
|
* import config form qrcode or...
|
||||||
*/
|
*/
|
||||||
fun importConfig(server: String?, subid: String, removedSelectedServer: AngConfig.VmessBean?): Int {
|
fun importConfig(server: String?, subid: String): Int {
|
||||||
try {
|
try {
|
||||||
if (server == null || TextUtils.isEmpty(server)) {
|
if (server == null || TextUtils.isEmpty(server)) {
|
||||||
return R.string.toast_none_data
|
return R.string.toast_none_data
|
||||||
@@ -252,11 +250,7 @@ object AngConfigManager {
|
|||||||
if (server.startsWith(VMESS_PROTOCOL)) {
|
if (server.startsWith(VMESS_PROTOCOL)) {
|
||||||
|
|
||||||
val indexSplit = server.indexOf("?")
|
val indexSplit = server.indexOf("?")
|
||||||
val newVmess = tryParseNewVmess(server)
|
if (indexSplit > 0) {
|
||||||
if (newVmess != null) {
|
|
||||||
vmess = newVmess
|
|
||||||
vmess.subid = subid
|
|
||||||
} else if (indexSplit > 0) {
|
|
||||||
vmess = ResolveVmess4Kitsunebi(server)
|
vmess = ResolveVmess4Kitsunebi(server)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -365,12 +359,6 @@ object AngConfigManager {
|
|||||||
} else {
|
} else {
|
||||||
return R.string.toast_incorrect_protocol
|
return R.string.toast_incorrect_protocol
|
||||||
}
|
}
|
||||||
if (removedSelectedServer != null &&
|
|
||||||
vmess.subid.equals(removedSelectedServer.subid) &&
|
|
||||||
vmess.address.equals(removedSelectedServer.address) &&
|
|
||||||
vmess.port.equals(removedSelectedServer.port)) {
|
|
||||||
setActiveServer(configs.vmess.count() - 1)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
return -1
|
return -1
|
||||||
@@ -378,61 +366,6 @@ object AngConfigManager {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tryParseNewVmess(uri: String): AngConfig.VmessBean? {
|
|
||||||
return runCatching {
|
|
||||||
val uri = URI(uri)
|
|
||||||
check(uri.scheme == "vmess")
|
|
||||||
val (_, protocol, tlsStr, uuid, alterId) =
|
|
||||||
Regex("(tcp|http|ws|kcp|quic)(\\+tls)?:([0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12})-([0-9]+)")
|
|
||||||
.matchEntire(uri.userInfo)?.groupValues
|
|
||||||
?: error("parse user info fail.")
|
|
||||||
val tls = tlsStr.isNotBlank()
|
|
||||||
val queryParam = uri.rawQuery.split("&")
|
|
||||||
.map { it.split("=").let { (k, v) -> k to URLDecoder.decode(v, "utf-8")!! } }
|
|
||||||
.toMap()
|
|
||||||
val vmess = AngConfig.VmessBean()
|
|
||||||
vmess.address = uri.host
|
|
||||||
vmess.port = uri.port
|
|
||||||
vmess.id = uuid
|
|
||||||
vmess.alterId = alterId.toInt()
|
|
||||||
vmess.streamSecurity = if (tls) "tls" else ""
|
|
||||||
vmess.remarks = uri.fragment
|
|
||||||
vmess.security = "auto"
|
|
||||||
|
|
||||||
// TODO: allowInsecure not supported
|
|
||||||
|
|
||||||
when (protocol) {
|
|
||||||
"tcp" -> {
|
|
||||||
vmess.network = "tcp"
|
|
||||||
vmess.headerType = queryParam["type"] ?: "none"
|
|
||||||
vmess.requestHost = queryParam["host"] ?: ""
|
|
||||||
}
|
|
||||||
"http" -> {
|
|
||||||
vmess.network = "h2"
|
|
||||||
vmess.path = queryParam["path"]?.takeIf { it.trim() != "/" } ?: ""
|
|
||||||
vmess.requestHost = queryParam["host"]?.split("|")?.get(0) ?: ""
|
|
||||||
}
|
|
||||||
"ws" -> {
|
|
||||||
vmess.network = "ws"
|
|
||||||
vmess.path = queryParam["path"]?.takeIf { it.trim() != "/" } ?: ""
|
|
||||||
vmess.requestHost = queryParam["host"]?.split("|")?.get(0) ?: ""
|
|
||||||
}
|
|
||||||
"kcp" -> {
|
|
||||||
vmess.network = "kcp"
|
|
||||||
vmess.headerType = queryParam["type"] ?: "none"
|
|
||||||
vmess.path = queryParam["seed"] ?: ""
|
|
||||||
}
|
|
||||||
"quic" -> {
|
|
||||||
vmess.network = "quic"
|
|
||||||
vmess.requestHost = queryParam["security"] ?: "none"
|
|
||||||
vmess.headerType = queryParam["type"] ?: "none"
|
|
||||||
vmess.path = queryParam["key"] ?: ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vmess
|
|
||||||
}.getOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ResolveVmess4Kitsunebi(server: String): AngConfig.VmessBean {
|
private fun ResolveVmess4Kitsunebi(server: String): AngConfig.VmessBean {
|
||||||
|
|
||||||
val vmess = AngConfig.VmessBean()
|
val vmess = AngConfig.VmessBean()
|
||||||
@@ -793,11 +726,6 @@ object AngConfigManager {
|
|||||||
if (servers == null) {
|
if (servers == null) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
val removedSelectedServer =
|
|
||||||
if (!TextUtils.isEmpty(subid) && configs.vmess.count() > 0 && configs.vmess[configs.index].subid.equals(subid))
|
|
||||||
configs.vmess[configs.index]
|
|
||||||
else
|
|
||||||
null
|
|
||||||
removeServerViaSubid(subid)
|
removeServerViaSubid(subid)
|
||||||
|
|
||||||
// var servers = server
|
// var servers = server
|
||||||
@@ -808,7 +736,7 @@ object AngConfigManager {
|
|||||||
var count = 0
|
var count = 0
|
||||||
servers.lines()
|
servers.lines()
|
||||||
.forEach {
|
.forEach {
|
||||||
val resId = importConfig(it, subid, removedSelectedServer)
|
val resId = importConfig(it, subid)
|
||||||
if (resId == 0) {
|
if (resId == 0) {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
@@ -848,7 +776,6 @@ object AngConfigManager {
|
|||||||
for (k in configs.vmess.count() - 1 downTo 0) {
|
for (k in configs.vmess.count() - 1 downTo 0) {
|
||||||
if (configs.vmess[k].subid.equals(subid)) {
|
if (configs.vmess[k].subid.equals(subid)) {
|
||||||
angConfig.vmess.removeAt(k)
|
angConfig.vmess.removeAt(k)
|
||||||
adjustIndexForRemovalAt(k)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,4 +821,4 @@ object AngConfigManager {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ object AppManagerUtil {
|
|||||||
val apps = ArrayList<AppInfo>()
|
val apps = ArrayList<AppInfo>()
|
||||||
|
|
||||||
for (pkg in packages) {
|
for (pkg in packages) {
|
||||||
if (!pkg.hasInternetPermission && pkg.packageName != "android") continue
|
if (!pkg.hasInternetPermission) continue
|
||||||
|
|
||||||
val applicationInfo = pkg.applicationInfo
|
val applicationInfo = pkg.applicationInfo
|
||||||
|
|
||||||
@@ -40,4 +40,4 @@ object AppManagerUtil {
|
|||||||
val permissions = requestedPermissions
|
val permissions = requestedPermissions
|
||||||
return permissions?.any { it == Manifest.permission.INTERNET } ?: false
|
return permissions?.any { it == Manifest.permission.INTERNET } ?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,11 +27,9 @@ import com.v2ray.ang.AngApplication
|
|||||||
import com.v2ray.ang.AppConfig
|
import com.v2ray.ang.AppConfig
|
||||||
import com.v2ray.ang.R
|
import com.v2ray.ang.R
|
||||||
import com.v2ray.ang.extension.responseLength
|
import com.v2ray.ang.extension.responseLength
|
||||||
import com.v2ray.ang.extension.v2RayApplication
|
|
||||||
import com.v2ray.ang.service.V2RayVpnService
|
import com.v2ray.ang.service.V2RayVpnService
|
||||||
import com.v2ray.ang.ui.SettingsActivity
|
import com.v2ray.ang.ui.SettingsActivity
|
||||||
import kotlinx.android.synthetic.main.activity_logcat.*
|
import kotlinx.android.synthetic.main.activity_logcat.*
|
||||||
import kotlinx.coroutines.isActive
|
|
||||||
import me.dozen.dpreference.DPreference
|
import me.dozen.dpreference.DPreference
|
||||||
import org.jetbrains.anko.toast
|
import org.jetbrains.anko.toast
|
||||||
import org.jetbrains.anko.uiThread
|
import org.jetbrains.anko.uiThread
|
||||||
@@ -45,13 +43,10 @@ import java.util.regex.Pattern
|
|||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import libv2ray.Libv2ray
|
import libv2ray.Libv2ray
|
||||||
import kotlin.coroutines.coroutineContext
|
|
||||||
|
|
||||||
|
|
||||||
object Utils {
|
object Utils {
|
||||||
|
|
||||||
val tcpTestingSockets = ArrayList<Socket?>()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert string to editalbe for kotlin
|
* convert string to editalbe for kotlin
|
||||||
*
|
*
|
||||||
@@ -316,11 +311,7 @@ object Utils {
|
|||||||
* startVService
|
* startVService
|
||||||
*/
|
*/
|
||||||
fun startVService(context: Context): Boolean {
|
fun startVService(context: Context): Boolean {
|
||||||
if (context.v2RayApplication.defaultDPreference.getPrefBoolean(SettingsActivity.PREF_PROXY_SHARING, false)) {
|
context.toast(R.string.toast_services_start)
|
||||||
context.toast(R.string.toast_warning_pref_proxysharing_short)
|
|
||||||
}else{
|
|
||||||
context.toast(R.string.toast_services_start)
|
|
||||||
}
|
|
||||||
if (AngConfigManager.genStoreV2rayConfig(-1)) {
|
if (AngConfigManager.genStoreV2rayConfig(-1)) {
|
||||||
val configContent = AngConfigManager.currGeneratedV2rayConfig()
|
val configContent = AngConfigManager.currGeneratedV2rayConfig()
|
||||||
val configType = AngConfigManager.currConfigType()
|
val configType = AngConfigManager.currConfigType()
|
||||||
@@ -344,7 +335,6 @@ object Utils {
|
|||||||
*/
|
*/
|
||||||
fun startVService(context: Context, guid: String): Boolean {
|
fun startVService(context: Context, guid: String): Boolean {
|
||||||
val index = AngConfigManager.getIndexViaGuid(guid)
|
val index = AngConfigManager.getIndexViaGuid(guid)
|
||||||
context.v2RayApplication.curIndex=index
|
|
||||||
return startVService(context, index)
|
return startVService(context, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,13 +477,10 @@ object Utils {
|
|||||||
/**
|
/**
|
||||||
* tcping
|
* tcping
|
||||||
*/
|
*/
|
||||||
suspend fun tcping(url: String, port: Int): String {
|
fun tcping(url: String, port: Int): String {
|
||||||
var time = -1L
|
var time = -1L
|
||||||
for (k in 0 until 2) {
|
for (k in 0 until 2) {
|
||||||
val one = socketConnectTime(url, port)
|
val one = socketConnectTime(url, port)
|
||||||
if (!coroutineContext.isActive) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (one != -1L )
|
if (one != -1L )
|
||||||
if(time == -1L || one < time) {
|
if(time == -1L || one < time) {
|
||||||
time = one
|
time = one
|
||||||
@@ -504,35 +491,19 @@ object Utils {
|
|||||||
|
|
||||||
fun socketConnectTime(url: String, port: Int): Long {
|
fun socketConnectTime(url: String, port: Int): Long {
|
||||||
try {
|
try {
|
||||||
val socket = Socket()
|
|
||||||
synchronized(this) {
|
|
||||||
tcpTestingSockets.add(socket)
|
|
||||||
}
|
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
socket.connect(InetSocketAddress(url, port))
|
val socket = Socket(url, port)
|
||||||
val time = System.currentTimeMillis() - start
|
val time = System.currentTimeMillis() - start
|
||||||
synchronized(this) {
|
|
||||||
tcpTestingSockets.remove(socket)
|
|
||||||
}
|
|
||||||
socket.close()
|
socket.close()
|
||||||
return time
|
return time
|
||||||
} catch (e: UnknownHostException) {
|
} catch (e: UnknownHostException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
Log.d(AppConfig.ANG_PACKAGE, "socketConnectTime IOException: $e")
|
e.printStackTrace()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun closeAllTcpSockets() {
|
|
||||||
synchronized(this) {
|
|
||||||
tcpTestingSockets.forEach {
|
|
||||||
it?.close()
|
|
||||||
}
|
|
||||||
tcpTestingSockets.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.v2ray.ang.AngApplication
|
|||||||
import com.v2ray.ang.AppConfig
|
import com.v2ray.ang.AppConfig
|
||||||
import com.v2ray.ang.dto.AngConfig.VmessBean
|
import com.v2ray.ang.dto.AngConfig.VmessBean
|
||||||
import com.v2ray.ang.dto.V2rayConfig
|
import com.v2ray.ang.dto.V2rayConfig
|
||||||
|
import com.v2ray.ang.extension.defaultDPreference
|
||||||
import com.v2ray.ang.ui.SettingsActivity
|
import com.v2ray.ang.ui.SettingsActivity
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
@@ -128,12 +129,6 @@ object V2rayConfigUtil {
|
|||||||
*/
|
*/
|
||||||
private fun inbounds(vmess: VmessBean, v2rayConfig: V2rayConfig, app: AngApplication): Boolean {
|
private fun inbounds(vmess: VmessBean, v2rayConfig: V2rayConfig, app: AngApplication): Boolean {
|
||||||
try {
|
try {
|
||||||
v2rayConfig.inbounds.forEach { curInbound ->
|
|
||||||
if (!app.defaultDPreference.getPrefBoolean(SettingsActivity.PREF_PROXY_SHARING, false)) {
|
|
||||||
//bind all inbounds to localhost if the user requests
|
|
||||||
curInbound.listen = "127.0.0.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v2rayConfig.inbounds[0].port = 10808
|
v2rayConfig.inbounds[0].port = 10808
|
||||||
// val socksPort = Utils.parseInt(app.defaultDPreference.getPrefString(SettingsActivity.PREF_SOCKS_PORT, "10808"))
|
// val socksPort = Utils.parseInt(app.defaultDPreference.getPrefString(SettingsActivity.PREF_SOCKS_PORT, "10808"))
|
||||||
// val lanconnPort = Utils.parseInt(app.defaultDPreference.getPrefString(SettingsActivity.PREF_HTTP_PORT, ""))
|
// val lanconnPort = Utils.parseInt(app.defaultDPreference.getPrefString(SettingsActivity.PREF_HTTP_PORT, ""))
|
||||||
@@ -245,7 +240,7 @@ object V2rayConfigUtil {
|
|||||||
//streamSettings
|
//streamSettings
|
||||||
when (streamSettings.network) {
|
when (streamSettings.network) {
|
||||||
"kcp" -> {
|
"kcp" -> {
|
||||||
val kcpsettings = V2rayConfig.OutboundBean.StreamSettingsBean.KcpSettingsBean()
|
val kcpsettings = V2rayConfig.OutboundBean.StreamSettingsBean.KcpsettingsBean()
|
||||||
kcpsettings.mtu = 1350
|
kcpsettings.mtu = 1350
|
||||||
kcpsettings.tti = 50
|
kcpsettings.tti = 50
|
||||||
kcpsettings.uplinkCapacity = 12
|
kcpsettings.uplinkCapacity = 12
|
||||||
@@ -253,33 +248,34 @@ object V2rayConfigUtil {
|
|||||||
kcpsettings.congestion = false
|
kcpsettings.congestion = false
|
||||||
kcpsettings.readBufferSize = 1
|
kcpsettings.readBufferSize = 1
|
||||||
kcpsettings.writeBufferSize = 1
|
kcpsettings.writeBufferSize = 1
|
||||||
kcpsettings.header = V2rayConfig.OutboundBean.StreamSettingsBean.KcpSettingsBean.HeaderBean()
|
kcpsettings.header = V2rayConfig.OutboundBean.StreamSettingsBean.KcpsettingsBean.HeaderBean()
|
||||||
kcpsettings.header.type = vmess.headerType
|
kcpsettings.header.type = vmess.headerType
|
||||||
streamSettings.kcpSettings = kcpsettings
|
streamSettings.kcpsettings = kcpsettings
|
||||||
}
|
}
|
||||||
"ws" -> {
|
"ws" -> {
|
||||||
val wssettings = V2rayConfig.OutboundBean.StreamSettingsBean.WsSettingsBean()
|
val wssettings = V2rayConfig.OutboundBean.StreamSettingsBean.WssettingsBean()
|
||||||
|
wssettings.connectionReuse = true
|
||||||
val host = vmess.requestHost.trim()
|
val host = vmess.requestHost.trim()
|
||||||
val path = vmess.path.trim()
|
val path = vmess.path.trim()
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(host)) {
|
if (!TextUtils.isEmpty(host)) {
|
||||||
wssettings.headers = V2rayConfig.OutboundBean.StreamSettingsBean.WsSettingsBean.HeadersBean()
|
wssettings.headers = V2rayConfig.OutboundBean.StreamSettingsBean.WssettingsBean.HeadersBean()
|
||||||
wssettings.headers.Host = host
|
wssettings.headers.Host = host
|
||||||
}
|
}
|
||||||
if (!TextUtils.isEmpty(path)) {
|
if (!TextUtils.isEmpty(path)) {
|
||||||
wssettings.path = path
|
wssettings.path = path
|
||||||
}
|
}
|
||||||
streamSettings.wsSettings = wssettings
|
streamSettings.wssettings = wssettings
|
||||||
|
|
||||||
val tlssettings = V2rayConfig.OutboundBean.StreamSettingsBean.TlsSettingsBean()
|
val tlssettings = V2rayConfig.OutboundBean.StreamSettingsBean.TlssettingsBean()
|
||||||
tlssettings.allowInsecure = true
|
tlssettings.allowInsecure = true
|
||||||
if (!TextUtils.isEmpty(host)) {
|
if (!TextUtils.isEmpty(host)) {
|
||||||
tlssettings.serverName = host
|
tlssettings.serverName = host
|
||||||
}
|
}
|
||||||
streamSettings.tlsSettings = tlssettings
|
streamSettings.tlssettings = tlssettings
|
||||||
}
|
}
|
||||||
"h2" -> {
|
"h2" -> {
|
||||||
val httpsettings = V2rayConfig.OutboundBean.StreamSettingsBean.HttpSettingsBean()
|
val httpsettings = V2rayConfig.OutboundBean.StreamSettingsBean.HttpsettingsBean()
|
||||||
val host = vmess.requestHost.trim()
|
val host = vmess.requestHost.trim()
|
||||||
val path = vmess.path.trim()
|
val path = vmess.path.trim()
|
||||||
|
|
||||||
@@ -287,30 +283,31 @@ object V2rayConfigUtil {
|
|||||||
httpsettings.host = host.split(",").map { it.trim() }
|
httpsettings.host = host.split(",").map { it.trim() }
|
||||||
}
|
}
|
||||||
httpsettings.path = path
|
httpsettings.path = path
|
||||||
streamSettings.httpSettings = httpsettings
|
streamSettings.httpsettings = httpsettings
|
||||||
|
|
||||||
val tlssettings = V2rayConfig.OutboundBean.StreamSettingsBean.TlsSettingsBean()
|
val tlssettings = V2rayConfig.OutboundBean.StreamSettingsBean.TlssettingsBean()
|
||||||
tlssettings.allowInsecure = true
|
tlssettings.allowInsecure = true
|
||||||
streamSettings.tlsSettings = tlssettings
|
streamSettings.tlssettings = tlssettings
|
||||||
}
|
}
|
||||||
"quic" -> {
|
"quic" -> {
|
||||||
val quicsettings = V2rayConfig.OutboundBean.StreamSettingsBean.QuicSettingBean()
|
val quicsettings = V2rayConfig.OutboundBean.StreamSettingsBean.QuicsettingBean()
|
||||||
val host = vmess.requestHost.trim()
|
val host = vmess.requestHost.trim()
|
||||||
val path = vmess.path.trim()
|
val path = vmess.path.trim()
|
||||||
|
|
||||||
quicsettings.security = host
|
quicsettings.security = host
|
||||||
quicsettings.key = path
|
quicsettings.key = path
|
||||||
|
|
||||||
quicsettings.header = V2rayConfig.OutboundBean.StreamSettingsBean.QuicSettingBean.HeaderBean()
|
quicsettings.header = V2rayConfig.OutboundBean.StreamSettingsBean.QuicsettingBean.HeaderBean()
|
||||||
quicsettings.header.type = vmess.headerType
|
quicsettings.header.type = vmess.headerType
|
||||||
|
|
||||||
streamSettings.quicSettings = quicsettings
|
streamSettings.quicsettings = quicsettings
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
//tcp带http伪装
|
//tcp带http伪装
|
||||||
if (vmess.headerType == "http") {
|
if (vmess.headerType == "http") {
|
||||||
val tcpSettings = V2rayConfig.OutboundBean.StreamSettingsBean.TcpSettingsBean()
|
val tcpSettings = V2rayConfig.OutboundBean.StreamSettingsBean.TcpsettingsBean()
|
||||||
tcpSettings.header = V2rayConfig.OutboundBean.StreamSettingsBean.TcpSettingsBean.HeaderBean()
|
tcpSettings.connectionReuse = true
|
||||||
|
tcpSettings.header = V2rayConfig.OutboundBean.StreamSettingsBean.TcpsettingsBean.HeaderBean()
|
||||||
tcpSettings.header.type = vmess.headerType
|
tcpSettings.header.type = vmess.headerType
|
||||||
|
|
||||||
// if (requestObj.has("headers")
|
// if (requestObj.has("headers")
|
||||||
@@ -550,7 +547,7 @@ object V2rayConfigUtil {
|
|||||||
mux = null))
|
mux = null))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNS routing
|
// DNS routing
|
||||||
v2rayConfig.routing.rules.add(0, V2rayConfig.RoutingBean.RulesBean(
|
v2rayConfig.routing.rules.add(0, V2rayConfig.RoutingBean.RulesBean(
|
||||||
type = "field",
|
type = "field",
|
||||||
outboundTag = AppConfig.TAG_DIRECT,
|
outboundTag = AppConfig.TAG_DIRECT,
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:state_pressed="true"
|
|
||||||
android:drawable="@color/secondary_text" />
|
|
||||||
<item android:state_focused="true"
|
|
||||||
android:drawable="@color/secondary_text" />
|
|
||||||
<item android:state_hovered="true"
|
|
||||||
android:drawable="@color/secondary_text" />
|
|
||||||
<item android:drawable="@color/colorPrimary_text" />
|
|
||||||
</selector>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<solid android:color="@color/accent"/>
|
|
||||||
<corners android:radius="20dp"/>
|
|
||||||
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
|
|
||||||
</shape>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<solid android:color="#009963"/>
|
|
||||||
<corners android:radius="20dp"/>
|
|
||||||
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
|
|
||||||
</shape>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -54,10 +54,8 @@
|
|||||||
android:id="@+id/layout_test"
|
android:id="@+id/layout_test"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/connection_test_height"
|
android:layout_height="@dimen/connection_test_height"
|
||||||
android:background="@drawable/background_test_button"
|
android:background="@color/colorPrimary_text"
|
||||||
android:gravity="center|left"
|
android:gravity="center|left">
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_test_state"
|
android:id="@+id/tv_test_state"
|
||||||
@@ -94,8 +92,6 @@
|
|||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:src="@drawable/ic_v_idle"
|
android:src="@drawable/ic_v_idle"
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
app:layout_anchorGravity="bottom|right|end" />
|
app:layout_anchorGravity="bottom|right|end" />
|
||||||
|
|
||||||
</com.github.jorgecastilloprz.FABProgressCircle>
|
</com.github.jorgecastilloprz.FABProgressCircle>
|
||||||
|
|||||||
@@ -68,15 +68,20 @@
|
|||||||
android:text="@string/server_lab_content"
|
android:text="@string/server_lab_content"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
|
||||||
|
|
||||||
<EditText
|
<TextView
|
||||||
android:id="@+id/tv_content"
|
android:id="@+id/tv_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/layout_margin_top_height"
|
android:layout_marginTop="@dimen/layout_margin_top_height"
|
||||||
android:text="" />
|
android:text="" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_margin_top_height"
|
||||||
|
android:layout_marginBottom="@dimen/layout_margin_top_height"
|
||||||
|
android:orientation="vertical" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
@@ -2,10 +2,7 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical">
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true">
|
|
||||||
|
|
||||||
<android.support.v7.widget.AppCompatImageView
|
<android.support.v7.widget.AppCompatImageView
|
||||||
android:id="@+id/icon"
|
android:id="@+id/icon"
|
||||||
@@ -43,7 +40,6 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:clickable="false"
|
android:clickable="false"
|
||||||
android:focusable="false"
|
|
||||||
android:paddingStart="2dp"
|
android:paddingStart="2dp"
|
||||||
android:paddingLeft="2dp"
|
android:paddingLeft="2dp"
|
||||||
android:paddingEnd="6dp"
|
android:paddingEnd="6dp"
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="3dp"
|
android:layout_margin="3dp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal"
|
||||||
card_view:cardCornerRadius="5dp">
|
card_view:cardCornerRadius="5dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -17,11 +21,7 @@
|
|||||||
android:layout_height="@dimen/server_height"
|
android:layout_height="@dimen/server_height"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal">
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:nextFocusRight="@+id/layout_share">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -111,14 +111,10 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/layout_share"
|
android:id="@+id/layout_share"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="@dimen/server_height"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="@dimen/layout_margin_spacing"
|
android:paddingEnd="@dimen/layout_margin_right_height">
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:nextFocusLeft="@+id/info_container">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -130,13 +126,10 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/layout_edit"
|
android:id="@+id/layout_edit"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="@dimen/server_height"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="@dimen/layout_margin_spacing"
|
android:paddingEnd="@dimen/layout_margin_right_height">
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="@dimen/png_height"
|
android:layout_width="@dimen/png_height"
|
||||||
@@ -148,13 +141,10 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/layout_remove"
|
android:id="@+id/layout_remove"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="@dimen/server_height"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="@dimen/layout_margin_spacing"
|
android:paddingEnd="@dimen/layout_margin_right_height">
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="@dimen/png_height"
|
android:layout_width="@dimen/png_height"
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
android:gravity="center_vertical">
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/item_cardview"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="3dp"
|
android:layout_margin="3dp"
|
||||||
@@ -14,8 +13,7 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:foreground="?android:attr/selectableItemBackground"
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
card_view:cardCornerRadius="5dp"
|
card_view:cardCornerRadius="5dp">
|
||||||
android:nextFocusRight="@+id/layout_edit">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/info_container"
|
android:id="@+id/info_container"
|
||||||
@@ -64,14 +62,11 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/layout_share"
|
android:id="@+id/layout_share"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="@dimen/server_height"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="@dimen/layout_margin_spacing"
|
android:paddingEnd="@dimen/layout_margin_right_height"
|
||||||
android:visibility="invisible"
|
android:visibility="invisible">
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="@dimen/png_height"
|
android:layout_width="@dimen/png_height"
|
||||||
@@ -83,14 +78,10 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/layout_edit"
|
android:id="@+id/layout_edit"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="@dimen/server_height"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="@dimen/layout_margin_spacing"
|
android:paddingEnd="@dimen/layout_margin_right_height">
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:nextFocusLeft="@+id/item_cardview">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="@dimen/png_height"
|
android:layout_width="@dimen/png_height"
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:id="@+id/layout_switch"
|
android:id="@+id/layout_switch"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -7,9 +14,16 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:padding="10dp"
|
android:src="@mipmap/ic_launcher" />
|
||||||
android:src="@drawable/ic_v" />
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="@string/app_widget_name"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||||
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -4,7 +4,12 @@
|
|||||||
tools:showIn="navigation_view">
|
tools:showIn="navigation_view">
|
||||||
|
|
||||||
<group
|
<group
|
||||||
android:id="@+id/group_main">
|
android:id="@+id/group_main"
|
||||||
|
android:checkableBehavior="single">
|
||||||
|
<item
|
||||||
|
android:id="@+id/server_profile"
|
||||||
|
android:icon="@drawable/ic_description_white_24dp"
|
||||||
|
android:title="@string/title_server" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/sub_setting"
|
android:id="@+id/sub_setting"
|
||||||
android:icon="@drawable/ic_subscriptions_white_24dp"
|
android:icon="@drawable/ic_subscriptions_white_24dp"
|
||||||
|
|||||||
@@ -6,9 +6,4 @@
|
|||||||
android:icon="@drawable/ic_copy_white"
|
android:icon="@drawable/ic_copy_white"
|
||||||
android:title="@string/logcat_copy"
|
android:title="@string/logcat_copy"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="always" />
|
||||||
<item
|
|
||||||
android:id="@+id/delete"
|
|
||||||
android:icon="@drawable/ic_delete_white_24dp"
|
|
||||||
android:title="@string/logcat_delete"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
</menu>
|
</menu>
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
<string name="summary_pref_mux_enabled">开启可能会加速,关闭可能会减少断流</string>
|
<string name="summary_pref_mux_enabled">开启可能会加速,关闭可能会减少断流</string>
|
||||||
|
|
||||||
<string name="title_pref_speed_enabled">启用速度显示</string>
|
<string name="title_pref_speed_enabled">启用速度显示</string>
|
||||||
<string name="summary_pref_speed_enabled">在通知中显示当前速度\n小图标显示流量的路由情况</string>
|
<string name="summary_pref_speed_enabled">在通知中显示当前速度</string>
|
||||||
|
|
||||||
<string name="title_pref_sniffing_enabled">启用流量探测</string>
|
<string name="title_pref_sniffing_enabled">启用流量探测</string>
|
||||||
<string name="summary_pref_sniffing_enabled">流量探测</string>
|
<string name="summary_pref_sniffing_enabled">流量探测</string>
|
||||||
@@ -135,7 +135,6 @@
|
|||||||
|
|
||||||
<string name="title_logcat">Logcat</string>
|
<string name="title_logcat">Logcat</string>
|
||||||
<string name="logcat_copy">复制</string>
|
<string name="logcat_copy">复制</string>
|
||||||
<string name="logcat_delete">删除</string>
|
|
||||||
<string name="title_export_all">导出全部配置至剪贴板</string>
|
<string name="title_export_all">导出全部配置至剪贴板</string>
|
||||||
<string name="title_sub_setting">订阅设置</string>
|
<string name="title_sub_setting">订阅设置</string>
|
||||||
<string name="sub_setting_remarks">备注</string>
|
<string name="sub_setting_remarks">备注</string>
|
||||||
@@ -181,10 +180,5 @@
|
|||||||
<item>绕过大陆地址</item>
|
<item>绕过大陆地址</item>
|
||||||
<item>绕过局域网及大陆地址</item>
|
<item>绕过局域网及大陆地址</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string name="title_pref_proxy_sharing_enabled">代理共享</string>
|
|
||||||
<string name="summary_pref_proxy_sharing_enabled">绑定代理入口ip到0.0.0.0</string>
|
|
||||||
<string name="toast_warning_pref_proxysharing">其他设备可以使用socks/http协议通过您的IP地址连接到代理\nHttp 代理: http://您的ip:10809\nSocks 代理: socks(4/5)://您的ip:10808\n仅在受信任的网络中启用以避免未经授权的连接</string>
|
|
||||||
<string name="toast_warning_pref_proxysharing_short">代理共享已启用,请确保处于受信网络</string>
|
|
||||||
<string name="toast_malformed_josn">配置格式错误</string>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<string name="toast_services_failure">啟動服務失敗</string>
|
<string name="toast_services_failure">啟動服務失敗</string>
|
||||||
|
|
||||||
<!--ServerActivity-->
|
<!--ServerActivity-->
|
||||||
<string name="title_server">設定檔</string>
|
<string name="title_server">組態</string>
|
||||||
<string name="menu_item_add_config">新增組態</string>
|
<string name="menu_item_add_config">新增組態</string>
|
||||||
<string name="menu_item_save_config">儲存組態</string>
|
<string name="menu_item_save_config">儲存組態</string>
|
||||||
<string name="menu_item_del_config">刪除組態</string>
|
<string name="menu_item_del_config">刪除組態</string>
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
<string name="title_file_chooser">選取一個設定檔</string>
|
<string name="title_file_chooser">選取一個設定檔</string>
|
||||||
<string name="toast_require_file_manager">請安裝檔案總管。</string>
|
<string name="toast_require_file_manager">請安裝檔案總管。</string>
|
||||||
<string name="server_customize_config">自訂組態</string>
|
<string name="server_customize_config">自訂組態</string>
|
||||||
<string name="toast_config_file_invalid">無效設定檔</string>
|
<string name="toast_config_file_invalid">無效組態</string>
|
||||||
<string name="server_lab_content">內容</string>
|
<string name="server_lab_content">內容</string>
|
||||||
<string name="toast_none_data_clipboard">剪貼簿內無資料</string>
|
<string name="toast_none_data_clipboard">剪貼簿內無資料</string>
|
||||||
<string name="toast_invalid_url">網址無效</string>
|
<string name="toast_invalid_url">網址無效</string>
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
<string name="summary_pref_mux_enabled">啟用或許會加快網路速度,切換或許會閃爍</string>
|
<string name="summary_pref_mux_enabled">啟用或許會加快網路速度,切換或許會閃爍</string>
|
||||||
|
|
||||||
<string name="title_pref_speed_enabled">啟用速度顯示</string>
|
<string name="title_pref_speed_enabled">啟用速度顯示</string>
|
||||||
<string name="summary_pref_speed_enabled">在通知中顯示當前速度\n小圖標顯示流量的路由情況</string>
|
<string name="summary_pref_speed_enabled">在通知中顯示當前速度</string>
|
||||||
|
|
||||||
<string name="title_pref_sniffing_enabled">啟用流量探測</string>
|
<string name="title_pref_sniffing_enabled">啟用流量探測</string>
|
||||||
<string name="summary_pref_sniffing_enabled">流量探測</string>
|
<string name="summary_pref_sniffing_enabled">流量探測</string>
|
||||||
@@ -104,17 +104,17 @@
|
|||||||
<string name="summary_pref_donate">向開發人員捐款</string>
|
<string name="summary_pref_donate">向開發人員捐款</string>
|
||||||
<string name="donate_detail">新增一些實驗性進階功能</string>
|
<string name="donate_detail">新增一些實驗性進階功能</string>
|
||||||
|
|
||||||
<string name="title_pref_remote_dns">遠端DNS (可選)</string>
|
<string name="title_pref_remote_dns">遠端DNS (可选)</string>
|
||||||
<string name="summary_pref_remote_dns">DNS</string>
|
<string name="summary_pref_remote_dns">DNS</string>
|
||||||
|
|
||||||
<string name="title_pref_domestic_dns">境内DNS (可選,僅本地DNS模式下生效)</string>
|
<string name="title_pref_domestic_dns">境内DNS (可选,僅本地DNS模式下生效)</string>
|
||||||
<string name="summary_pref_domestic_dns">DNS</string>
|
<string name="summary_pref_domestic_dns">DNS</string>
|
||||||
|
|
||||||
<string name="title_pref_socks_port">SOCKS5代理連接埠</string>
|
<string name="title_pref_socks_port">SOCKS5代理端口</string>
|
||||||
<string name="summary_pref_socks_port">SOCKS5代理連接埠</string>
|
<string name="summary_pref_socks_port">SOCKS5代理端口</string>
|
||||||
|
|
||||||
<string name="title_pref_http_port">HTTP代理連接埠</string>
|
<string name="title_pref_http_port">HTTP代理端口</string>
|
||||||
<string name="summary_pref_http_port">HTTP代理連接埠</string>
|
<string name="summary_pref_http_port">HTTP代理端口</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="title_pref_feedback">回饋</string>
|
<string name="title_pref_feedback">回饋</string>
|
||||||
@@ -137,7 +137,6 @@
|
|||||||
|
|
||||||
<string name="title_logcat">Logcat</string>
|
<string name="title_logcat">Logcat</string>
|
||||||
<string name="logcat_copy">複製</string>
|
<string name="logcat_copy">複製</string>
|
||||||
<string name="logcat_delete">刪除</string>
|
|
||||||
<string name="title_export_all">匯出全部配置至剪貼簿</string>
|
<string name="title_export_all">匯出全部配置至剪貼簿</string>
|
||||||
<string name="title_sub_setting">訂閱設定</string>
|
<string name="title_sub_setting">訂閱設定</string>
|
||||||
<string name="sub_setting_remarks">備註</string>
|
<string name="sub_setting_remarks">備註</string>
|
||||||
@@ -154,7 +153,7 @@
|
|||||||
<string name="routing_settings_delete">清除</string>
|
<string name="routing_settings_delete">清除</string>
|
||||||
<string name="routing_settings_scan_replace">掃描並取代</string>
|
<string name="routing_settings_scan_replace">掃描並取代</string>
|
||||||
<string name="routing_settings_scan_append">掃描並附加</string>
|
<string name="routing_settings_scan_append">掃描並附加</string>
|
||||||
<string name="routing_settings_default_rules">設置預設路由規則</string>
|
<string name="routing_settings_default_rules">設置默認路由規則</string>
|
||||||
|
|
||||||
<string name="connection_test_pending">"檢查連線能力"</string>
|
<string name="connection_test_pending">"檢查連線能力"</string>
|
||||||
<string name="connection_test_testing">"測試中……"</string>
|
<string name="connection_test_testing">"測試中……"</string>
|
||||||
@@ -179,13 +178,8 @@
|
|||||||
|
|
||||||
<string-array name="routing_mode">
|
<string-array name="routing_mode">
|
||||||
<item>全球</item>
|
<item>全球</item>
|
||||||
<item>略過區域網路</item>
|
<item>略過局域網</item>
|
||||||
<item>略過中國大陸</item>
|
<item>略過中國大陸</item>
|
||||||
<item>略過區域網路及中國大陸</item>
|
<item>略過局域網及中國大陸</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string name="title_pref_proxy_sharing_enabled">代理共享</string>
|
|
||||||
<string name="summary_pref_proxy_sharing_enabled">綁定代理入口ip到0.0.0.0</string>
|
|
||||||
<string name="toast_warning_pref_proxysharing">其他設備可以使用socks/http協定通過您的IP地址連接到代理\nHttp 代理: http://您的ip:10809\nSocks 代理: socks(4/5)://您的ip:10808\n僅在受信任的網路中啟用以避免未經授權的連接</string>
|
|
||||||
<string name="toast_warning_pref_proxysharing_short">代理共享已啟用,請確保處於受信網路</string>
|
|
||||||
<string name="toast_malformed_josn">配置格式錯誤</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -66,39 +66,4 @@
|
|||||||
<item>IPIfNonMatch</item>
|
<item>IPIfNonMatch</item>
|
||||||
<item>IPOnDemand</item>
|
<item>IPOnDemand</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- minimum list https://serverfault.com/a/304791 -->
|
|
||||||
<string-array name="bypass_private_ip_address" translatable="false">
|
|
||||||
<item>0.0.0.0/5</item>
|
|
||||||
<item>8.0.0.0/7</item>
|
|
||||||
<item>11.0.0.0/8</item>
|
|
||||||
<item>12.0.0.0/6</item>
|
|
||||||
<item>16.0.0.0/4</item>
|
|
||||||
<item>32.0.0.0/3</item>
|
|
||||||
<item>64.0.0.0/2</item>
|
|
||||||
<item>128.0.0.0/3</item>
|
|
||||||
<item>160.0.0.0/5</item>
|
|
||||||
<item>168.0.0.0/6</item>
|
|
||||||
<item>172.0.0.0/12</item>
|
|
||||||
<item>172.32.0.0/11</item>
|
|
||||||
<item>172.64.0.0/10</item>
|
|
||||||
<item>172.128.0.0/9</item>
|
|
||||||
<item>173.0.0.0/8</item>
|
|
||||||
<item>174.0.0.0/7</item>
|
|
||||||
<item>176.0.0.0/4</item>
|
|
||||||
<item>192.0.0.0/9</item>
|
|
||||||
<item>192.128.0.0/11</item>
|
|
||||||
<item>192.160.0.0/13</item>
|
|
||||||
<item>192.169.0.0/16</item>
|
|
||||||
<item>192.170.0.0/15</item>
|
|
||||||
<item>192.172.0.0/14</item>
|
|
||||||
<item>192.176.0.0/12</item>
|
|
||||||
<item>192.192.0.0/10</item>
|
|
||||||
<item>193.0.0.0/8</item>
|
|
||||||
<item>194.0.0.0/7</item>
|
|
||||||
<item>196.0.0.0/6</item>
|
|
||||||
<item>200.0.0.0/5</item>
|
|
||||||
<item>208.0.0.0/4</item>
|
|
||||||
<item>224.0.0.0/3</item>
|
|
||||||
</string-array>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
<dimen name="bypass_list_header_height">50dp</dimen>
|
<dimen name="bypass_list_header_height">50dp</dimen>
|
||||||
<dimen name="layout_margin_top_height">16dp</dimen>
|
<dimen name="layout_margin_top_height">16dp</dimen>
|
||||||
<dimen name="layout_margin_right_height">16dp</dimen>
|
<dimen name="layout_margin_right_height">16dp</dimen>
|
||||||
<dimen name="layout_margin_spacing">8dp</dimen>
|
|
||||||
<dimen name="edit_height">50dp</dimen>
|
<dimen name="edit_height">50dp</dimen>
|
||||||
<dimen name="png_height">24dp</dimen>
|
<dimen name="png_height">24dp</dimen>
|
||||||
<dimen name="server_height">72dp</dimen>
|
<dimen name="server_height">72dp</dimen>
|
||||||
|
|||||||
@@ -84,8 +84,7 @@
|
|||||||
<string name="summary_pref_mux_enabled">Enable maybe speed up network and switch network maybe flash</string>
|
<string name="summary_pref_mux_enabled">Enable maybe speed up network and switch network maybe flash</string>
|
||||||
|
|
||||||
<string name="title_pref_speed_enabled">Enable speed display</string>
|
<string name="title_pref_speed_enabled">Enable speed display</string>
|
||||||
<string name="summary_pref_speed_enabled">Display current speed in the notification.\nNotification icon would change based on
|
<string name="summary_pref_speed_enabled">Display current speed in the notification</string>
|
||||||
usage.</string>
|
|
||||||
|
|
||||||
<string name="title_pref_sniffing_enabled">Enable Sniffing</string>
|
<string name="title_pref_sniffing_enabled">Enable Sniffing</string>
|
||||||
<string name="summary_pref_sniffing_enabled">Sniffing</string>
|
<string name="summary_pref_sniffing_enabled">Sniffing</string>
|
||||||
@@ -137,7 +136,6 @@
|
|||||||
|
|
||||||
<string name="title_logcat">Logcat</string>
|
<string name="title_logcat">Logcat</string>
|
||||||
<string name="logcat_copy">Copy</string>
|
<string name="logcat_copy">Copy</string>
|
||||||
<string name="logcat_delete">Delete</string>
|
|
||||||
<string name="title_export_all">Export all config to clipboard</string>
|
<string name="title_export_all">Export all config to clipboard</string>
|
||||||
<string name="title_sub_setting">Subscription setting</string>
|
<string name="title_sub_setting">Subscription setting</string>
|
||||||
<string name="sub_setting_remarks">remarks</string>
|
<string name="sub_setting_remarks">remarks</string>
|
||||||
@@ -183,10 +181,5 @@
|
|||||||
<item>Bypass mainland address</item>
|
<item>Bypass mainland address</item>
|
||||||
<item>Bypassing LAN and mainland address</item>
|
<item>Bypassing LAN and mainland address</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string name="title_pref_proxy_sharing_enabled">Proxy sharing</string>
|
|
||||||
<string name="summary_pref_proxy_sharing_enabled">Bind inbound to 0.0.0.0</string>
|
|
||||||
<string name="toast_warning_pref_proxysharing">Other devices can connect to proxy by your ip address through socks/http protocol\nHttp Proxy: http://yourIP:10809\nSocks Proxy: socks(4/5)://yourIP:10808\nOnly enable in trusted network to avoid unauthorized connection</string>
|
|
||||||
<string name="toast_warning_pref_proxysharing_short">Proxy sharing enabled\nMake sure you are in a trusted network</string>
|
|
||||||
<string name="toast_malformed_josn">Config malformed</string>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -13,12 +13,6 @@
|
|||||||
<item name="windowNoTitle">true</item>
|
<item name="windowNoTitle">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.NoActionBar.Translucent">
|
|
||||||
<item name="android:windowBackground">@android:color/transparent</item>
|
|
||||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
|
||||||
<item name="android:windowIsTranslucent">true</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||||
|
|
||||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||||
|
|||||||
@@ -22,13 +22,6 @@
|
|||||||
android:summary="@string/summary_pref_sniffing_enabled"
|
android:summary="@string/summary_pref_sniffing_enabled"
|
||||||
android:title="@string/title_pref_sniffing_enabled" />
|
android:title="@string/title_pref_sniffing_enabled" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:defaultValue="false"
|
|
||||||
android:key="pref_proxy_sharing_enabled"
|
|
||||||
android:onClick="proxySharingOnClick"
|
|
||||||
android:summary="@string/summary_pref_proxy_sharing_enabled"
|
|
||||||
android:title="@string/title_pref_proxy_sharing_enabled" />
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/title_pref_routing">
|
<PreferenceCategory android:title="@string/title_pref_routing">
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#Tue Feb 25 12:40:41 CST 2020
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
|
||||||
distributionPath=wrapper/dists
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
|
||||||
zipStorePath=wrapper/dists
|
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip
|
|
||||||
Reference in New Issue
Block a user