Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ce96d0591 | ||
|
|
a7ef0618ba | ||
|
|
5af322552c | ||
|
|
fc852281dd | ||
|
|
0b2f036a22 | ||
|
|
cf2becb5e9 | ||
|
|
82d8eba1b9 | ||
|
|
286ad34d94 | ||
|
|
ff0bc6594d | ||
|
|
7b8113aef1 | ||
|
|
81d2ef5db5 | ||
|
|
bdea3ef88c | ||
|
|
c62c86fc29 | ||
|
|
59f698f755 | ||
|
|
9ac979006e | ||
|
|
da6291a965 | ||
|
|
bf6555e57c | ||
|
|
35b114220e | ||
|
|
800bb6a4e9 | ||
|
|
2c80521f5b | ||
|
|
6351ce5991 | ||
|
|
683362f0ee | ||
|
|
84fc909339 | ||
|
|
74171e26db | ||
|
|
f25c0cc890 | ||
|
|
29848053a4 | ||
|
|
0d9856919e | ||
|
|
0ae7f2f7b3 | ||
|
|
3dde6b0ca3 | ||
|
|
6b28208044 | ||
|
|
13f855e3c4 | ||
|
|
c870595e98 | ||
|
|
ae19a3f68d | ||
|
|
545afc41b3 | ||
|
|
7177d88144 | ||
|
|
294ed50afd | ||
|
|
0105fe48f7 | ||
|
|
c7ff23e3d5 | ||
|
|
23e9d7fde5 | ||
|
|
c93edd8875 | ||
|
|
bde37e38a7 | ||
|
|
c401d63d2f | ||
|
|
52416dd43d | ||
|
|
59bd7128ae | ||
|
|
87f16467bb | ||
|
|
bed0fd00bd | ||
|
|
0672af98f8 | ||
|
|
2341eceb65 | ||
|
|
caa2edcf05 | ||
|
|
dbe78d0aa5 | ||
|
|
71f2f590a7 | ||
|
|
ed26120581 | ||
|
|
71bd684b46 | ||
|
|
02ae19f0c7 | ||
|
|
062c0d8ddb | ||
|
|
775fa5ea62 | ||
|
|
a5bb39ac8a | ||
|
|
073c7c0410 | ||
|
|
7e88e3ba4f |
64
.github/workflows/build.yml
vendored
Normal file
64
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
name: Build APK
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
XRAY_CORE_VERSION:
|
||||
description: 'Xray core version or commit hash'
|
||||
required: false
|
||||
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.19.11'
|
||||
|
||||
- name: Install gomobile
|
||||
run: |
|
||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
||||
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
|
||||
|
||||
|
||||
- name: Setup Android environment
|
||||
uses: android-actions/setup-android@v2
|
||||
|
||||
|
||||
- name: Build dependencies
|
||||
run: |
|
||||
mkdir ${{ github.workspace }}/build
|
||||
cd ${{ github.workspace }}/build
|
||||
git clone --depth=1 -b main https://github.com/2dust/AndroidLibXrayLite.git
|
||||
cd AndroidLibXrayLite
|
||||
go get github.com/xtls/xray-core@${{ github.event.inputs.XRAY_CORE_VERSION }} || true
|
||||
gomobile init
|
||||
go mod tidy -v
|
||||
gomobile bind -v -androidapi 19 -ldflags='-s -w' ./
|
||||
cp *.aar ${{ github.workspace }}/V2rayNG/app/libs/
|
||||
|
||||
- name: Build APK
|
||||
run: |
|
||||
cd ${{ github.workspace }}/V2rayNG
|
||||
chmod 777 *
|
||||
sed -i 's/org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8/org.gradle.jvmargs=-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8/' ${{ github.workspace }}/V2rayNG/gradle.properties
|
||||
./gradlew assembleDebug
|
||||
|
||||
- name: Upload APK
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: apk
|
||||
path: ${{ github.workspace }}/V2rayNG/app/build/outputs/apk/debug/
|
||||
41
CR.md
41
CR.md
@@ -1,29 +1,40 @@
|
||||
v2rayNG 隐私条款
|
||||
**v2rayNG 隐私权政策**
|
||||
|
||||
最后更新 2017-11-22
|
||||
本政策自2023年11月17日起施行
|
||||
|
||||
v2rayNG 尊重并保护所有用户的个人隐私权,为此我们向大众公开这份隐私条款。**您使用 v2rayNG 即代表您以阅读并同意了这份条款,如果您不同意这份条款请立即停止使用并卸载 v2rayNG。**
|
||||
2dust 将 v2rayNG 应用程序构建为开源应用程序。 本服务由 2dust 免费提供,并且旨在按原样使用。
|
||||
|
||||
1. 信息收集
|
||||
v2rayNG 尊重并保护所有用户的个人隐私权,为此我们向大众公开这份隐私权政策。**您使用 v2rayNG 即代表您以阅读并同意了这份条款,如果您不同意这份条款请立即停止使用并卸载 v2rayNG。**
|
||||
|
||||
v2rayNG 软件自身不会发送任何信息到开发者,但是您下载软件的应用市场(如 Google Play)可能会收集关于应用运行状态的相关信息并提供给 v2rayNG 开发者。有关这些信息,请阅读您使用的应用市场所提供的隐私条款。
|
||||
**信息收集**
|
||||
|
||||
v2rayNG 软件中可能包含需要通过 IAP 支付解锁的功能,您的支付信息将由相关的 IAP 渠道进行处理,而我们对支付信息没有访问权。
|
||||
v2rayNG 软件自身不会发送任何信息到开发者,但是您下载软件的应用市场(如 Google Play)可能会收集关于应用运行状态的相关信息并提供给 v2rayNG 开发者。有关这些信息,请阅读您使用的应用市场所提供的隐私权政策。
|
||||
|
||||
当您向 v2rayNG 开发者反馈软件运行中的错误时,开发者可能会要求您提供软件以及系统的日志以帮助确认问题的原因。因日志中可能包括敏感信息,此类信息只能由您自己操作发送。**我们不对任何传输服务的安全性和隐私性做任何明示或暗示的担保,请您在传送相关信息时选择可以您自身可以接受的方式。**
|
||||
v2rayNG 软件中可能包含需要通过 IAP 支付解锁的功能,您的支付信息将由相关的 IAP 渠道进行处理,而我们对支付信息没有访问权。
|
||||
|
||||
2. 信息共享
|
||||
当您向 v2rayNG 开发者反馈软件运行中的错误时,开发者可能会要求您提供软件以及系统的日志以帮助确认问题的原因。因日志中可能包括敏感信息,此类信息只能由您自己操作发送。**我们不对任何传输服务的安全性和隐私性做任何明示或暗示的担保,请您在传送相关信息时选择可以您自身可以接受的方式。**
|
||||
|
||||
我们不会向任何第三方出售收集到的用户数据。我们可能向外部开发者提供信息以协助软件的开发,但是在提供信息之前我们会传达相关保密义务并确定其可以遵守。
|
||||
**信息共享**
|
||||
|
||||
3. 信息存留
|
||||
我们不会向任何第三方出售收集到的用户数据。我们可能向外部开发者提供信息以协助软件的开发,但是在提供信息之前我们会传达相关保密义务并确定其可以遵守。
|
||||
|
||||
除非有相关法律规定,我们会在 30 天内清除不需要继续使用的用户数据,或将统计数据整合为无法识别单个用户的综合报告。
|
||||
**信息存留**
|
||||
|
||||
4. 信息泄露
|
||||
除非有相关法律规定,我们会在 30 天内清除不需要继续使用的用户数据,或将统计数据整合为无法识别单个用户的综合报告。
|
||||
|
||||
我们会使用合理的技术和安全手段尽力保护用户的数据,但是无法保证数据的绝对安全。如果我们确认数据发生了泄露,我们会在 7 天内通过可用的渠道通知用户。**您同意不向我们追责任何因不可抗力而造成的损失。**
|
||||
**信息泄露**
|
||||
|
||||
5. 条款修改
|
||||
我们会使用合理的技术和安全手段尽力保护用户的数据,但是无法保证数据的绝对安全。如果我们确认数据发生了泄露,我们会在 7 天内通过可用的渠道通知用户。**您同意不向我们追责任何因不可抗力而造成的损失。**
|
||||
|
||||
**儿童隐私**
|
||||
|
||||
这些服务不针对 13 岁以下的任何人。我不会故意收集 13 岁以下儿童的个人身份信息。 如果我发现 13 岁以下的儿童向我提供了个人信息,我会立即从我们的服务器中删除该信息。 如果您是父母或监护人,并且您知道您的孩子向我们提供了个人信息,请与我联系,以便我能够采取必要的行动。
|
||||
|
||||
**条款修改**
|
||||
|
||||
我们保留修改这份隐私权政策的权利,但是会确保在更新条款前至少 30 天通过我们的可用渠道和应用内提示来通知用户。**在新条款生效后继续使用软件即表示您同意修改后的隐私权政策。**
|
||||
|
||||
**联系我们**
|
||||
|
||||
如果您对我的隐私政策有任何疑问或建议,请随时通过 CaptainIronng@protonmail.com 与我联系。
|
||||
|
||||
我们保留修改这份隐私条款的权利,但是会确保在更新条款前至少 30 天通过我们的可用渠道和应用内提示来通知用户。**在新条款生效后继续使用软件即表示您同意修改后的隐私条款。**
|
||||
|
||||
@@ -17,8 +17,8 @@ android {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion Integer.parseInt("$targetSdkVer")
|
||||
multiDexEnabled true
|
||||
versionCode 521
|
||||
versionName "1.8.7"
|
||||
versionCode 532
|
||||
versionName "1.8.12"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -132,4 +132,9 @@ dependencies {
|
||||
implementation 'com.blacksquircle.ui:language-json:2.8.0'
|
||||
implementation 'io.github.g00fy2.quickie:quickie-bundled:1.6.0'
|
||||
implementation 'com.google.zxing:core:3.5.1'
|
||||
|
||||
def work_version = "2.8.1"
|
||||
|
||||
implementation "androidx.work:work-runtime-ktx:$work_version"
|
||||
implementation "androidx.work:work-multiprocess:$work_version"
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:ignore="MissingLeanbackLauncher">
|
||||
|
||||
<supports-screens
|
||||
android:anyDensity="true"
|
||||
@@ -26,6 +27,9 @@
|
||||
<!-- <useapplications-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission
|
||||
android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"
|
||||
android:minSdkVersion="34" />
|
||||
<!-- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> -->
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
@@ -50,7 +54,7 @@
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
|
||||
<!-- <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>-->
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
|
||||
@@ -127,6 +131,7 @@
|
||||
android:exported="false"
|
||||
android:label="@string/app_name"
|
||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
||||
android:foregroundServiceType="specialUse"
|
||||
android:process=":RunSoLibV2RayDaemon">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.VpnService" />
|
||||
@@ -134,12 +139,19 @@
|
||||
<meta-data
|
||||
android:name="android.net.VpnService.SUPPORTS_ALWAYS_ON"
|
||||
android:value="true" />
|
||||
<property
|
||||
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
|
||||
android:value="vpn" />
|
||||
</service>
|
||||
|
||||
<service android:name=".service.V2RayProxyOnlyService"
|
||||
android:exported="false"
|
||||
android:label="@string/app_name"
|
||||
android:foregroundServiceType="specialUse"
|
||||
android:process=":RunSoLibV2RayDaemon">
|
||||
<property
|
||||
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
|
||||
android:value="proxy" />
|
||||
</service>
|
||||
|
||||
<service android:name=".service.V2RayTestService"
|
||||
@@ -192,6 +204,18 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<!-- =====================Tasker===================== -->
|
||||
<provider
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup"
|
||||
android:exported="false"
|
||||
tools:node="merge">
|
||||
|
||||
<meta-data
|
||||
android:name="androidx.work.WorkManagerInitializer"
|
||||
android:value="androidx.startup"
|
||||
tools:node="remove" />
|
||||
|
||||
</provider>
|
||||
|
||||
</application>
|
||||
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
package com.v2ray.ang
|
||||
|
||||
import android.content.Context
|
||||
import androidx.multidex.MultiDexApplication
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.work.Configuration
|
||||
import com.tencent.mmkv.MMKV
|
||||
|
||||
class AngApplication : MultiDexApplication() {
|
||||
class AngApplication : MultiDexApplication(), Configuration.Provider {
|
||||
companion object {
|
||||
const val PREF_LAST_VERSION = "pref_last_version"
|
||||
lateinit var application: AngApplication
|
||||
}
|
||||
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
super.attachBaseContext(base)
|
||||
application = this
|
||||
}
|
||||
|
||||
var firstRun = false
|
||||
@@ -25,4 +33,10 @@ class AngApplication : MultiDexApplication() {
|
||||
//Logger.init().logLevel(if (BuildConfig.DEBUG) LogLevel.FULL else LogLevel.NONE)
|
||||
MMKV.initialize(this)
|
||||
}
|
||||
|
||||
override fun getWorkManagerConfiguration(): Configuration {
|
||||
return Configuration.Builder()
|
||||
.setDefaultProcessName("${BuildConfig.APPLICATION_ID}:bg")
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,9 @@ object AppConfig {
|
||||
const val PREF_BYPASS_APPS = "pref_bypass_apps"
|
||||
const val PREF_CONFIRM_REMOVE = "pref_confirm_remove"
|
||||
const val PREF_START_SCAN_IMMEDIATE = "pref_start_scan_immediate"
|
||||
const val PREF_MUX_ENABLED = "pref_mux_enabled"
|
||||
const val PREF_MUX_XUDP_CONCURRENCY = "pref_mux_xudp_concurency"
|
||||
const val PREF_MUX_XUDP_QUIC = "pref_mux_xudp_quic"
|
||||
|
||||
const val HTTP_PROTOCOL: String = "http://"
|
||||
const val HTTPS_PROTOCOL: String = "https://"
|
||||
@@ -62,8 +65,9 @@ object AppConfig {
|
||||
const val v2rayCustomRoutingListUrl = "https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/"
|
||||
const val v2rayNGIssues = "https://github.com/2dust/v2rayNG/issues"
|
||||
const val v2rayNGWikiMode = "https://github.com/2dust/v2rayNG/wiki/Mode"
|
||||
const val v2rayNGPrivacyPolicy = "https://raw.githubusercontent.com/2dust/v2rayNG/master/CR.md"
|
||||
const val promotionUrl = "aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw="
|
||||
const val geoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/";
|
||||
const val geoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/"
|
||||
|
||||
const val DNS_AGENT = "1.1.1.1"
|
||||
const val DNS_DIRECT = "223.5.5.5"
|
||||
@@ -87,4 +91,11 @@ object AppConfig {
|
||||
const val MSG_MEASURE_CONFIG = 7
|
||||
const val MSG_MEASURE_CONFIG_SUCCESS = 71
|
||||
const val MSG_MEASURE_CONFIG_CANCEL = 72
|
||||
|
||||
// subscription settings
|
||||
const val SUBSCRIPTION_AUTO_UPDATE = "pref_auto_update_subscription"
|
||||
const val SUBSCRIPTION_AUTO_UPDATE_INTERVAL = "pref_auto_update_interval"
|
||||
const val SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL = "1440" // 24 hours
|
||||
const val SUBSCRIPTION_UPDATE_TASK_NAME = "subscription_updater"
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.v2ray.ang.dto
|
||||
|
||||
data class SubscriptionItem(
|
||||
var remarks: String = "",
|
||||
var url: String = "",
|
||||
var enabled: Boolean = true,
|
||||
val addedTime: Long = System.currentTimeMillis()) {
|
||||
}
|
||||
var remarks: String = "",
|
||||
var url: String = "",
|
||||
var enabled: Boolean = true,
|
||||
val addedTime: Long = System.currentTimeMillis(),
|
||||
var lastUpdated: Long = -1,
|
||||
var autoUpdate: Boolean = false,
|
||||
val updateInterval: Int? = null,
|
||||
)
|
||||
@@ -292,7 +292,10 @@ data class V2rayConfig(
|
||||
}
|
||||
}
|
||||
|
||||
data class MuxBean(var enabled: Boolean, var concurrency: Int = 8)
|
||||
data class MuxBean(var enabled: Boolean,
|
||||
var concurrency: Int = 8,
|
||||
var xudpConcurrency: Int = 8,
|
||||
var xudpProxyUDP443: String = "",)
|
||||
|
||||
fun getServerAddress(): String? {
|
||||
if (protocol.equals(EConfigType.VMESS.name, true)
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.v2ray.ang.service
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.util.AngConfigManager
|
||||
import com.v2ray.ang.util.MmkvManager
|
||||
import com.v2ray.ang.util.Utils
|
||||
|
||||
object SubscriptionUpdater {
|
||||
|
||||
const val notificationChannel = "subscription_update_channel"
|
||||
|
||||
class UpdateTask(context: Context, params: WorkerParameters) :
|
||||
CoroutineWorker(context, params) {
|
||||
|
||||
private val notificationManager = NotificationManagerCompat.from(applicationContext)
|
||||
private val notification =
|
||||
NotificationCompat.Builder(applicationContext, notificationChannel)
|
||||
.setWhen(0)
|
||||
.setTicker("Update")
|
||||
.setContentTitle(context.getString(R.string.title_pref_auto_update_subscription))
|
||||
.setSmallIcon(R.drawable.ic_stat_name)
|
||||
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
override suspend fun doWork(): Result {
|
||||
Log.d(AppConfig.ANG_PACKAGE, "subscription automatic update starting")
|
||||
|
||||
val subs = MmkvManager.decodeSubscriptions().filter { it.second.autoUpdate }
|
||||
|
||||
for (i in subs) {
|
||||
val subscription = i.second
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
notification.setChannelId(notificationChannel)
|
||||
val channel =
|
||||
NotificationChannel(
|
||||
notificationChannel,
|
||||
"Subscription Update Service",
|
||||
NotificationManager.IMPORTANCE_MIN
|
||||
)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
notificationManager.notify(3, notification.build())
|
||||
Log.d(
|
||||
AppConfig.ANG_PACKAGE,
|
||||
"subscription automatic update: ---${subscription.remarks}"
|
||||
)
|
||||
val configs = Utils.getUrlContentWithCustomUserAgent(subscription.url)
|
||||
importBatchConfig(configs, i.first)
|
||||
notification.setContentText("Updating ${subscription.remarks}")
|
||||
}
|
||||
notificationManager.cancel(3)
|
||||
return Result.success()
|
||||
}
|
||||
}
|
||||
|
||||
fun importBatchConfig(server: String?, subid: String = "") {
|
||||
val append = subid.isEmpty()
|
||||
|
||||
val count = AngConfigManager.importBatchConfig(server, subid, append)
|
||||
if (count <= 0) {
|
||||
AngConfigManager.importBatchConfig(Utils.decode(server!!), subid, append)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ object V2RayServiceManager {
|
||||
set(value) {
|
||||
field = value
|
||||
Seq.setContext(value?.get()?.getService()?.applicationContext)
|
||||
Libv2ray.initV2Env(Utils.userAssetPath(value?.get()?.getService()))
|
||||
Libv2ray.initV2Env(Utils.userAssetPath(value?.get()?.getService()), Utils.getDeviceIdForXUDPBaseKey())
|
||||
}
|
||||
var currentConfig: ServerConfig? = null
|
||||
|
||||
@@ -133,7 +133,11 @@ object V2RayServiceManager {
|
||||
mFilter.addAction(Intent.ACTION_SCREEN_ON)
|
||||
mFilter.addAction(Intent.ACTION_SCREEN_OFF)
|
||||
mFilter.addAction(Intent.ACTION_USER_PRESENT)
|
||||
service.registerReceiver(mMsgReceive, mFilter)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
service.registerReceiver(mMsgReceive, mFilter, Context.RECEIVER_EXPORTED)
|
||||
} else {
|
||||
service.registerReceiver(mMsgReceive, mFilter)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.d(ANG_PACKAGE, e.toString())
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class V2RayTestService : Service() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
Seq.setContext(this)
|
||||
Libv2ray.initV2Env(Utils.userAssetPath(this))
|
||||
Libv2ray.initV2Env(Utils.userAssetPath(this), Utils.getDeviceIdForXUDPBaseKey())
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
|
||||
@@ -2,13 +2,25 @@ package com.v2ray.ang.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.WindowCompat
|
||||
import com.v2ray.ang.util.MyContextWrapper
|
||||
import com.v2ray.ang.util.Utils
|
||||
|
||||
abstract class BaseActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
if (!Utils.getDarkModeStatus(this)) {
|
||||
WindowCompat.getInsetsController(window, window.decorView).apply {
|
||||
isAppearanceLightStatusBars = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
onBackPressed()
|
||||
|
||||
@@ -25,13 +25,12 @@ class LogcatActivity : BaseActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityLogcatBinding.inflate(layoutInflater)
|
||||
val view = binding.root
|
||||
setContentView(view)
|
||||
binding = ActivityLogcatBinding.inflate(layoutInflater)
|
||||
val view = binding.root
|
||||
setContentView(view)
|
||||
|
||||
title = getString(R.string.title_logcat)
|
||||
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
logcat(false)
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.tencent.mmkv.MMKV
|
||||
import com.v2ray.ang.AppConfig.ANG_PACKAGE
|
||||
@@ -66,11 +65,6 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
setContentView(view)
|
||||
title = getString(R.string.title_server)
|
||||
setSupportActionBar(binding.toolbar)
|
||||
if (!Utils.getDarkModeStatus(this)) {
|
||||
WindowCompat.getInsetsController(window, window.decorView).apply {
|
||||
isAppearanceLightStatusBars = true
|
||||
}
|
||||
}
|
||||
|
||||
binding.fab.setOnClickListener {
|
||||
if (mainViewModel.isRunning.value == true) {
|
||||
@@ -109,7 +103,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
binding.drawerLayout.addDrawerListener(toggle)
|
||||
toggle.syncState()
|
||||
binding.navView.setNavigationItemSelectedListener(this)
|
||||
binding.version.text = "v${BuildConfig.VERSION_NAME} (${SpeedtestUtil.getLibVersion()})"
|
||||
"v${BuildConfig.VERSION_NAME} (${SpeedtestUtil.getLibVersion()})".also { binding.version.text = it }
|
||||
|
||||
setupViewModel()
|
||||
copyAssets()
|
||||
@@ -688,6 +682,9 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
R.id.logcat -> {
|
||||
startActivity(Intent(this, LogcatActivity::class.java))
|
||||
}
|
||||
R.id.privacy_policy-> {
|
||||
Utils.openUri(this, AppConfig.v2rayNGPrivacyPolicy)
|
||||
}
|
||||
}
|
||||
binding.drawerLayout.closeDrawer(GravityCompat.START)
|
||||
return true
|
||||
|
||||
@@ -96,7 +96,8 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
|
||||
holder.itemMainBinding.tvType.text = config.configType.name.lowercase()
|
||||
}
|
||||
}
|
||||
holder.itemMainBinding.tvStatistics.text = "${outbound?.getServerAddress()} : ${outbound?.getServerPort()}"
|
||||
val strState = "${outbound?.getServerAddress()?.dropLast(3)}*** : ${outbound?.getServerPort()}"
|
||||
holder.itemMainBinding.tvStatistics.text = strState
|
||||
|
||||
holder.itemMainBinding.layoutShare.setOnClickListener {
|
||||
AlertDialog.Builder(mActivity).setItems(shareOptions.toTypedArray()) { _, i ->
|
||||
|
||||
@@ -41,8 +41,6 @@ class PerAppProxyActivity : BaseActivity() {
|
||||
val view = binding.root
|
||||
setContentView(view)
|
||||
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
val dividerItemDecoration = DividerItemDecoration(this, LinearLayoutManager.VERTICAL)
|
||||
binding.recyclerView.addItemDecoration(dividerItemDecoration)
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ class RoutingSettingsActivity : BaseActivity() {
|
||||
setContentView(view)
|
||||
|
||||
title = getString(R.string.title_pref_routing_custom)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
val fragments = ArrayList<Fragment>()
|
||||
fragments.add(RoutingSettingsFragment().newInstance(AppConfig.PREF_V2RAY_ROUTING_AGENT))
|
||||
|
||||
@@ -31,16 +31,6 @@ class ScannerActivity : BaseActivity(){
|
||||
if (settingsStorage?.decodeBool(AppConfig.PREF_START_SCAN_IMMEDIATE) == true) {
|
||||
launchScan()
|
||||
}
|
||||
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
public override fun onResume() {
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
public override fun onPause() {
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
private fun launchScan(){
|
||||
|
||||
@@ -175,7 +175,6 @@ class ServerActivity : BaseActivity() {
|
||||
} else {
|
||||
clearServer()
|
||||
}
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -305,7 +304,11 @@ class ServerActivity : BaseActivity() {
|
||||
}
|
||||
val config = MmkvManager.decodeServerConfig(editGuid) ?: ServerConfig.create(createConfigType)
|
||||
if (config.configType != EConfigType.SOCKS && TextUtils.isEmpty(et_id.text.toString())) {
|
||||
toast(R.string.server_lab_id)
|
||||
if (config.configType == EConfigType.TROJAN || config.configType == EConfigType.SHADOWSOCKS) {
|
||||
toast(R.string.server_lab_id3)
|
||||
}else{
|
||||
toast(R.string.server_lab_id)
|
||||
}
|
||||
return false
|
||||
}
|
||||
sp_stream_security?.let {
|
||||
|
||||
@@ -49,7 +49,6 @@ class ServerCustomConfigActivity : BaseActivity() {
|
||||
} else {
|
||||
clearServer()
|
||||
}
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,10 +6,18 @@ import android.text.TextUtils
|
||||
import android.view.View
|
||||
import androidx.activity.viewModels
|
||||
import androidx.preference.*
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.ExistingPeriodicWorkPolicy
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.PeriodicWorkRequest
|
||||
import androidx.work.multiprocess.RemoteWorkManager
|
||||
import com.v2ray.ang.AngApplication
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.service.SubscriptionUpdater
|
||||
import com.v2ray.ang.util.Utils
|
||||
import com.v2ray.ang.viewmodel.SettingsViewModel
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class SettingsActivity : BaseActivity() {
|
||||
private val settingsViewModel: SettingsViewModel by viewModels()
|
||||
@@ -20,8 +28,6 @@ class SettingsActivity : BaseActivity() {
|
||||
|
||||
title = getString(R.string.title_settings)
|
||||
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
settingsViewModel.startListenPreferenceChange()
|
||||
}
|
||||
|
||||
@@ -31,12 +37,20 @@ class SettingsActivity : BaseActivity() {
|
||||
private val fakeDns by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_FAKE_DNS_ENABLED) }
|
||||
private val localDnsPort by lazy { findPreference<EditTextPreference>(AppConfig.PREF_LOCAL_DNS_PORT) }
|
||||
private val vpnDns by lazy { findPreference<EditTextPreference>(AppConfig.PREF_VPN_DNS) }
|
||||
|
||||
private val mux by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_MUX_ENABLED) }
|
||||
private val muxXudpConcurrency by lazy { findPreference<EditTextPreference>(AppConfig.PREF_MUX_XUDP_CONCURRENCY) }
|
||||
private val muxXudpQuic by lazy { findPreference<ListPreference>(AppConfig.PREF_MUX_XUDP_QUIC) }
|
||||
|
||||
|
||||
// val autoRestart by lazy { findPreference(PREF_AUTO_RESTART) as CheckBoxPreference }
|
||||
private val remoteDns by lazy { findPreference<EditTextPreference>(AppConfig.PREF_REMOTE_DNS) }
|
||||
private val domesticDns by lazy { findPreference<EditTextPreference>(AppConfig.PREF_DOMESTIC_DNS) }
|
||||
private val socksPort by lazy { findPreference<EditTextPreference>(AppConfig.PREF_SOCKS_PORT) }
|
||||
private val httpPort by lazy { findPreference<EditTextPreference>(AppConfig.PREF_HTTP_PORT) }
|
||||
private val routingCustom by lazy { findPreference<Preference>(AppConfig.PREF_ROUTING_CUSTOM) }
|
||||
private val autoUpdateCheck by lazy { findPreference<CheckBoxPreference>(AppConfig.SUBSCRIPTION_AUTO_UPDATE) }
|
||||
private val autoUpdateInterval by lazy { findPreference<EditTextPreference>(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL) }
|
||||
// val licenses: Preference by lazy { findPreference(PREF_LICENSES) }
|
||||
// val feedback: Preference by lazy { findPreference(PREF_FEEDBACK) }
|
||||
// val tgGroup: Preference by lazy { findPreference(PREF_TG_GROUP) }
|
||||
@@ -51,6 +65,27 @@ class SettingsActivity : BaseActivity() {
|
||||
false
|
||||
}
|
||||
|
||||
autoUpdateCheck?.setOnPreferenceChangeListener { _, newValue ->
|
||||
val value = newValue as Boolean
|
||||
autoUpdateCheck?.isChecked = value
|
||||
autoUpdateInterval?.isEnabled = value
|
||||
autoUpdateInterval?.text?.toLong()?.let {
|
||||
if (newValue) configureUpdateTask(it) else cancelUpdateTask()
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
autoUpdateInterval?.setOnPreferenceChangeListener { _, any ->
|
||||
var nval = any as String
|
||||
|
||||
autoUpdateInterval?.summary = nval
|
||||
// It must be greater than 15 minutes because WorkManager couldn't run tasks under 15 minutes intervals
|
||||
nval =
|
||||
if (TextUtils.isEmpty(nval) or (nval.toLong() < 15)) AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL else nval
|
||||
configureUpdateTask(nval.toLong())
|
||||
true
|
||||
}
|
||||
|
||||
// licenses.onClick {
|
||||
// val fragment = LicensesDialogFragment.Builder(act)
|
||||
// .setNotices(R.raw.licenses)
|
||||
@@ -92,13 +127,14 @@ class SettingsActivity : BaseActivity() {
|
||||
true
|
||||
}
|
||||
|
||||
localDns?.setOnPreferenceChangeListener{ _, any ->
|
||||
localDns?.setOnPreferenceChangeListener { _, any ->
|
||||
updateLocalDns(any as Boolean)
|
||||
true
|
||||
}
|
||||
localDnsPort?.setOnPreferenceChangeListener { _, any ->
|
||||
val nval = any as String
|
||||
localDnsPort?.summary = if (TextUtils.isEmpty(nval)) AppConfig.PORT_LOCAL_DNS else nval
|
||||
localDnsPort?.summary =
|
||||
if (TextUtils.isEmpty(nval)) AppConfig.PORT_LOCAL_DNS else nval
|
||||
true
|
||||
}
|
||||
vpnDns?.setOnPreferenceChangeListener { _, any ->
|
||||
@@ -121,18 +157,31 @@ class SettingsActivity : BaseActivity() {
|
||||
}
|
||||
mode?.dialogLayoutResource = R.layout.preference_with_help_link
|
||||
//loglevel.summary = "LogLevel"
|
||||
mux?.setOnPreferenceChangeListener { _, newValue ->
|
||||
updateMux(newValue as Boolean)
|
||||
true
|
||||
}
|
||||
muxXudpConcurrency?.setOnPreferenceChangeListener { _, newValue ->
|
||||
updateMuxConcurrency(newValue as String)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity())
|
||||
val defaultSharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(requireActivity())
|
||||
updateMode(defaultSharedPreferences.getString(AppConfig.PREF_MODE, "VPN"))
|
||||
var remoteDnsString = defaultSharedPreferences.getString(AppConfig.PREF_REMOTE_DNS, "")
|
||||
domesticDns?.summary = defaultSharedPreferences.getString(AppConfig.PREF_DOMESTIC_DNS, "")
|
||||
|
||||
domesticDns?.summary = defaultSharedPreferences.getString(AppConfig.PREF_DOMESTIC_DNS, "")
|
||||
localDnsPort?.summary = defaultSharedPreferences.getString(AppConfig.PREF_LOCAL_DNS_PORT, AppConfig.PORT_LOCAL_DNS)
|
||||
socksPort?.summary = defaultSharedPreferences.getString(AppConfig.PREF_SOCKS_PORT, AppConfig.PORT_SOCKS)
|
||||
httpPort?.summary = defaultSharedPreferences.getString(AppConfig.PREF_HTTP_PORT, AppConfig.PORT_HTTP)
|
||||
updateMux(defaultSharedPreferences.getBoolean(AppConfig.PREF_MUX_ENABLED, false))
|
||||
muxXudpConcurrency?.summary = defaultSharedPreferences.getString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8")
|
||||
autoUpdateInterval?.summary = defaultSharedPreferences.getString(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL,AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL)
|
||||
autoUpdateInterval?.isEnabled = defaultSharedPreferences.getBoolean(AppConfig.SUBSCRIPTION_AUTO_UPDATE, false)
|
||||
|
||||
if (TextUtils.isEmpty(remoteDnsString)) {
|
||||
remoteDnsString = AppConfig.DNS_AGENT
|
||||
@@ -141,7 +190,8 @@ class SettingsActivity : BaseActivity() {
|
||||
domesticDns?.summary = AppConfig.DNS_DIRECT
|
||||
}
|
||||
remoteDns?.summary = remoteDnsString
|
||||
vpnDns?.summary = defaultSharedPreferences.getString(AppConfig.PREF_VPN_DNS, remoteDnsString)
|
||||
vpnDns?.summary =
|
||||
defaultSharedPreferences.getString(AppConfig.PREF_VPN_DNS, remoteDnsString)
|
||||
|
||||
if (TextUtils.isEmpty(localDnsPort?.summary)) {
|
||||
localDnsPort?.summary = AppConfig.PORT_LOCAL_DNS
|
||||
@@ -155,17 +205,24 @@ class SettingsActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
private fun updateMode(mode: String?) {
|
||||
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity())
|
||||
val defaultSharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(requireActivity())
|
||||
val vpn = mode == "VPN"
|
||||
perAppProxy?.isEnabled = vpn
|
||||
perAppProxy?.isChecked = PreferenceManager.getDefaultSharedPreferences(requireActivity())
|
||||
perAppProxy?.isChecked =
|
||||
PreferenceManager.getDefaultSharedPreferences(requireActivity())
|
||||
.getBoolean(AppConfig.PREF_PER_APP_PROXY, false)
|
||||
localDns?.isEnabled = vpn
|
||||
fakeDns?.isEnabled = vpn
|
||||
localDnsPort?.isEnabled = vpn
|
||||
vpnDns?.isEnabled = vpn
|
||||
if (vpn) {
|
||||
updateLocalDns(defaultSharedPreferences.getBoolean(AppConfig.PREF_LOCAL_DNS_ENABLED, false))
|
||||
updateLocalDns(
|
||||
defaultSharedPreferences.getBoolean(
|
||||
AppConfig.PREF_LOCAL_DNS_ENABLED,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +231,48 @@ class SettingsActivity : BaseActivity() {
|
||||
localDnsPort?.isEnabled = enabled
|
||||
vpnDns?.isEnabled = !enabled
|
||||
}
|
||||
|
||||
private fun configureUpdateTask(interval: Long) {
|
||||
val rw = RemoteWorkManager.getInstance(AngApplication.application)
|
||||
rw.cancelUniqueWork(AppConfig.SUBSCRIPTION_UPDATE_TASK_NAME)
|
||||
rw.enqueueUniquePeriodicWork(
|
||||
AppConfig.SUBSCRIPTION_UPDATE_TASK_NAME,
|
||||
ExistingPeriodicWorkPolicy.UPDATE,
|
||||
PeriodicWorkRequest.Builder(
|
||||
SubscriptionUpdater.UpdateTask::class.java,
|
||||
interval,
|
||||
TimeUnit.MINUTES
|
||||
)
|
||||
.apply {
|
||||
setInitialDelay(interval, TimeUnit.MINUTES)
|
||||
}
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
private fun cancelUpdateTask() {
|
||||
val rw = RemoteWorkManager.getInstance(AngApplication.application)
|
||||
rw.cancelUniqueWork(AppConfig.SUBSCRIPTION_UPDATE_TASK_NAME)
|
||||
}
|
||||
|
||||
private fun updateMux(enabled: Boolean) {
|
||||
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity())
|
||||
muxXudpConcurrency?.isEnabled = enabled
|
||||
muxXudpQuic?.isEnabled = enabled
|
||||
if (enabled) {
|
||||
updateMuxConcurrency(defaultSharedPreferences.getString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateMuxConcurrency(value: String?) {
|
||||
if (value == null) {
|
||||
muxXudpQuic?.isEnabled = true
|
||||
} else {
|
||||
val concurrency = value.toIntOrNull() ?: 8
|
||||
muxXudpConcurrency?.summary = concurrency.toString()
|
||||
muxXudpQuic?.isEnabled = concurrency >= 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onModeHelpClicked(view: View) {
|
||||
|
||||
@@ -5,14 +5,22 @@ import android.text.TextUtils
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.ExistingPeriodicWorkPolicy
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.PeriodicWorkRequest
|
||||
import androidx.work.multiprocess.RemoteWorkManager
|
||||
import com.google.gson.Gson
|
||||
import com.tencent.mmkv.MMKV
|
||||
import com.v2ray.ang.AngApplication
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.databinding.ActivitySubEditBinding
|
||||
import com.v2ray.ang.dto.SubscriptionItem
|
||||
import com.v2ray.ang.extension.toast
|
||||
import com.v2ray.ang.service.SubscriptionUpdater
|
||||
import com.v2ray.ang.util.MmkvManager
|
||||
import com.v2ray.ang.util.Utils
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class SubEditActivity : BaseActivity() {
|
||||
private lateinit var binding: ActivitySubEditBinding
|
||||
@@ -36,7 +44,6 @@ class SubEditActivity : BaseActivity() {
|
||||
} else {
|
||||
clearServer()
|
||||
}
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,6 +53,7 @@ class SubEditActivity : BaseActivity() {
|
||||
binding.etRemarks.text = Utils.getEditable(subItem.remarks)
|
||||
binding.etUrl.text = Utils.getEditable(subItem.url)
|
||||
binding.chkEnable.isChecked = subItem.enabled
|
||||
binding.autoUpdateCheck.isChecked = subItem.autoUpdate
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -76,6 +84,7 @@ class SubEditActivity : BaseActivity() {
|
||||
subItem.remarks = binding.etRemarks.text.toString()
|
||||
subItem.url = binding.etUrl.text.toString()
|
||||
subItem.enabled = binding.chkEnable.isChecked
|
||||
subItem.autoUpdate = binding.autoUpdateCheck.isChecked
|
||||
|
||||
if (TextUtils.isEmpty(subItem.remarks)) {
|
||||
toast(R.string.sub_setting_remarks)
|
||||
@@ -130,4 +139,5 @@ class SubEditActivity : BaseActivity() {
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@ class SubSettingActivity : BaseActivity() {
|
||||
binding.recyclerView.setHasFixedSize(true)
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(this)
|
||||
binding.recyclerView.adapter = adapter
|
||||
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
||||
@@ -49,7 +49,6 @@ class UserAssetActivity : BaseActivity() {
|
||||
val view = binding.root
|
||||
setContentView(view)
|
||||
title = getString(R.string.title_user_asset_setting)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
binding.recyclerView.setHasFixedSize(true)
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(this)
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.LocaleList
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.util.Patterns
|
||||
import android.webkit.URLUtil
|
||||
@@ -317,6 +318,11 @@ object Utils {
|
||||
return extDir.absolutePath
|
||||
}
|
||||
|
||||
fun getDeviceIdForXUDPBaseKey(): String {
|
||||
val androidId = Settings.Secure.ANDROID_ID.toByteArray(charset("UTF-8"))
|
||||
return Base64.encodeToString(androidId.copyOf(32), Base64.NO_PADDING.or(Base64.URL_SAFE))
|
||||
}
|
||||
|
||||
fun getUrlContext(url: String, timeout: Int): String {
|
||||
var result: String
|
||||
var conn: HttpURLConnection? = null
|
||||
|
||||
@@ -64,7 +64,7 @@ object V2rayConfigUtil {
|
||||
|
||||
inbounds(v2rayConfig)
|
||||
|
||||
httpRequestObject(outbound)
|
||||
updateOutboundWithGlobalSettings(outbound)
|
||||
|
||||
v2rayConfig.outbounds[0] = outbound
|
||||
|
||||
@@ -399,10 +399,37 @@ object V2rayConfigUtil {
|
||||
return true
|
||||
}
|
||||
|
||||
private fun httpRequestObject(outbound: V2rayConfig.OutboundBean): Boolean {
|
||||
private fun updateOutboundWithGlobalSettings(outbound: V2rayConfig.OutboundBean): Boolean {
|
||||
try {
|
||||
var muxEnabled = settingsStorage?.decodeBool(AppConfig.PREF_MUX_ENABLED, false)
|
||||
|
||||
val protocol = outbound.protocol
|
||||
if (protocol.equals(EConfigType.SHADOWSOCKS.name, true)
|
||||
|| protocol.equals(EConfigType.SOCKS.name, true)
|
||||
|| protocol.equals(EConfigType.TROJAN.name, true)
|
||||
) {
|
||||
muxEnabled = false
|
||||
} else if (protocol.equals(EConfigType.VLESS.name, true)
|
||||
&& outbound.settings?.vnext?.get(0)?.users?.get(0)?.flow?.isNotEmpty() == true
|
||||
) {
|
||||
muxEnabled = false
|
||||
}
|
||||
|
||||
if (muxEnabled == true) {
|
||||
outbound.mux?.enabled = true
|
||||
outbound.mux?.concurrency = 8
|
||||
outbound.mux?.xudpConcurrency =
|
||||
settingsStorage?.decodeInt(AppConfig.PREF_MUX_XUDP_CONCURRENCY) ?: 8
|
||||
outbound.mux?.xudpProxyUDP443 =
|
||||
settingsStorage?.decodeString(AppConfig.PREF_MUX_XUDP_QUIC) ?: "reject"
|
||||
} else {
|
||||
outbound.mux?.enabled = false
|
||||
outbound.mux?.concurrency = -1
|
||||
}
|
||||
|
||||
if (outbound.streamSettings?.network == DEFAULT_NETWORK
|
||||
&& outbound.streamSettings?.tcpSettings?.header?.type == HTTP) {
|
||||
&& outbound.streamSettings?.tcpSettings?.header?.type == HTTP
|
||||
) {
|
||||
val path = outbound.streamSettings?.tcpSettings?.header?.request?.path
|
||||
val host = outbound.streamSettings?.tcpSettings?.header?.request?.headers?.Host
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.v2ray.ang.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import android.content.*
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.ArrayAdapter
|
||||
@@ -40,7 +41,18 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
||||
fun startListenBroadcast() {
|
||||
isRunning.value = false
|
||||
getApplication<AngApplication>().registerReceiver(mMsgReceiver, IntentFilter(AppConfig.BROADCAST_ACTION_ACTIVITY))
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
getApplication<AngApplication>().registerReceiver(
|
||||
mMsgReceiver,
|
||||
IntentFilter(AppConfig.BROADCAST_ACTION_ACTIVITY),
|
||||
Context.RECEIVER_EXPORTED
|
||||
)
|
||||
} else {
|
||||
getApplication<AngApplication>().registerReceiver(
|
||||
mMsgReceiver,
|
||||
IntentFilter(AppConfig.BROADCAST_ACTION_ACTIVITY)
|
||||
)
|
||||
}
|
||||
MessageUtil.sendMsg2Service(getApplication(), AppConfig.MSG_REGISTER_CLIENT, "")
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,9 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
|
||||
AppConfig.PREF_ROUTING_MODE,
|
||||
AppConfig.PREF_V2RAY_ROUTING_AGENT,
|
||||
AppConfig.PREF_V2RAY_ROUTING_BLOCKED,
|
||||
AppConfig.PREF_V2RAY_ROUTING_DIRECT, -> {
|
||||
AppConfig.PREF_V2RAY_ROUTING_DIRECT,
|
||||
AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL,
|
||||
AppConfig.PREF_MUX_XUDP_QUIC, -> {
|
||||
settingsStorage?.encode(key, sharedPreferences.getString(key, ""))
|
||||
}
|
||||
AppConfig.PREF_SPEED_ENABLED,
|
||||
@@ -51,12 +53,17 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
|
||||
AppConfig.PREF_PER_APP_PROXY,
|
||||
AppConfig.PREF_BYPASS_APPS,
|
||||
AppConfig.PREF_CONFIRM_REMOVE,
|
||||
AppConfig.PREF_START_SCAN_IMMEDIATE, -> {
|
||||
AppConfig.PREF_START_SCAN_IMMEDIATE,
|
||||
AppConfig.SUBSCRIPTION_AUTO_UPDATE,
|
||||
AppConfig.PREF_MUX_ENABLED, -> {
|
||||
settingsStorage?.encode(key, sharedPreferences.getBoolean(key, false))
|
||||
}
|
||||
AppConfig.PREF_SNIFFING_ENABLED -> {
|
||||
settingsStorage?.encode(key, sharedPreferences.getBoolean(key, true))
|
||||
}
|
||||
AppConfig.PREF_MUX_XUDP_CONCURRENCY -> {
|
||||
settingsStorage?.encode(key, sharedPreferences.getString(key, "8")?.toIntOrNull() ?: 8)
|
||||
}
|
||||
AppConfig.PREF_PER_APP_PROXY_SET -> {
|
||||
settingsStorage?.encode(key, sharedPreferences.getStringSet(key, setOf()))
|
||||
}
|
||||
|
||||
@@ -69,6 +69,28 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/layout_margin_top_height"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.0"
|
||||
android:text="@string/sub_auto_update" />
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatCheckBox
|
||||
android:id="@+id/auto_update_check"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="2dp"
|
||||
android:paddingEnd="6dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -94,6 +116,7 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -41,7 +41,12 @@
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="9dp">
|
||||
|
||||
<TextView
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -49,18 +54,18 @@
|
||||
android:minLines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_statistics"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:lines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textSize="12sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
android:id="@+id/feedback"
|
||||
android:icon="@drawable/ic_feedback_24dp"
|
||||
android:title="@string/title_pref_feedback" />
|
||||
<item
|
||||
android:id="@+id/privacy_policy"
|
||||
android:icon="@drawable/ic_info_24dp"
|
||||
android:title="@string/title_privacy_policy" />
|
||||
<!-- place holder for version text at the bottom -->
|
||||
<item
|
||||
android:id="@+id/placeholder"
|
||||
|
||||
@@ -97,7 +97,14 @@
|
||||
<string name="title_pref_per_app_proxy">وكيل لكل تطبيق</string>
|
||||
<string name="summary_pref_per_app_proxy">عام: التطبيق المحدد هو الوكيل، الاتصال غير المحدد مباشر؛ \nوضع التجاوز: التطبيق المحدد متصل مباشرة، الوكيل غير المحدد. \nالخيار لتحديد التطبيق الوكيل تلقائيا في القائمة</string>
|
||||
<string name="title_pref_mux_enabled">تمكين Mux</string>
|
||||
<string name="summary_pref_mux_enabled">التمكين قد يسرع الشبكة والتبديل بين الشبكات قد يكون فلاش</string>
|
||||
<string name="summary_pref_mux_enabled">حركة مرور TCP مع 8 اتصالات افتراضية، قم بتخصيص كيفية التعامل مع UDP وQUIC أدناهn\أسرع، لكنه قد يسبب اتصالاً غير مستقر</string>
|
||||
<string name="title_pref_mux_xudp_concurency">اتصالات XUDP (النطاق من -1 إلى 1024)</string>
|
||||
<string name="title_pref_mux_xudp_quic">التعامل مع QUIC في نفق مكس</string>
|
||||
<string-array name="mux_xudp_quic_entries">
|
||||
<item>يرفض</item>
|
||||
<item>مسموح</item>
|
||||
<item>يتخطى</item>
|
||||
</string-array>
|
||||
<string name="title_pref_speed_enabled">تمكين عرض السرعة</string>
|
||||
<string name="summary_pref_speed_enabled">عرض السرعة الحالية في الإشعار.\nسيتغير رمز الإشعار استنادًا إلى الاستخدام.</string>
|
||||
<string name="title_pref_sniffing_enabled">تمكين Sniffing</string>
|
||||
@@ -147,19 +154,19 @@
|
||||
<string name="logcat_copy">نسخ</string>
|
||||
<string name="logcat_clear">مسح</string>
|
||||
<string name="title_service_restart">إعادة تشغيل الخدمة</string>
|
||||
<string name="title_del_all_config">حذف كل التكوين</string>
|
||||
<string name="title_del_duplicate_config">حذف التكوين المكرر</string>
|
||||
<string name="title_del_invalid_config">حذف التكوين غير الصالح (اختبر أولا)</string>
|
||||
<string name="title_del_all_config">حذف الكل (قبل أول خطوة)</string>
|
||||
<string name="title_del_duplicate_config">حذف المكررات (2)</string>
|
||||
<string name="title_del_invalid_config">حذف العناوين العاطلة (بعد الاختبار؛ 4)</string>
|
||||
<string name="title_export_all">تصدير التكوينات غير المخصصة إلى الحافظة</string>
|
||||
<string name="title_sub_setting">إعدادات مجموعة الاشتراك</string>
|
||||
<string name="sub_setting_remarks">ملاحظات</string>
|
||||
<string name="sub_setting_url">URL اختياري</string>
|
||||
<string name="sub_setting_enable">تمكين التحديث</string>
|
||||
<string name="title_sub_update">تحديث الاشتراك</string>
|
||||
<string name="title_sub_update">تحديث الاشتراك (1)</string>
|
||||
<string name="title_ping_all_server">Tcping كل التكوين</string>
|
||||
<string name="title_real_ping_all_server">تأخير الحقيقي لكل التكوين</string>
|
||||
<string name="title_real_ping_all_server">اختبر كل العناوين (3)</string>
|
||||
<string name="title_user_asset_setting">ملفات الأصول الجغرافية</string>
|
||||
<string name="title_sort_by_test_results">الترتيب بناءً على نتائج الاختبار</string>
|
||||
<string name="title_sort_by_test_results">ترتيب العناوين حسب نتائج الاختبار (5)</string>
|
||||
<string name="title_filter_config">تصفية ملف التكوين</string>
|
||||
<string name="filter_config_all">جميع مجموعات الاشتراك</string>
|
||||
<string name="title_del_duplicate_config_count">حذف %d من التكوينات المكررة</string>
|
||||
@@ -192,9 +199,9 @@
|
||||
<item>تصدير إلى الحافظة</item>
|
||||
</string-array>
|
||||
<string-array name="routing_tag">
|
||||
<item>URL الوكيل أو IP</item>
|
||||
<item>URL المباشر أو IP</item>
|
||||
<item>URL المحظور أو IP</item>
|
||||
<item>مسار وكيل أو IP</item>
|
||||
<item>مسار مباشر أو IP</item>
|
||||
<item>مسار محظور أو IP</item>
|
||||
</string-array>
|
||||
<string-array name="routing_mode">
|
||||
<item>وكيل عالمي</item>
|
||||
|
||||
@@ -98,7 +98,14 @@
|
||||
<string name="summary_pref_per_app_proxy">عمومی: برنامه بررسی شده پروکسی است، اتصال مستقیم بدون بررسی است. \nحالت bypass: برنامه بررسی شده مستقیما متصل است، پراکسی بررسی نشده است. \nگزینهای برای انتخاب خودکار پروکسی برنامه در منو است</string>
|
||||
|
||||
<string name="title_pref_mux_enabled">فعال کردن Mux</string>
|
||||
<string name="summary_pref_mux_enabled">فعال کردن شاید سرعت بخشیدن به شبکه و تغییر شبکه شاید فلش، بهبود کند</string>
|
||||
<string name="summary_pref_mux_enabled">سریعتر است، اما ممکن است باعث اتصال ناپایدار شود\nمخزن ترافیک TCP با 8 اتصال پیشفرض، نحوه مدیریت UDP و QUIC را در زیر سفارشی کنید</string>
|
||||
<string name="title_pref_mux_xudp_concurency">اتصالات XUDP (محدوده -1 تا 1024)</string>
|
||||
<string name="title_pref_mux_xudp_quic">مدیریت QUIC در تونل mux</string>
|
||||
<string-array name="mux_xudp_quic_entries">
|
||||
<item>رد کردن</item>
|
||||
<item>مجاز</item>
|
||||
<item>جست و خیز کردن</item>
|
||||
</string-array>
|
||||
|
||||
<string name="title_pref_speed_enabled">فعال کردن نمایش سرعت</string>
|
||||
<string name="summary_pref_speed_enabled">نمایش سرعت فعلی در قسمت آگاهسازی. \nآیکون آگاهسازی بر اساس استفاده تغییر میکند.</string>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<string name="menu_item_import_config_manually_trojan">Ручной ввод профиля Trojan</string>
|
||||
<string name="menu_item_import_config_custom">Пользовательский профиль</string>
|
||||
<string name="menu_item_import_config_custom_clipboard">Импорт из буфера обмена</string>
|
||||
<string name="menu_item_import_config_custom_local">Импорт с устройства</string>
|
||||
<string name="menu_item_import_config_custom_local">Импорт из файла</string>
|
||||
<string name="menu_item_import_config_custom_url">Импорт из URL</string>
|
||||
<string name="menu_item_import_config_custom_url_scan">Импорт сканированием URL</string>
|
||||
<string name="del_config_comfirm">Подтверждаете удаление?</string>
|
||||
@@ -103,7 +103,14 @@
|
||||
<string name="summary_pref_per_app_proxy">Основной: выделенное приложение соединяется через прокси, не выделенное — напрямую; \n\nРежим обхода: выделенное приложение соединяется напрямую, не выделенное — через прокси.\n\nЕсть возможность автоматического выбора проксируемых приложений в меню.</string>
|
||||
|
||||
<string name="title_pref_mux_enabled">Использовать мультиплексирование</string>
|
||||
<string name="summary_pref_mux_enabled">Включение может ускорить работу и переключение сети</string>
|
||||
<string name="summary_pref_mux_enabled">Быстрее, но это может привести к нестабильному соединению.\nМультиплексирование TCP-трафика с 8 соединениями по умолчанию, ниже можно настроить обработку UDP и QUIC.</string>
|
||||
<string name="title_pref_mux_xudp_concurency">XUDP-соединения (диапазон от -1 до 1024)</string>
|
||||
<string name="title_pref_mux_xudp_quic">Обработка QUIC в мультиплексном туннеле</string>
|
||||
<string-array name="mux_xudp_quic_entries">
|
||||
<item>отклонять</item>
|
||||
<item>разрешать</item>
|
||||
<item>пропускать</item>
|
||||
</string-array>
|
||||
|
||||
<string name="title_pref_speed_enabled">Отображение скорости</string>
|
||||
<string name="summary_pref_speed_enabled">Показывать текущую скорость в уведомлении.\nЗначок будет меняться в зависимости от использования.</string>
|
||||
@@ -159,10 +166,15 @@
|
||||
<string name="summary_pref_feedback">Предложить улучшение или сообщить об ошибке на GitHub</string>
|
||||
<string name="summary_pref_tg_group">Присоединиться к группе в Telegram</string>
|
||||
<string name="toast_tg_app_not_found">Приложение Telegram не найдено</string>
|
||||
<string name="title_privacy_policy">Политика конфиденциальности</string>
|
||||
|
||||
<string name="title_pref_promotion">Содействие</string>
|
||||
<string name="summary_pref_promotion">Содействие, нажмите для получения подробной информации (пожертвование может быть удалено)</string>
|
||||
|
||||
<string name="title_pref_auto_update_subscription">Автоматическое обновление подписок</string>
|
||||
<string name="summary_pref_auto_update_subscription">Автоматическое обновление подписок в фоновом режиме с указанным интервалом. В зависимости от устройства эта функция может работать не всегда.</string>
|
||||
<string name="title_pref_auto_update_interval">Интервал автообновления (мин.)</string>
|
||||
|
||||
<string name="title_core_loglevel">Подробность ведения журнала</string>
|
||||
<string name="title_mode">Режим</string>
|
||||
<string name="title_mode_help">Нажмите для получения дополнительной информации</string>
|
||||
@@ -175,12 +187,13 @@
|
||||
<string name="title_service_restart">Перезапуск службы</string>
|
||||
<string name="title_del_all_config">Удалить все профили</string>
|
||||
<string name="title_del_duplicate_config">Удалить дубликаты профилей</string>
|
||||
<string name="title_del_invalid_config">Удалить сбойные профили (после проверки)</string>
|
||||
<string name="title_del_invalid_config">Удалить нерабочие профили (после проверки)</string>
|
||||
<string name="title_export_all">Экспорт всех профилей в буфер обмена</string>
|
||||
<string name="title_sub_setting">Группы</string>
|
||||
<string name="sub_setting_remarks">примечания</string>
|
||||
<string name="sub_setting_url">URL (необязательно)</string>
|
||||
<string name="sub_setting_enable">использовать обновление</string>
|
||||
<string name="sub_setting_enable">Использовать обновление</string>
|
||||
<string name="sub_auto_update">Использовать автоматическое обновление</string>
|
||||
<string name="title_sub_update">Обновить подписку</string>
|
||||
<string name="title_ping_all_server">Проверка доступности профилей</string>
|
||||
<string name="title_real_ping_all_server">Время отклика профилей</string>
|
||||
@@ -199,7 +212,7 @@
|
||||
<string name="routing_settings_delete">Очистить</string>
|
||||
<string name="routing_settings_scan_replace">Сканировать и заменить</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_testing">Проверка…</string>
|
||||
@@ -210,6 +223,9 @@
|
||||
<string name="connection_connected">Подключено, нажмите для проверки</string>
|
||||
<string name="connection_not_connected">Не подключено</string>
|
||||
|
||||
<string name="import_subscription_success">Подписка импортирована</string>
|
||||
<string name="import_subscription_failure">Невозможно импортировать подписку</string>
|
||||
|
||||
<string-array name="share_method">
|
||||
<item>QR-код</item>
|
||||
<item>Экспорт в буфер обмена</item>
|
||||
@@ -239,7 +255,5 @@
|
||||
<item>VPN</item>
|
||||
<item>Только прокси</item>
|
||||
</string-array>
|
||||
<string name="import_subscription_success">Подписка импортирована</string>
|
||||
<string name="import_subscription_failure">Подписка не импортирована</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -97,7 +97,15 @@
|
||||
<string name="summary_pref_per_app_proxy">- Chung: Ứng dụng đã chọn sẽ kết nối Proxy, chưa lựa chọn sẽ kết nối trực tiếp. \n- Bỏ qua kết nối: Ứng dụng được chọn sẽ trực tiếp kết nối, không lựa chọn sẽ kết nối qua Proxy. \n- Lựa chọn để tự động chọn ứng dụng Proxy trong Menu.</string>
|
||||
|
||||
<string name="title_pref_mux_enabled">Cho phép Mux</string>
|
||||
<string name="summary_pref_mux_enabled">Bật lên có thể làm tăng tốc độ mạng và chuyển mạng nhanh hơn.</string>
|
||||
<string name="summary_pref_mux_enabled">Nhanh hơn nhưng có thể khiến kết nối không ổn định\nMux lưu lượng TCP với 8 kết nối mặc định, tùy chỉnh cách xử lý UDP và QUIC bên dưới</string>
|
||||
<string name="title_pref_mux_xudp_concurency">Kết nối XUDP (phạm vi -1 đến 1024)</string>
|
||||
<string name="title_pref_mux_xudp_quic">Xử lý QUIC trong đường hầm mux</string>
|
||||
<string-array name="mux_xudp_quic_entries">
|
||||
<item>từ chối</item>
|
||||
<item>cho phép</item>
|
||||
<item>nhảy</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<string name="title_pref_speed_enabled">Cho phép hiển thị tốc độ mạng</string>
|
||||
<string name="summary_pref_speed_enabled">Hiển thị tốc độ mạng hiện tại trên thanh thông báo.\nBiểu tượng trên thanh trạng thái có thể thay đổi tùy vào mức sử dụng.</string>
|
||||
|
||||
@@ -96,8 +96,15 @@
|
||||
<string name="title_pref_per_app_proxy">分应用代理</string>
|
||||
<string name="summary_pref_per_app_proxy">常规:勾选的App被代理,未勾选的直连;\n绕行模式:勾选的App直连,未勾选的被代理.\n不明白者在菜单中选择自动选中需代理应用</string>
|
||||
|
||||
<string name="title_pref_mux_enabled">启用Mux多路复用</string>
|
||||
<string name="summary_pref_mux_enabled">开启可能会加速,关闭可能会减少断流</string>
|
||||
<string name="title_pref_mux_enabled">启用 Mux 多路复用</string>
|
||||
<string name="summary_pref_mux_enabled">减低延时,但可能会断流,建议不要启用。\nTCP 默认复用 8 个子链接,UDP 及 QUIC 流量处理方式下方可选。</string>
|
||||
<string name="title_pref_mux_xudp_concurency">XUDP 复用子链接数(可填 -1 至 1024)</string>
|
||||
<string name="title_pref_mux_xudp_quic">QUIC 流量处理方式</string>
|
||||
<string-array name="mux_xudp_quic_entries">
|
||||
<item>不代理</item>
|
||||
<item>多路复用</item>
|
||||
<item>原生</item>
|
||||
</string-array>
|
||||
|
||||
<string name="title_pref_speed_enabled">启用速度显示</string>
|
||||
<string name="summary_pref_speed_enabled">在通知中显示当前速度\n小图标显示流量的路由情况</string>
|
||||
@@ -153,10 +160,15 @@
|
||||
<string name="summary_pref_feedback">反馈改进或漏洞至 GitHub</string>
|
||||
<string name="summary_pref_tg_group">加入Telegram Group</string>
|
||||
<string name="toast_tg_app_not_found">未找到Telegram app</string>
|
||||
<string name="title_privacy_policy">隐私权政策</string>
|
||||
|
||||
<string name="title_pref_promotion">推广</string>
|
||||
<string name="summary_pref_promotion">一些推广,点击查看详情(捐赠可去除)</string>
|
||||
|
||||
<string name="title_pref_auto_update_subscription">自动更新订阅</string>
|
||||
<string name="summary_pref_auto_update_subscription">在后台按一定时间间隔自动更新您的订阅。受设备影响,此功能不一定总是有效</string>
|
||||
<string name="title_pref_auto_update_interval">自动更新间隔(分钟,最小值15)</string>
|
||||
|
||||
<string name="title_core_loglevel">日志级别</string>
|
||||
<string name="title_mode">模式</string>
|
||||
<string name="title_mode_help">点此查看更多帮助</string>
|
||||
@@ -175,6 +187,7 @@
|
||||
<string name="sub_setting_remarks">备注</string>
|
||||
<string name="sub_setting_url">可选地址(url)</string>
|
||||
<string name="sub_setting_enable">启用更新</string>
|
||||
<string name="sub_auto_update">启用自动更新</string>
|
||||
<string name="title_sub_update">更新订阅</string>
|
||||
<string name="title_ping_all_server">测试全部配置Tcping</string>
|
||||
<string name="title_real_ping_all_server">测试全部配置真连接</string>
|
||||
|
||||
@@ -96,8 +96,15 @@
|
||||
<string name="title_pref_per_app_proxy">Proxy 個別應用程式</string>
|
||||
<string name="summary_pref_per_app_proxy">常規:勾選的 App 啟用 Proxy,未勾選的直接連線;\n繞行模式:勾選的 App 直接連線,未勾選的啟用 Proxy。\n可在選單中選擇自動選中需 Proxy 應用</string>
|
||||
|
||||
<string name="title_pref_mux_enabled">啟用 Mux</string>
|
||||
<string name="summary_pref_mux_enabled">啟用或許會加快網路速度,切換或許會閃爍</string>
|
||||
<string name="title_pref_mux_enabled">啟用 Mux 多路復用</string>
|
||||
<string name="summary_pref_mux_enabled">減低延時 但可能會斷流\nTCP 默認復用 8 個子鏈接,UDP 及 QUIC 流量處理方式下方可選</string>
|
||||
<string name="title_pref_mux_xudp_concurency">XUDP 復用子鏈接數(可填 -1 至 1024)</string>
|
||||
<string name="title_pref_mux_xudp_quic">QUIC 流量處理方式</string>
|
||||
<string-array name="mux_xudp_quic_entries">
|
||||
<item>不代理</item>
|
||||
<item>多路復用</item>
|
||||
<item>原生</item>
|
||||
</string-array>
|
||||
|
||||
<string name="title_pref_speed_enabled">啟用速度顯示</string>
|
||||
<string name="summary_pref_speed_enabled">在通知中顯示當前速度\n小圖示顯示流量的轉送狀況</string>
|
||||
@@ -153,10 +160,15 @@
|
||||
<string name="summary_pref_feedback">前往 GitHub 回報錯誤</string>
|
||||
<string name="summary_pref_tg_group">加入 Telegram 群組</string>
|
||||
<string name="toast_tg_app_not_found">未找到 Telegram 應用程式</string>
|
||||
<string name="title_privacy_policy">隱私權政策</string>
|
||||
|
||||
<string name="title_pref_promotion">推廣</string>
|
||||
<string name="summary_pref_promotion">一些推廣,輕觸以檢視 (捐贈可去除)</string>
|
||||
|
||||
<string name="title_pref_auto_update_subscription">自動更新訂閱</string>
|
||||
<string name="summary_pref_auto_update_subscription">在後台以一定時間間隔自動更新您的訂閱。受設備影響,此功能不一定總是有效</string>
|
||||
<string name="title_pref_auto_update_interval">自動更新間隔(分鐘,最小值15)</string>
|
||||
|
||||
<string name="title_core_loglevel">記錄層級</string>
|
||||
<string name="title_mode">模式</string>
|
||||
<string name="title_mode_help">輕觸以檢視說明</string>
|
||||
@@ -175,6 +187,7 @@
|
||||
<string name="sub_setting_remarks">備註</string>
|
||||
<string name="sub_setting_url">Optional URL</string>
|
||||
<string name="sub_setting_enable">啟用更新</string>
|
||||
<string name="sub_auto_update">啟用自動更新</string>
|
||||
<string name="title_sub_update">更新訂閱</string>
|
||||
<string name="title_ping_all_server">偵測所有組態 Tcping</string>
|
||||
<string name="title_real_ping_all_server">偵測所有組態真延遲</string>
|
||||
|
||||
@@ -179,4 +179,10 @@
|
||||
<item>fa</item>
|
||||
<item>ar</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="mux_xudp_quic_value" translatable="false">
|
||||
<item>reject</item>
|
||||
<item>allow</item>
|
||||
<item>skip</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
||||
@@ -103,7 +103,14 @@
|
||||
<string name="summary_pref_per_app_proxy">General: Checked App is proxy, unchecked direct connection; \nbypass mode: checked app directly connected, unchecked proxy. \nThe option to automatically select the proxy application in the menu</string>
|
||||
|
||||
<string name="title_pref_mux_enabled">Enable Mux</string>
|
||||
<string name="summary_pref_mux_enabled">Enable maybe speed up network and switch network maybe flash</string>
|
||||
<string name="summary_pref_mux_enabled">Faster, but it may cause unstable connectivity\nTCP traffic mux with default 8 connections,customize how to handle UDP and QUIC below</string>
|
||||
<string name="title_pref_mux_xudp_concurency">XUDP connections(range -1 to 1024)</string>
|
||||
<string name="title_pref_mux_xudp_quic">Handling of QUIC in mux tunnel</string>
|
||||
<string-array name="mux_xudp_quic_entries">
|
||||
<item>reject</item>
|
||||
<item>allow</item>
|
||||
<item>skip</item>
|
||||
</string-array>
|
||||
|
||||
<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
|
||||
@@ -161,10 +168,15 @@
|
||||
<string name="summary_pref_feedback">Feedback enhancements or bugs to GitHub</string>
|
||||
<string name="summary_pref_tg_group">Join Telegram Group</string>
|
||||
<string name="toast_tg_app_not_found">Telegram app not found</string>
|
||||
<string name="title_privacy_policy">Privacy policy</string>
|
||||
|
||||
<string name="title_pref_promotion">Promotion</string>
|
||||
<string name="summary_pref_promotion">Promotion,click for details(Donation can be removed)</string>
|
||||
|
||||
<string name="title_pref_auto_update_subscription">Automatic update subscriptions</string>
|
||||
<string name="summary_pref_auto_update_subscription">Update your subscriptions automatically with an interval in background. Depending on the device, this feature may not always work</string>
|
||||
<string name="title_pref_auto_update_interval">Auto Update Interval (Minutes, Min value 15)</string>
|
||||
|
||||
<string name="title_core_loglevel">Log Level</string>
|
||||
<string name="title_mode">Mode</string>
|
||||
<string name="title_mode_help">Click me for more help</string>
|
||||
@@ -182,7 +194,8 @@
|
||||
<string name="title_sub_setting">Subscription group setting</string>
|
||||
<string name="sub_setting_remarks">remarks</string>
|
||||
<string name="sub_setting_url">Optional URL</string>
|
||||
<string name="sub_setting_enable">enable update</string>
|
||||
<string name="sub_setting_enable">Enable update</string>
|
||||
<string name="sub_auto_update">Enable automatic update</string>
|
||||
<string name="title_sub_update">Update subscription</string>
|
||||
<string name="title_ping_all_server">Tcping all configuration</string>
|
||||
<string name="title_real_ping_all_server">Real delay all configuration</string>
|
||||
|
||||
@@ -1,15 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<CheckBoxPreference
|
||||
android:key="pref_speed_enabled"
|
||||
android:summary="@string/summary_pref_speed_enabled"
|
||||
android:title="@string/title_pref_speed_enabled" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="pref_sniffing_enabled"
|
||||
android:summary="@string/summary_pref_sniffing_enabled"
|
||||
android:title="@string/title_pref_sniffing_enabled" />
|
||||
android:defaultValue="true"
|
||||
android:key="pref_sniffing_enabled"
|
||||
android:summary="@string/summary_pref_sniffing_enabled"
|
||||
android:title="@string/title_pref_sniffing_enabled" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_mux_enabled"
|
||||
android:summary="@string/summary_pref_mux_enabled"
|
||||
android:title="@string/title_pref_mux_enabled" />
|
||||
|
||||
<EditTextPreference
|
||||
android:key="pref_mux_xudp_concurency"
|
||||
android:summary="8"
|
||||
android:inputType="number"
|
||||
android:title="@string/title_pref_mux_xudp_concurency" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="reject"
|
||||
android:entries="@array/mux_xudp_quic_entries"
|
||||
android:entryValues="@array/mux_xudp_quic_value"
|
||||
android:key="pref_mux_xudp_quic"
|
||||
android:summary="%s"
|
||||
android:title="@string/title_pref_mux_xudp_quic" />
|
||||
|
||||
<PreferenceCategory android:title="@string/title_vpn_settings">
|
||||
<CheckBoxPreference
|
||||
@@ -17,30 +32,26 @@
|
||||
android:summary="@string/summary_pref_per_app_proxy"
|
||||
android:title="@string/title_pref_per_app_proxy" />
|
||||
|
||||
<!--<CheckBoxPreference-->
|
||||
<!--android:key="pref_mux_enabled"-->
|
||||
<!--android:summary="@string/summary_pref_mux_enabled"-->
|
||||
<!--android:title="@string/title_pref_mux_enabled" />-->
|
||||
<CheckBoxPreference
|
||||
android:key="pref_local_dns_enabled"
|
||||
android:summary="@string/summary_pref_local_dns_enabled"
|
||||
android:title="@string/title_pref_local_dns_enabled" />
|
||||
android:key="pref_local_dns_enabled"
|
||||
android:summary="@string/summary_pref_local_dns_enabled"
|
||||
android:title="@string/title_pref_local_dns_enabled" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_fake_dns_enabled"
|
||||
android:summary="@string/summary_pref_fake_dns_enabled"
|
||||
android:title="@string/title_pref_fake_dns_enabled" />
|
||||
android:key="pref_fake_dns_enabled"
|
||||
android:summary="@string/summary_pref_fake_dns_enabled"
|
||||
android:title="@string/title_pref_fake_dns_enabled" />
|
||||
|
||||
<EditTextPreference
|
||||
android:key="pref_local_dns_port"
|
||||
android:summary="10853"
|
||||
android:inputType="number"
|
||||
android:title="@string/title_pref_local_dns_port" />
|
||||
android:key="pref_local_dns_port"
|
||||
android:summary="10853"
|
||||
android:inputType="number"
|
||||
android:title="@string/title_pref_local_dns_port" />
|
||||
|
||||
<EditTextPreference
|
||||
android:key="pref_vpn_dns"
|
||||
android:summary="@string/summary_pref_remote_dns"
|
||||
android:title="@string/title_pref_vpn_dns" />
|
||||
android:key="pref_vpn_dns"
|
||||
android:summary="@string/summary_pref_remote_dns"
|
||||
android:title="@string/title_pref_vpn_dns" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/title_pref_routing">
|
||||
@@ -67,6 +78,44 @@
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/title_sub_setting">
|
||||
<CheckBoxPreference
|
||||
android:key="pref_auto_update_subscription"
|
||||
android:summary="@string/summary_pref_auto_update_subscription"
|
||||
android:title="@string/title_pref_auto_update_subscription" />
|
||||
<EditTextPreference
|
||||
android:key="pref_auto_update_interval"
|
||||
android:summary="1440"
|
||||
android:inputType="number"
|
||||
android:title="@string/title_pref_auto_update_interval" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/title_ui_settings">
|
||||
<CheckBoxPreference
|
||||
android:key="pref_speed_enabled"
|
||||
android:summary="@string/summary_pref_speed_enabled"
|
||||
android:title="@string/title_pref_speed_enabled" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_confirm_remove"
|
||||
android:summary="@string/summary_pref_confirm_remove"
|
||||
android:title="@string/title_pref_confirm_remove" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_start_scan_immediate"
|
||||
android:summary="@string/summary_pref_start_scan_immediate"
|
||||
android:title="@string/title_pref_start_scan_immediate" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="auto"
|
||||
android:entries="@array/language_select"
|
||||
android:entryValues="@array/language_select_value"
|
||||
android:key="pref_language"
|
||||
android:summary="%s"
|
||||
android:title="@string/title_language" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/title_advanced">
|
||||
|
||||
<CheckBoxPreference
|
||||
@@ -104,9 +153,9 @@
|
||||
android:title="@string/title_pref_remote_dns" />
|
||||
|
||||
<EditTextPreference
|
||||
android:key="pref_domestic_dns"
|
||||
android:summary="@string/summary_pref_domestic_dns"
|
||||
android:title="@string/title_pref_domestic_dns" />
|
||||
android:key="pref_domestic_dns"
|
||||
android:summary="@string/summary_pref_domestic_dns"
|
||||
android:title="@string/title_pref_domestic_dns" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="warning"
|
||||
@@ -117,34 +166,12 @@
|
||||
android:title="@string/title_core_loglevel" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="VPN"
|
||||
android:entries="@array/mode_entries"
|
||||
android:entryValues="@array/mode_value"
|
||||
android:key="pref_mode"
|
||||
android:summary="%s"
|
||||
android:title="@string/title_mode" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/title_ui_settings">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_confirm_remove"
|
||||
android:summary="@string/summary_pref_confirm_remove"
|
||||
android:title="@string/title_pref_confirm_remove" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_start_scan_immediate"
|
||||
android:summary="@string/summary_pref_start_scan_immediate"
|
||||
android:title="@string/title_pref_start_scan_immediate" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="auto"
|
||||
android:entries="@array/language_select"
|
||||
android:entryValues="@array/language_select_value"
|
||||
android:key="pref_language"
|
||||
android:defaultValue="VPN"
|
||||
android:entries="@array/mode_entries"
|
||||
android:entryValues="@array/mode_value"
|
||||
android:key="pref_mode"
|
||||
android:summary="%s"
|
||||
android:title="@string/title_language" />
|
||||
android:title="@string/title_mode" />
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
</PreferenceScreen>
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
buildToolsVer=33.0.2
|
||||
compileSdkVer=33
|
||||
targetSdkVer=33
|
||||
buildToolsVer=34.0.0
|
||||
compileSdkVer=34
|
||||
targetSdkVer=34
|
||||
kotlin.incremental=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
Reference in New Issue
Block a user