Compare commits

...

25 Commits

Author SHA1 Message Date
2dust 026bf6a37b up 1.10.27 2025-11-06 18:21:43 +08:00
solokot c117a334ce Russian translation improvements (#4997) 2025-11-02 10:15:59 +08:00
2dust 051520de37 Set HEV tunnel preference default to true
Changed the default value of the HEV tunnel setting to true across the app, including preference XML, settings UI, config manager, and view model. This ensures that the HEV tunnel is enabled by default for new users and maintains consistent default behavior throughout the application.
2025-11-01 11:29:08 +08:00
2dust b5146e4712 Comment out per-app proxy setting in preferences 2025-11-01 11:12:15 +08:00
2dust 4457b6b2c9 Refactor PerAppProxyActivity and add auto-enable logic 2025-11-01 11:08:41 +08:00
2dust 12edb051c3 Update config-related strings for clarity and consistency 2025-11-01 10:13:03 +08:00
2dust 923e3f32d1 up 1.10.26 2025-10-26 17:46:30 +08:00
2dust 5490db90c0 up 1.10.25 2025-10-26 17:39:37 +08:00
2dust cb68d42291 Check for update to add fdroid 2025-10-26 17:38:51 +08:00
2dust ec3a8e80d6 up 1.10.25 2025-10-26 16:30:28 +08:00
2dust eb0960125b Update build.yml 2025-10-26 16:29:40 +08:00
2dust 12b70e2088 Adjust the adapter that can modify APPLICATION_ID
Add APPLICATION_ID to the About page
2025-10-26 16:08:44 +08:00
2dust 0c473dea19 up 1.10.24 2025-10-15 17:57:41 +08:00
2dust e71dd7342a Update AndroidLibXrayLite 2025-10-15 17:56:33 +08:00
2dust a765215dda Update libs.versions.toml 2025-10-10 19:14:46 +08:00
2dust edea3027f7 Fix
https://github.com/2dust/v2rayN/issues/8060
2025-10-03 14:28:31 +08:00
2dust 305219c3bc Update libs.versions.toml 2025-10-03 14:28:24 +08:00
DHR60 9c4188fba7 Adjust DNS routing (#4905) 2025-09-13 13:55:53 +08:00
2dust 0f3124bece up 1.10.23 2025-09-11 19:09:59 +08:00
2dust 2614f72a36 Update AndroidLibXrayLite 2025-09-11 19:08:56 +08:00
2dust 480c7fc8a1 up 1.10.22 2025-09-05 18:37:08 +08:00
2dust 302e7f148e Update libs.versions.toml 2025-09-05 18:36:42 +08:00
2dust 98d6da983b Update AndroidLibXrayLite 2025-09-05 18:36:27 +08:00
2dust f6f60f77d3 up 1.10.21 2025-09-01 09:41:04 +08:00
2dust 7be0fb3ecd Update AndroidLibXrayLite 2025-09-01 09:40:27 +08:00
23 changed files with 206 additions and 126 deletions
+1 -1
View File
@@ -153,7 +153,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/V2rayNG/app/build/outputs/apk/*playstore*/release/*.apk
file: ${{ github.workspace }}/V2rayNG/app/build/outputs/apk/*/release/*.apk
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true
+2 -2
View File
@@ -12,8 +12,8 @@ android {
applicationId = "com.v2ray.ang"
minSdk = 21
targetSdk = 35
versionCode = 670
versionName = "1.10.20"
versionCode = 678
versionName = "1.10.27"
multiDexEnabled = true
val abiFilterList = (properties["ABI_FILTERS"] as? String)?.split(';')
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">v2rayNG (F-Droid)</string>
</resources>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:enabled="true"
android:icon="@drawable/ic_qu_switch_24dp"
android:shortcutDisabledMessage="@string/app_widget_name"
android:shortcutId="shortcuts_switch"
android:shortcutLongLabel="@string/app_widget_name"
android:shortcutShortLabel="@string/app_widget_name">
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.v2ray.ang.ui.ScSwitchActivity"
android:targetPackage="com.v2ray.ang.fdroid" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
<shortcut
android:enabled="true"
android:icon="@drawable/ic_qu_scan_24dp"
android:shortcutDisabledMessage="@string/menu_item_import_config_qrcode"
android:shortcutId="shortcuts_scan"
android:shortcutLongLabel="@string/menu_item_import_config_qrcode"
android:shortcutShortLabel="@string/menu_item_import_config_qrcode">
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.v2ray.ang.ui.ScScannerActivity"
android:targetPackage="com.v2ray.ang.fdroid" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
</shortcuts>
+2 -2
View File
@@ -195,8 +195,8 @@
android:resource="@xml/app_widget_provider" />
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.v2ray.ang.action.widget.click" />
<action android:name="com.v2ray.ang.action.activity" />
<action android:name="${applicationId}.action.widget.click" />
<action android:name="${applicationId}.action.activity" />
</intent-filter>
</receiver>
<receiver
@@ -75,9 +75,9 @@ object AppConfig {
const val PROTOCOL_FREEDOM = "freedom"
/** Broadcast actions. */
const val BROADCAST_ACTION_SERVICE = "com.v2ray.ang.action.service"
const val BROADCAST_ACTION_ACTIVITY = "com.v2ray.ang.action.activity"
const val BROADCAST_ACTION_WIDGET_CLICK = "com.v2ray.ang.action.widget.click"
const val BROADCAST_ACTION_SERVICE = "$ANG_PACKAGE.action.service"
const val BROADCAST_ACTION_ACTIVITY = "$ANG_PACKAGE.action.activity"
const val BROADCAST_ACTION_WIDGET_CLICK = "$ANG_PACKAGE.action.widget.click"
/** Tasker extras. */
const val TASKER_EXTRA_BUNDLE = "com.twofortyfouram.locale.intent.extra.BUNDLE"
@@ -122,7 +122,7 @@ object ShadowsocksFmt : FmtBase() {
fun toUri(config: ProfileItem): String {
val pw = "${config.method}:${config.password}"
return toUri(config, Utils.encode(pw), null)
return toUri(config, Utils.encode(pw, true), null)
}
/**
@@ -51,7 +51,7 @@ object SocksFmt : FmtBase() {
else
":"
return toUri(config, Utils.encode(pw), null)
return toUri(config, Utils.encode(pw, true), null)
}
/**
@@ -100,8 +100,19 @@ object UpdateCheckerManager {
}
private fun getDownloadUrl(release: GitHubRelease, abi: String): String {
return release.assets.find { it.name.contains(abi) }?.browserDownloadUrl
?: release.assets.firstOrNull()?.browserDownloadUrl
val fDroid = "fdroid"
val assetsByAbi = release.assets.filter {
(it.name.contains(abi, true))
}
val asset = if (BuildConfig.APPLICATION_ID.contains(fDroid, ignoreCase = true)) {
assetsByAbi.firstOrNull { it.name.contains(fDroid) }
} else {
assetsByAbi.firstOrNull { !it.name.contains(fDroid) }
}
return asset?.browserDownloadUrl
?: throw IllegalStateException("No compatible APK found")
}
}
@@ -470,7 +470,7 @@ object V2rayConfigManager {
)
}
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_USE_HEV_TUNNEL) == false) {
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_USE_HEV_TUNNEL ,true) == false) {
// DNS inbound
val remoteDns = SettingsManager.getRemoteDnsServers()
@@ -623,17 +623,16 @@ object V2rayConfigManager {
// DNS routing
v2rayConfig.routing.rules.add(
0, RulesBean(
outboundTag = AppConfig.TAG_PROXY,
inboundTag = arrayListOf(AppConfig.TAG_DNS),
RulesBean(
outboundTag = AppConfig.TAG_DIRECT,
inboundTag = arrayListOf(AppConfig.TAG_DOMESTIC_DNS),
domain = null
)
)
v2rayConfig.routing.rules.add(
0, RulesBean(
outboundTag = AppConfig.TAG_DIRECT,
inboundTag = arrayListOf(AppConfig.TAG_DOMESTIC_DNS),
RulesBean(
outboundTag = AppConfig.TAG_PROXY,
inboundTag = arrayListOf(AppConfig.TAG_DNS),
domain = null
)
)
@@ -295,7 +295,7 @@ class V2RayVpnService : VpnService(), ServiceControl {
* Starts the tun2socks process with the appropriate parameters.
*/
private fun runTun2socks() {
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_USE_HEV_TUNNEL) == true) {
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_USE_HEV_TUNNEL, true) == true) {
tun2SocksService = TProxyService(
context = applicationContext,
vpnInterface = mInterface,
@@ -127,6 +127,9 @@ class AboutActivity : BaseActivity() {
"v${BuildConfig.VERSION_NAME} (${SpeedtestManager.getLibVersion()})".also {
binding.tvVersion.text = it
}
BuildConfig.APPLICATION_ID.also {
binding.tvAppId.text = it
}
}
private fun backupConfiguration(outputZipFilePos: String): Pair<Boolean, String> {
@@ -42,10 +42,30 @@ class PerAppProxyActivity : BaseActivity() {
addCustomDividerToRecyclerView(binding.recyclerView, this, R.drawable.custom_divider)
initList()
binding.switchPerAppProxy.setOnCheckedChangeListener { _, isChecked ->
MmkvManager.encodeSettings(AppConfig.PREF_PER_APP_PROXY, isChecked)
}
binding.switchPerAppProxy.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_PER_APP_PROXY, false)
binding.switchBypassApps.setOnCheckedChangeListener { _, isChecked ->
MmkvManager.encodeSettings(AppConfig.PREF_BYPASS_APPS, isChecked)
}
binding.switchBypassApps.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_BYPASS_APPS, false)
binding.layoutSwitchBypassAppsTips.setOnClickListener {
Toasty.info(this, R.string.summary_pref_per_app_proxy, Toast.LENGTH_LONG, true).show()
}
}
private fun initList() {
binding.pbWaiting.show()
lifecycleScope.launch {
try {
binding.pbWaiting.show()
val blacklist = MmkvManager.decodeSettingsStringSet(AppConfig.PREF_PER_APP_PROXY_SET)
val blacklist =
MmkvManager.decodeSettingsStringSet(AppConfig.PREF_PER_APP_PROXY_SET)
val apps = withContext(Dispatchers.IO) {
val appsList = AppManagerUtil.loadNetworkAppList(this@PerAppProxyActivity)
@@ -75,26 +95,12 @@ class PerAppProxyActivity : BaseActivity() {
appsAll = apps
adapter = PerAppProxyAdapter(this@PerAppProxyActivity, apps, blacklist)
binding.recyclerView.adapter = adapter
binding.pbWaiting.hide()
} catch (e: Exception) {
binding.pbWaiting.hide()
Log.e(ANG_PACKAGE, "Error loading apps", e)
} finally {
binding.pbWaiting.hide()
}
}
binding.switchPerAppProxy.setOnCheckedChangeListener { _, isChecked ->
MmkvManager.encodeSettings(AppConfig.PREF_PER_APP_PROXY, isChecked)
}
binding.switchPerAppProxy.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_PER_APP_PROXY, false)
binding.switchBypassApps.setOnCheckedChangeListener { _, isChecked ->
MmkvManager.encodeSettings(AppConfig.PREF_BYPASS_APPS, isChecked)
}
binding.switchBypassApps.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_BYPASS_APPS, false)
binding.layoutSwitchBypassAppsTips.setOnClickListener {
Toasty.info(this, R.string.summary_pref_per_app_proxy, Toast.LENGTH_LONG, true).show()
}
}
override fun onPause() {
@@ -120,14 +126,40 @@ class PerAppProxyActivity : BaseActivity() {
})
}
return super.onCreateOptionsMenu(menu)
}
@SuppressLint("NotifyDataSetChanged")
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.select_all -> adapter?.let { it ->
R.id.select_all -> {
selectAllApp()
allowPerAppProxy()
true
}
R.id.select_proxy_app -> {
selectProxyAppAuto()
allowPerAppProxy()
true
}
R.id.import_proxy_app -> {
importProxyApp()
allowPerAppProxy()
true
}
R.id.export_proxy_app -> {
exportProxyApp()
true
}
else -> super.onOptionsItemSelected(item)
}
private fun selectAllApp() {
adapter?.let { it ->
val pkgNames = it.apps.map { it.packageName }
if (it.blacklist.containsAll(pkgNames)) {
it.apps.forEach {
@@ -142,27 +174,10 @@ class PerAppProxyActivity : BaseActivity() {
}
it.notifyDataSetChanged()
true
} == true
R.id.select_proxy_app -> {
selectProxyApp()
true
}
R.id.import_proxy_app -> {
importProxyApp()
true
}
R.id.export_proxy_app -> {
exportProxyApp()
true
}
else -> super.onOptionsItemSelected(item)
}
private fun selectProxyApp() {
private fun selectProxyAppAuto() {
toast(R.string.msg_downloading_content)
binding.pbWaiting.show()
@@ -199,6 +214,10 @@ class PerAppProxyActivity : BaseActivity() {
toastSuccess(R.string.toast_success)
}
private fun allowPerAppProxy() {
binding.switchPerAppProxy.isChecked = true
}
@SuppressLint("NotifyDataSetChanged")
private fun selectProxyApp(content: String, force: Boolean): Boolean {
try {
@@ -37,7 +37,7 @@ class SettingsActivity : BaseActivity() {
class SettingsFragment : PreferenceFragmentCompat() {
private val perAppProxy by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_PER_APP_PROXY) }
// private val perAppProxy by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_PER_APP_PROXY) }
private val localDns by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_LOCAL_DNS_ENABLED) }
private val fakeDns by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_FAKE_DNS_ENABLED) }
private val appendHttpProxy by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_APPEND_HTTP_PROXY) }
@@ -74,11 +74,11 @@ class SettingsActivity : BaseActivity() {
override fun onCreatePreferences(bundle: Bundle?, s: String?) {
addPreferencesFromResource(R.xml.pref_settings)
perAppProxy?.setOnPreferenceClickListener {
startActivity(Intent(activity, PerAppProxyActivity::class.java))
perAppProxy?.isChecked = true
false
}
// perAppProxy?.setOnPreferenceClickListener {
// startActivity(Intent(activity, PerAppProxyActivity::class.java))
// perAppProxy?.isChecked = true
// false
// }
localDns?.setOnPreferenceChangeListener { _, any ->
updateLocalDns(any as Boolean)
true
@@ -227,7 +227,7 @@ class SettingsActivity : BaseActivity() {
dnsHosts?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_DNS_HOSTS)
delayTestUrl?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_DELAY_TEST_URL, AppConfig.DELAY_TEST_URL)
updateHevTunSettings(MmkvManager.decodeSettingsBool(AppConfig.PREF_USE_HEV_TUNNEL, false))
updateHevTunSettings(MmkvManager.decodeSettingsBool(AppConfig.PREF_USE_HEV_TUNNEL, true))
hevTunRwTimeout?.summary = MmkvManager.decodeSettingsString(AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT, AppConfig.HEVTUN_RW_TIMEOUT)
initSharedPreference()
@@ -254,6 +254,7 @@ class SettingsActivity : BaseActivity() {
listOf(
AppConfig.PREF_SNIFFING_ENABLED,
AppConfig.PREF_USE_HEV_TUNNEL
).forEach { key ->
findPreference<CheckBoxPreference>(key)?.isChecked =
MmkvManager.decodeSettingsBool(key, true)
@@ -269,8 +270,7 @@ class SettingsActivity : BaseActivity() {
AppConfig.PREF_DOUBLE_COLUMN_DISPLAY,
AppConfig.PREF_PREFER_IPV6,
AppConfig.PREF_PROXY_SHARING,
AppConfig.PREF_ALLOW_INSECURE,
AppConfig.PREF_USE_HEV_TUNNEL
AppConfig.PREF_ALLOW_INSECURE
).forEach { key ->
findPreference<CheckBoxPreference>(key)?.isChecked =
MmkvManager.decodeSettingsBool(key, false)
@@ -298,8 +298,8 @@ class SettingsActivity : BaseActivity() {
private fun updateMode(mode: String?) {
val vpn = mode == VPN
perAppProxy?.isEnabled = vpn
perAppProxy?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_PER_APP_PROXY, false)
// perAppProxy?.isEnabled = vpn
// perAppProxy?.isChecked = MmkvManager.decodeSettingsBool(AppConfig.PREF_PER_APP_PROXY, false)
localDns?.isEnabled = vpn
fakeDns?.isEnabled = vpn
appendHttpProxy?.isEnabled = vpn
@@ -134,11 +134,16 @@ object Utils {
* Encode a string to base64.
*
* @param text The string to encode.
* @param removePadding
* @return The base64 encoded string, or an empty string if encoding fails.
*/
fun encode(text: String): String {
fun encode(text: String, removePadding : Boolean = false): String {
return try {
Base64.encodeToString(text.toByteArray(Charsets.UTF_8), Base64.NO_WRAP)
var encoded = Base64.encodeToString(text.toByteArray(Charsets.UTF_8), Base64.NO_WRAP)
if (removePadding) {
encoded = encoded.trimEnd('=')
}
encoded
} catch (e: Exception) {
Log.e(AppConfig.TAG, "Failed to encode text to base64", e)
""
@@ -75,20 +75,20 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
AppConfig.PREF_APPEND_HTTP_PROXY,
AppConfig.PREF_ALLOW_INSECURE,
AppConfig.PREF_PREFER_IPV6,
AppConfig.PREF_PER_APP_PROXY,
// AppConfig.PREF_PER_APP_PROXY,
AppConfig.PREF_BYPASS_APPS,
AppConfig.PREF_CONFIRM_REMOVE,
AppConfig.PREF_START_SCAN_IMMEDIATE,
AppConfig.PREF_DOUBLE_COLUMN_DISPLAY,
AppConfig.SUBSCRIPTION_AUTO_UPDATE,
AppConfig.PREF_FRAGMENT_ENABLED,
AppConfig.PREF_MUX_ENABLED,
AppConfig.PREF_USE_HEV_TUNNEL
AppConfig.PREF_MUX_ENABLED
-> {
MmkvManager.encodeSettings(key, sharedPreferences.getBoolean(key, false))
}
AppConfig.PREF_SNIFFING_ENABLED -> {
AppConfig.PREF_SNIFFING_ENABLED,
AppConfig.PREF_USE_HEV_TUNNEL -> {
MmkvManager.encodeSettings(key, sharedPreferences.getBoolean(key, true))
}
@@ -236,7 +236,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:orientation="vertical"
android:padding="@dimen/padding_spacing_dp16">
<TextView
@@ -245,6 +245,13 @@
android:layout_height="wrap_content"
android:text="@string/title_about"
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
<TextView
android:id="@+id/tv_app_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_about"
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
</LinearLayout>
</LinearLayout>
+13 -13
View File
@@ -90,7 +90,7 @@
<string name="toast_none_data">Ничего нет</string>
<string name="toast_incorrect_protocol">Неправильный протокол</string>
<string name="toast_decoding_failed">Невозможно декодировать</string>
<string name="title_file_chooser">Выберите файл профиля</string>
<string name="title_file_chooser">Выберите профиль</string>
<string name="toast_require_file_manager">Установите файловый менеджер</string>
<string name="server_customize_config">Изменить профиль</string>
<string name="toast_config_file_invalid">Неправильный профиль</string>
@@ -159,11 +159,11 @@
<item>Пропускать</item>
</string-array>
<string name="title_pref_speed_enabled">Отображение скорости</string>
<string name="title_pref_speed_enabled">Показывать скорость</string>
<string name="summary_pref_speed_enabled">Показывать текущую скорость в уведомлении.\nЗначок будет меняться в зависимости от использования.</string>
<string name="title_pref_sniffing_enabled">Анализ пакетов</string>
<string name="summary_pref_sniffing_enabled">Использовать определение доменных имён в пакетах (по умолчанию включено)</string>
<string name="title_pref_sniffing_enabled">Анализировать пакеты</string>
<string name="summary_pref_sniffing_enabled">Пытаться определелять доменные имена в пакетах (по умолчанию включено)</string>
<string name="title_pref_route_only_enabled">Домен только для маршрутизации</string>
<string name="summary_pref_route_only_enabled">Использовать доменное имя только для маршрутизации и сохранять целевой адрес в виде IP.</string>
@@ -191,7 +191,7 @@
<string name="title_pref_dns_hosts">Узлы DNS (формат: домен:адрес,…)</string>
<string name="summary_pref_dns_hosts">домен:адрес,…</string>
<string name="title_pref_delay_test_url">Сервис проверки времени отклика (HTTP/HTTPS)</string>
<string name="title_pref_delay_test_url">Сервис проверки задержки (HTTP/HTTPS)</string>
<string name="summary_pref_delay_test_url">URL</string>
<string name="title_pref_proxy_sharing_enabled">Разрешать подключения из LAN</string>
@@ -207,17 +207,17 @@
<string name="title_pref_local_dns_port">Порт локальной DNS</string>
<string name="summary_pref_local_dns_port">Порт локальной DNS</string>
<string name="title_pref_confirm_remove">Подтверждение удаления профиля</string>
<string name="summary_pref_confirm_remove">Требовать двойное подтверждение удаления профиля</string>
<string name="title_pref_confirm_remove">Подтверждать удаление профиля</string>
<string name="summary_pref_confirm_remove">Обязательное подтверждение удаления профиля</string>
<string name="title_pref_start_scan_immediate">Сканирование при запуске</string>
<string name="title_pref_start_scan_immediate">Сканировать при запуске</string>
<string name="summary_pref_start_scan_immediate">Начинать сканирование сразу при запуске приложения или запускать функцию сканирования камерой или из изображения через панель инструментов</string>
<string name="title_pref_append_http_proxy">Дополнительный HTTP-прокси</string>
<string name="summary_pref_append_http_proxy">HTTP-прокси будет использоваться напрямую (из браузера и других поддерживающих приложений), минуя виртуальный сетевой адаптер (Android 10+)</string>
<string name="title_pref_double_column_display">Отображение в два столбца</string>
<string name="summary_pref_double_column_display">Список профилей выводится в виде двух столбцов, что позволяет показать больше информации на экране. Требуется перезапуск приложения.</string>
<string name="title_pref_double_column_display">Профили в два столбца</string>
<string name="summary_pref_double_column_display">Список профилей отображается двумя столбцами, что позволяет показать больше информации на экране. Требуется перезапуск приложения.</string>
<!-- AboutActivity -->
<string name="title_pref_feedback">Обратная связь</string>
@@ -237,7 +237,7 @@
<string name="title_pref_promotion">Содействие</string>
<string name="summary_pref_promotion">Содействие, нажмите для получения подробной информации (пожертвование может быть удалено)</string>
<string name="title_pref_auto_update_subscription">Автоматическое обновление подписок</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>
@@ -273,11 +273,11 @@
<string name="sub_setting_pre_profile_tip">Конфигурация должна быть уникальной</string>
<string name="title_sub_update">Обновить подписку группы</string>
<string name="title_ping_all_server">Проверить профили группы</string>
<string name="title_real_ping_all_server">Время отклика профилей группы</string>
<string name="title_real_ping_all_server">Проверить задержку профилей группы</string>
<string name="title_create_intelligent_selection_all_server">Создать конфигурацию умного выбора</string>
<string name="title_user_asset_setting">Файлы ресурсов</string>
<string name="title_sort_by_test_results">Сортировать по результатам теста</string>
<string name="title_filter_config">Фильтр групп</string>
<string name="title_filter_config">Фильтр профилей</string>
<string name="filter_config_all">Все группы</string>
<string name="title_del_duplicate_config_count">Удалено дубликатов профилей: %d</string>
<string name="title_del_config_count">Удалено профилей: %d</string>
@@ -20,7 +20,7 @@
<string name="toast_services_failure">启动服务失败</string>
<!--ServerActivity-->
<string name="title_server">配置文件</string>
<string name="title_server">配置</string>
<string name="menu_item_add_config">添加配置</string>
<string name="menu_item_save_config">保存配置</string>
<string name="menu_item_del_config">删除配置</string>
@@ -90,10 +90,10 @@
<string name="toast_none_data">没有数据</string>
<string name="toast_incorrect_protocol">不正确的协议</string>
<string name="toast_decoding_failed">解码失败</string>
<string name="title_file_chooser">选择一个配置文件</string>
<string name="title_file_chooser">选择一个配置</string>
<string name="toast_require_file_manager">请安装一个文件管理器</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="toast_none_data_clipboard">剪贴板中没有数据</string>
<string name="toast_invalid_url">无效的网址</string>
@@ -205,8 +205,8 @@
<string name="title_pref_local_dns_port">本地 DNS 端口</string>
<string name="summary_pref_local_dns_port">本地 DNS 端口</string>
<string name="title_pref_confirm_remove">删除配置文件确认</string>
<string name="summary_pref_confirm_remove">删除配置文件是否需要用户二次确认</string>
<string name="title_pref_confirm_remove">删除配置确认</string>
<string name="summary_pref_confirm_remove">删除配置是否需要用户二次确认</string>
<string name="title_pref_start_scan_immediate">立即启动扫码</string>
<string name="summary_pref_start_scan_immediate">启动时立即打开相机扫描,否则可在工具栏选择扫码或选照片</string>
@@ -215,7 +215,7 @@
<string name="summary_pref_append_http_proxy">浏览器 / 一些支持的应用 将直接使用 HTTP 代理, 而不经过虚拟网卡设备 (Android 10+)</string>
<string name="title_pref_double_column_display">启用双列显示</string>
<string name="summary_pref_double_column_display">配置文件列表以双列显示,允许在屏幕上显示更多内容。需要重启应用生效。</string>
<string name="summary_pref_double_column_display">配置列表以双列显示,允许在屏幕上显示更多内容。需要重启应用生效。</string>
<!-- AboutActivity -->
<string name="title_pref_feedback">反馈</string>
@@ -266,16 +266,16 @@
<string name="sub_setting_enable">启用更新</string>
<string name="sub_auto_update">启用自动更新</string>
<string name="sub_allow_insecure_url">允许不安全的 HTTP 地址</string>
<string name="sub_setting_pre_profile">前置代理配置文件别名</string>
<string name="sub_setting_next_profile">落地代理配置文件別名</string>
<string name="sub_setting_pre_profile_tip">请确保配置文件别名存在并唯一</string>
<string name="sub_setting_pre_profile">前置代理配置别名</string>
<string name="sub_setting_next_profile">落地代理配置別名</string>
<string name="sub_setting_pre_profile_tip">请确保配置别名存在并唯一</string>
<string name="title_sub_update">更新当前组订阅</string>
<string name="title_ping_all_server">测试当前组配置 Tcping</string>
<string name="title_real_ping_all_server">测试当前组配置真连接</string>
<string name="title_create_intelligent_selection_all_server">生成当前组智能选择配置</string>
<string name="title_user_asset_setting">资源文件</string>
<string name="title_sort_by_test_results">按测试结果排序</string>
<string name="title_filter_config">过滤配置文件</string>
<string name="title_filter_config">过滤配置</string>
<string name="filter_config_all">所有分组</string>
<string name="title_del_duplicate_config_count">删除 %d 个重复配置</string>
@@ -366,7 +366,7 @@
</string-array>
<string-array name="vpn_bypass_lan">
<item>跟随配置文件</item>
<item>跟随配置</item>
<item>绕过</item>
<item>不绕过</item>
</string-array>
+15 -15
View File
@@ -21,13 +21,13 @@
<string name="toast_services_failure">Start Services Failure</string>
<!--ServerActivity-->
<string name="title_server">Configuration file</string>
<string name="menu_item_add_config">Add config</string>
<string name="menu_item_save_config">Save config</string>
<string name="menu_item_del_config">Delete config</string>
<string name="menu_item_import_config_qrcode">Import config from QRcode</string>
<string name="menu_item_import_config_clipboard">Import config from Clipboard</string>
<string name="menu_item_import_config_local">Import config from locally</string>
<string name="title_server">Configuration</string>
<string name="menu_item_add_config">Add configuration</string>
<string name="menu_item_save_config">Save configuration</string>
<string name="menu_item_del_config">Delete configuration</string>
<string name="menu_item_import_config_qrcode">Import configuration from QRcode</string>
<string name="menu_item_import_config_clipboard">Import configuration from Clipboard</string>
<string name="menu_item_import_config_local">Import configuration from locally</string>
<string name="menu_item_import_config_manually_vmess">Type manually[VMess]</string>
<string name="menu_item_import_config_manually_vless">Type manually[VLESS]</string>
<string name="menu_item_import_config_manually_ss">Type manually[Shadowsocks]</string>
@@ -91,16 +91,16 @@
<string name="toast_none_data">There is nothing</string>
<string name="toast_incorrect_protocol">Incorrect protocol</string>
<string name="toast_decoding_failed">Decoding failed</string>
<string name="title_file_chooser">Select a Config File</string>
<string name="title_file_chooser">Select a configuration</string>
<string name="toast_require_file_manager">Please install a File Manager.</string>
<string name="server_customize_config">Customize Config</string>
<string name="toast_config_file_invalid">Invalid Config</string>
<string name="server_customize_config">Customize configuration</string>
<string name="toast_config_file_invalid">Invalid configuration</string>
<string name="server_lab_content">Content</string>
<string name="toast_none_data_clipboard">There is no data in the clipboard</string>
<string name="toast_invalid_url">Invalid URL</string>
<string name="toast_insecure_url_protocol">Please do not use the insecure HTTP protocol subscription address</string>
<string name="server_lab_need_inbound">Ensure inbounds port is consistent with the settings</string>
<string name="toast_malformed_josn">Config malformed</string>
<string name="toast_malformed_josn">Configuration malformed</string>
<string name="server_lab_request_host6">Host(SNI)(Optional)</string>
<string name="toast_action_not_allowed">Action not allowed</string>
<string name="server_obfs_password">Obfs password</string>
@@ -211,8 +211,8 @@
<string name="title_pref_local_dns_port">Local DNS port</string>
<string name="summary_pref_local_dns_port">Local DNS port</string>
<string name="title_pref_confirm_remove">Delete configuration file confirmation</string>
<string name="summary_pref_confirm_remove">Whether to delete the configuration file requires a second confirmation by the user</string>
<string name="title_pref_confirm_remove">Delete configuration confirmation</string>
<string name="summary_pref_confirm_remove">Whether to delete the configuration requires a second confirmation by the user</string>
<string name="title_pref_start_scan_immediate">Start scanning immediately</string>
<string name="summary_pref_start_scan_immediate">Open the camera to scan immediately at startup, otherwise you can choose to scan the code or select a photo in the toolbar</string>
@@ -281,7 +281,7 @@
<string name="title_create_intelligent_selection_all_server">Creating Intelligent Selection Current Group Configuration</string>
<string name="title_user_asset_setting">Asset files</string>
<string name="title_sort_by_test_results">Sorting by test results</string>
<string name="title_filter_config">Filter configuration file</string>
<string name="title_filter_config">Filter configuration</string>
<string name="filter_config_all">All groups</string>
<string name="title_del_duplicate_config_count">Delete %d duplicate configurations</string>
<string name="title_del_config_count">Delete %d configurations</string>
@@ -378,7 +378,7 @@
</string-array>
<string-array name="vpn_bypass_lan">
<item>Follow config</item>
<item>Follow configuration</item>
<item>Bypass</item>
<item>Not Bypass</item>
</string-array>
@@ -25,10 +25,10 @@
android:summary="@string/summary_pref_prefer_ipv6"
android:title="@string/title_pref_prefer_ipv6" />
<CheckBoxPreference
android:key="pref_per_app_proxy"
android:summary="@string/summary_pref_per_app_proxy"
android:title="@string/title_pref_per_app_proxy" />
<!-- <CheckBoxPreference-->
<!-- android:key="pref_per_app_proxy"-->
<!-- android:summary="@string/summary_pref_per_app_proxy"-->
<!-- android:title="@string/title_pref_per_app_proxy" />-->
<CheckBoxPreference
android:key="pref_local_dns_enabled"
@@ -79,6 +79,7 @@
android:title="@string/title_pref_vpn_mtu" />
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_use_hev_tunnel"
android:summary="@string/summary_pref_use_hev_tunnel"
android:title="@string/title_pref_use_hev_tunnel" />
+5 -5
View File
@@ -1,14 +1,14 @@
[versions]
agp = "8.12.1"
agp = "8.12.3"
desugarJdkLibs = "2.1.5"
gradleLicensePlugin = "0.9.8"
kotlin = "2.2.10"
kotlin = "2.2.20"
coreKtx = "1.16.0"
junit = "4.13.2"
junitVersion = "1.3.0"
espressoCore = "3.7.0"
appcompat = "1.7.1"
material = "1.12.0"
material = "1.13.0"
activity = "1.10.1"
constraintlayout = "2.2.1"
mmkvStatic = "1.3.14"
@@ -20,8 +20,8 @@ swiperefreshlayout = "1.1.0"
toasty = "1.5.2"
editorkit = "2.9.0"
core = "3.5.3"
workRuntimeKtx = "2.10.3"
lifecycleViewmodelKtx = "2.9.2"
workRuntimeKtx = "2.10.5"
lifecycleViewmodelKtx = "2.9.4"
multidex = "2.0.1"
mockitoMockitoInline = "5.2.0"
flexbox = "3.0.0"