diff --git a/V2rayNG/app/build.gradle b/V2rayNG/app/build.gradle
index 00cc729b..733784a0 100644
--- a/V2rayNG/app/build.gradle
+++ b/V2rayNG/app/build.gradle
@@ -17,8 +17,8 @@ android {
minSdkVersion 21
targetSdkVersion Integer.parseInt("$targetSdkVer")
multiDexEnabled true
- versionCode 523
- versionName "1.8.9"
+ versionCode 526
+ versionName "1.8.10"
}
buildTypes {
diff --git a/V2rayNG/app/src/main/AndroidManifest.xml b/V2rayNG/app/src/main/AndroidManifest.xml
index bdec513e..24d7d2bd 100644
--- a/V2rayNG/app/src/main/AndroidManifest.xml
+++ b/V2rayNG/app/src/main/AndroidManifest.xml
@@ -50,7 +50,7 @@
-
+
diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt
index 8a3be9e0..2012818a 100644
--- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt
+++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt
@@ -94,7 +94,7 @@ object AppConfig {
// subscription settings
const val SUBSCRIPTION_AUTO_UPDATE = "pref_auto_update_subscription"
const val SUBSCRIPTION_AUTO_UPDATE_INTERVAL = "pref_auto_update_interval"
- const val DEFAULT_UPDATE_INTERVAL = "1440" // 24 hours
- const val UPDATE_TASK_NAME = "subscription-updater"
+ const val SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL = "1440" // 24 hours
+ const val SUBSCRIPTION_UPDATE_TASK_NAME = "subscription_updater"
}
diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/SubscriptionUpdater.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/SubscriptionUpdater.kt
index 4eeaaa7e..acbe0040 100644
--- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/SubscriptionUpdater.kt
+++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/SubscriptionUpdater.kt
@@ -1,29 +1,24 @@
package com.v2ray.ang.service
-import android.Manifest
import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
-import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
-import androidx.core.app.ActivityCompat
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.extension.toast
import com.v2ray.ang.util.AngConfigManager
import com.v2ray.ang.util.MmkvManager
import com.v2ray.ang.util.Utils
-import kotlinx.coroutines.delay
object SubscriptionUpdater {
- const val notificationChannel = "update-subscription-channel"
+ const val notificationChannel = "subscription_update_channel"
class UpdateTask(context: Context, params: WorkerParameters) :
CoroutineWorker(context, params) {
@@ -31,23 +26,20 @@ object SubscriptionUpdater {
private val notificationManager = NotificationManagerCompat.from(applicationContext)
private val notification =
NotificationCompat.Builder(applicationContext, notificationChannel)
-
.setWhen(0)
.setTicker("Update")
- .setContentTitle("Subscription Update")
+ .setContentTitle(context.getString(R.string.title_pref_auto_update_subscription))
.setSmallIcon(R.drawable.ic_stat_name)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
- .setPriority(NotificationCompat.PRIORITY_MIN)
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
@SuppressLint("MissingPermission")
override suspend fun doWork(): Result {
- Log.d(AppConfig.ANG_PACKAGE, "start updating subscriptions")
-
+ 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) {
@@ -61,7 +53,10 @@ object SubscriptionUpdater {
notificationManager.createNotificationChannel(channel)
}
notificationManager.notify(3, notification.build())
- Log.d(AppConfig.ANG_PACKAGE, "update: ${subscription.remarks} subscription")
+ 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}")
@@ -72,10 +67,9 @@ object SubscriptionUpdater {
}
fun importBatchConfig(server: String?, subid: String = "") {
+ val append = subid.isEmpty()
- val append = subid.isNullOrEmpty()
-
- var count = AngConfigManager.importBatchConfig(server, subid, append)
+ val count = AngConfigManager.importBatchConfig(server, subid, append)
if (count <= 0) {
AngConfigManager.importBatchConfig(Utils.decode(server!!), subid, append)
}
diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt
index 86e648fe..9891568c 100644
--- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt
+++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt
@@ -96,7 +96,8 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter
diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt
index e2420ce3..c93fae00 100644
--- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt
+++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt
@@ -14,13 +14,10 @@ import androidx.work.multiprocess.RemoteWorkManager
import com.v2ray.ang.AngApplication
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
-import com.v2ray.ang.dto.AngConfig
import com.v2ray.ang.service.SubscriptionUpdater
import com.v2ray.ang.util.Utils
import com.v2ray.ang.viewmodel.SettingsViewModel
-import java.sql.Time
import java.util.concurrent.TimeUnit
-import kotlin.time.toDuration
class SettingsActivity : BaseActivity() {
private val settingsViewModel: SettingsViewModel by viewModels()
@@ -81,9 +78,9 @@ class SettingsActivity : BaseActivity() {
autoUpdateInterval?.setOnPreferenceChangeListener { _, any ->
val nval = any as String
autoUpdateInterval?.summary =
- if (TextUtils.isEmpty(nval) or (nval.toLong() < 15)) AppConfig.DEFAULT_UPDATE_INTERVAL else nval
+ if (TextUtils.isEmpty(nval) or (nval.toLong() < 1)) AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL else nval
configureUpdateTask(nval.toLong())
- false
+ true
}
// licenses.onClick {
@@ -180,7 +177,8 @@ class SettingsActivity : BaseActivity() {
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.DEFAULT_UPDATE_INTERVAL)
+ 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
@@ -233,9 +231,9 @@ class SettingsActivity : BaseActivity() {
private fun configureUpdateTask(interval: Long) {
val rw = RemoteWorkManager.getInstance(AngApplication.application)
- rw.cancelUniqueWork(AppConfig.UPDATE_TASK_NAME)
+ rw.cancelUniqueWork(AppConfig.SUBSCRIPTION_UPDATE_TASK_NAME)
rw.enqueueUniquePeriodicWork(
- AppConfig.UPDATE_TASK_NAME,
+ AppConfig.SUBSCRIPTION_UPDATE_TASK_NAME,
ExistingPeriodicWorkPolicy.UPDATE,
PeriodicWorkRequest.Builder(
SubscriptionUpdater.UpdateTask::class.java,
@@ -245,17 +243,14 @@ class SettingsActivity : BaseActivity() {
.apply {
setInitialDelay(interval, TimeUnit.MINUTES)
}
- .setConstraints(
- Constraints(
- NetworkType.CONNECTED,
- )
- ).build()
+ .build()
)
}
private fun cancelUpdateTask() {
val rw = RemoteWorkManager.getInstance(AngApplication.application)
- rw.cancelUniqueWork(AppConfig.UPDATE_TASK_NAME)
+ rw.cancelUniqueWork(AppConfig.SUBSCRIPTION_UPDATE_TASK_NAME)
+ }
private fun updateMux(enabled: Boolean) {
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity())
diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt
index b8cf2f54..4e0df222 100644
--- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt
+++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/V2rayConfigUtil.kt
@@ -401,17 +401,35 @@ object V2rayConfigUtil {
private fun updateOutboundWithGlobalSettings(outbound: V2rayConfig.OutboundBean): Boolean {
try {
- if (settingsStorage?.decodeBool(AppConfig.PREF_MUX_ENABLED) == true) {
+ 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"
+ 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
diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt
index 0d34c0bb..4fa407e8 100644
--- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt
+++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/viewmodel/SettingsViewModel.kt
@@ -40,6 +40,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
AppConfig.PREF_V2RAY_ROUTING_AGENT,
AppConfig.PREF_V2RAY_ROUTING_BLOCKED,
AppConfig.PREF_V2RAY_ROUTING_DIRECT,
+ AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL,
AppConfig.PREF_MUX_XUDP_QUIC, -> {
settingsStorage?.encode(key, sharedPreferences.getString(key, ""))
}
@@ -53,6 +54,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
AppConfig.PREF_BYPASS_APPS,
AppConfig.PREF_CONFIRM_REMOVE,
AppConfig.PREF_START_SCAN_IMMEDIATE,
+ AppConfig.SUBSCRIPTION_AUTO_UPDATE,
AppConfig.PREF_MUX_ENABLED, -> {
settingsStorage?.encode(key, sharedPreferences.getBoolean(key, false))
}
diff --git a/V2rayNG/app/src/main/res/layout/activity_sub_edit.xml b/V2rayNG/app/src/main/res/layout/activity_sub_edit.xml
index d61169cf..1bf37ac7 100644
--- a/V2rayNG/app/src/main/res/layout/activity_sub_edit.xml
+++ b/V2rayNG/app/src/main/res/layout/activity_sub_edit.xml
@@ -69,6 +69,28 @@
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
diff --git a/V2rayNG/app/src/main/res/layout/item_recycler_main.xml b/V2rayNG/app/src/main/res/layout/item_recycler_main.xml
index 2dc83fb9..b2fbd63d 100644
--- a/V2rayNG/app/src/main/res/layout/item_recycler_main.xml
+++ b/V2rayNG/app/src/main/res/layout/item_recycler_main.xml
@@ -41,7 +41,12 @@
android:orientation="vertical"
android:paddingStart="9dp">
-
+
+
-
+
+ android:textAppearance="@style/TextAppearance.AppCompat.Small"
+ android:textSize="12sp"/>
diff --git a/V2rayNG/app/src/main/res/values-ru/strings.xml b/V2rayNG/app/src/main/res/values-ru/strings.xml
index efc771cf..4989238b 100644
--- a/V2rayNG/app/src/main/res/values-ru/strings.xml
+++ b/V2rayNG/app/src/main/res/values-ru/strings.xml
@@ -32,7 +32,7 @@
Ручной ввод профиля Trojan
Пользовательский профиль
Импорт из буфера обмена
- Импорт с устройства
+ Импорт из файла
Импорт из URL
Импорт сканированием URL
Подтверждаете удаление?
@@ -103,12 +103,12 @@
Основной: выделенное приложение соединяется через прокси, не выделенное — напрямую; \n\nРежим обхода: выделенное приложение соединяется напрямую, не выделенное — через прокси.\n\nЕсть возможность автоматического выбора проксируемых приложений в меню.
Использовать мультиплексирование
- Быстрее, но это может привести к нестабильному соединению\nМультиплексор TCP-трафика с 8 соединениями по умолчанию, ниже можно настроить обработку UDP и QUIC.
+ Быстрее, но это может привести к нестабильному соединению.\nМультиплексирование TCP-трафика с 8 соединениями по умолчанию, ниже можно настроить обработку UDP и QUIC.
XUDP-соединения (диапазон от -1 до 1024)
- Обработка QUIC в мультиплексорном туннеле
+ Обработка QUIC в мультиплексном туннеле
- отклонять
- - допустимый
+ - разрешать
- пропускать
@@ -170,6 +170,10 @@
Содействие
Содействие, нажмите для получения подробной информации (пожертвование может быть удалено)
+ Автоматическое обновление подписок
+ Автоматическое обновление подписок в фоновом режиме с указанным интервалом. В зависимости от устройства эта функция может работать не всегда.
+ Интервал автообновления (мин.)
+
Подробность ведения журнала
Режим
Нажмите для получения дополнительной информации
@@ -182,12 +186,13 @@
Перезапуск службы
Удалить все профили
Удалить дубликаты профилей
- Удалить сбойные профили (после проверки)
+ Удалить нерабочие профили (после проверки)
Экспорт всех профилей в буфер обмена
Группы
примечания
URL (необязательно)
- использовать обновление
+ Использовать обновление
+ Использовать автоматическое обновление
Обновить подписку
Проверка доступности профилей
Время отклика профилей
@@ -206,7 +211,7 @@
Очистить
Сканировать и заменить
Сканировать и добавить
- Правила по умолчанию
+ Правила по умолчанию
Проверить подключение
Проверка…
@@ -217,6 +222,9 @@
Подключено, нажмите для проверки
Не подключено
+ Подписка импортирована
+ Невозможно импортировать подписку
+
- QR-код
- Экспорт в буфер обмена
@@ -246,7 +254,5 @@
- VPN
- Только прокси
- Подписка импортирована
- Подписка не импортирована
diff --git a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml
index 346ea0b6..45879449 100644
--- a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml
+++ b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml
@@ -97,7 +97,7 @@
常规:勾选的App被代理,未勾选的直连;\n绕行模式:勾选的App直连,未勾选的被代理.\n不明白者在菜单中选择自动选中需代理应用
启用 Mux 多路复用
- 减低延时 但可能会断流\nTCP 默认复用 8 个子链接,UDP 及 QUIC 流量处理方式下方可选
+ 减低延时,但可能会断流,建议不要启用。\nTCP 默认复用 8 个子链接,UDP 及 QUIC 流量处理方式下方可选。
XUDP 复用子链接数(可填 -1 至 1024)
QUIC 流量处理方式
@@ -164,6 +164,10 @@
推广
一些推广,点击查看详情(捐赠可去除)
+ 自动更新订阅
+ 在后台按一定时间间隔自动更新您的订阅。受设备影响,此功能不一定总是有效
+ 订阅自动更新间隔(分钟)
+
日志级别
模式
点此查看更多帮助
@@ -182,6 +186,7 @@
备注
可选地址(url)
启用更新
+ 启用自动更新
更新订阅
测试全部配置Tcping
测试全部配置真连接
diff --git a/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml b/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml
index d2ff9e90..2fbd228a 100644
--- a/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml
+++ b/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml
@@ -164,6 +164,10 @@
推廣
一些推廣,輕觸以檢視 (捐贈可去除)
+ 自動更新訂閱
+ 在後台以一定時間間隔自動更新您的訂閱。受設備影響,此功能不一定總是有效
+ 訂閱自動更新間隔(分鐘)
+
記錄層級
模式
輕觸以檢視說明
@@ -182,6 +186,7 @@
備註
Optional URL
啟用更新
+ 啟用自動更新
更新訂閱
偵測所有組態 Tcping
偵測所有組態真延遲
diff --git a/V2rayNG/app/src/main/res/values/strings.xml b/V2rayNG/app/src/main/res/values/strings.xml
index 6214b267..a27d1398 100644
--- a/V2rayNG/app/src/main/res/values/strings.xml
+++ b/V2rayNG/app/src/main/res/values/strings.xml
@@ -172,6 +172,10 @@
Promotion
Promotion,click for details(Donation can be removed)
+ Automatic update subscriptions
+ Update your subscriptions automatically with an interval in background. Depending on the device, this feature may not always work
+ Subscription Auto Update Interval (Minutes)
+
Log Level
Mode
Click me for more help
@@ -189,8 +193,8 @@
Subscription group setting
remarks
Optional URL
- enable update
- Auto update
+ Enable update
+ Enable automatic update
Update subscription
Tcping all configuration
Real delay all configuration
diff --git a/V2rayNG/app/src/main/res/xml/pref_settings.xml b/V2rayNG/app/src/main/res/xml/pref_settings.xml
index a14314d5..21c1751d 100644
--- a/V2rayNG/app/src/main/res/xml/pref_settings.xml
+++ b/V2rayNG/app/src/main/res/xml/pref_settings.xml
@@ -2,10 +2,10 @@
+ android:defaultValue="true"
+ android:key="pref_sniffing_enabled"
+ android:summary="@string/summary_pref_sniffing_enabled"
+ android:title="@string/title_pref_sniffing_enabled" />
+ 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_fake_dns_enabled"
+ android:summary="@string/summary_pref_fake_dns_enabled"
+ android:title="@string/title_pref_fake_dns_enabled" />
+ android:key="pref_local_dns_port"
+ android:summary="10853"
+ android:inputType="number"
+ android:title="@string/title_pref_local_dns_port" />
+ android:key="pref_vpn_dns"
+ android:summary="@string/summary_pref_remote_dns"
+ android:title="@string/title_pref_vpn_dns" />
@@ -78,6 +78,18 @@
+
+
+
+
+
+ android:key="pref_domestic_dns"
+ android:summary="@string/summary_pref_domestic_dns"
+ android:title="@string/title_pref_domestic_dns" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:title="@string/title_mode" />
-
-
+
\ No newline at end of file