diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
index 35dcc2a9..5fdc3448 100644
--- a/.idea/deploymentTargetSelector.xml
+++ b/.idea/deploymentTargetSelector.xml
@@ -7,6 +7,14 @@
+
+
+
+
+
+
+
+
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 3c559cc5..2b4e3984 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -8,11 +8,11 @@ android {
compileSdk = 34
defaultConfig {
- applicationId = "io.github.dovecoteescapee.byedpi"
+ applicationId = "io.github.romanvht.byedpi"
minSdk = 21
targetSdk = 34
versionCode = 10
- versionName = "1.3.6"
+ versionName = "1.3.7"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@@ -74,6 +74,7 @@ dependencies {
implementation("com.google.android.material:material:1.12.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.4")
implementation("androidx.lifecycle:lifecycle-service:2.8.4")
+ implementation("com.squareup.okhttp3:okhttp:4.12.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0340489d..c4e18c38 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -19,11 +19,11 @@
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
- android:icon="@mipmap/ic_launcher"
- android:banner="@mipmap/ic_launcher_foreground"
android:logo="@mipmap/ic_launcher"
- android:label="@string/app_name"
+ android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
+ android:banner="@mipmap/ic_banner"
+ android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.ByeDPI"
tools:targetApi="34">
diff --git a/app/src/main/assets/proxytest_cmds.txt b/app/src/main/assets/proxytest_cmds.txt
new file mode 100644
index 00000000..21228c35
--- /dev/null
+++ b/app/src/main/assets/proxytest_cmds.txt
@@ -0,0 +1,42 @@
+--fake -1 --ttl 10
+-d 2 --auto=t -f 3
+-f 1 -n ya.ru -s 3+h
+--disorder 1 --fake 7
+--split 2 --disorder 7
+-o 2 --auto=t,r,a,s -d 2
+-s1 -O3 -q1+s -s25+s -t8
+-s1 -O3 -q1+s -s29+s -t8
+--disoob 2 --tlsrec 3+sni
+-q1+s -s25+s -o5+s -f-1 -S
+-q1+s -s29+s -o5+s -f-1 -S
+-q1+s -s25+s -o5+s -f-1 -S -As
+-q1+s -s29+s -o5+s -f-1 -S -As
+-s1 -q1 -Y -At -f-1 -r1+s -As
+--disoob 2+sni --fake 517 --ttl 5
+-n vk.com -q 1+s -O 1 -s 25+s -t 5
+-n vk.com -q 1+s -O 1 -s 29+s -t 5
+-s0 -o1 -Ar -o1 -At -f-1 -r1+s -As
+-s1 -o1 -Ar -o1 -At -f-1 -r1+s -As
+-s 2 -r 1+s -r 1+h -o 2 -f -1 -t 4
+-s1 -q1 -a2 -Art -f-1 -r1+s -a3 -Asn
+-s1 -d1 -o1 -Ar -o3 -At -f-1 -r1+s -As
+-s1 -q1 -Y -a2 -Art -f-1 -r1+s -a3 -Asn
+--split 2 --disorder 3 --fake -1 --ttl 5
+-s 2 -M h,d -A torst -T 3 -f -1 -r 3+s -S
+-n www.google.com -d 1+s -O 1 -s 25+s -t 5
+-n www.google.com -q 1+s -O 1 -s 29+s -t 5
+-n www.google.com -q 2+s -O 1 -s 25+s -t 5
+-n www.google.com -q 2+s -O 1 -s 29+s -t 5
+--split 2 --disoob 3+sni --fake 517 --ttl 5
+--split 1 --disorder 3+sni --fake -1 --ttl 5
+--split 2 --disorder 3+sni --fake -1 --ttl 5
+-s0 -o1 -d1 -r1+s -Ar -o1 -At -f-1 -r1+s -As
+--disoob 3+sni --split -1+host --tlsrec 1+sni
+--split 2 --fake 0+e --ttl 5 --tls-sni=www.google.com
+-s1 -q1 -Y -Ar -s5 -o1+s -At -f-1 -r1+s -As -s1 -o1+s -s-1 -An
+--split 1 --disorder 3+s --mod-http=h,d --auto=torst --tlsrec 1+s
+-s1 -q1 -Y -Ar -s5 -o25000+s -At -f-1 -r1+s -As -s1 -o1+s -s-1 -An -b+500
+--split 1 --disorder 3+s --mod-http=h,d --auto=torst --tlsrec 1+s --tlsrec 3+sni
+-s1 -o1 -Atr -f16 -l':\x16\x03\x01\x02\x87\x01\x00\x02\x83\x03\x03\x5f\x15\x63\xcb\x06' -As
+-s1 -o1 -Ar -o1 -At -f32 -r1+s -l':\x16\x03\x01\x02\x87\x01\x00\x02\x83\x03\x03\x5f\x15\x63\xcb\x06\xea\x1c\xdd\x40\x76\xf5\x8c\x44\x50\x6e\x01\xf3\xa3\x83\xac\xc2' -As
+--proto=udp --pf=443 --fake-data=':\xC2\x00\x00\x00\x01\x14\x2E\xE3\xE3\x5F\x6B\xBB\x23\xA8\xE6\x5D\xA9\x78\x21\xCF\xC2\x72\x4C\x8F\xC4\x5E\x14\x00\x00\x00\x00\xC5\x00\x00\x00\x00\x4C\x00\xA7\x00\x00\x00\x00\x00\x00\x44\x00\x00\x80\x00\x00\x00\x0D\xFC\xFA\x1D\xCD\x73\xBA\x2A\x90\x93\xB3\xEE\xF7\x43\xC5\x85\xDA\xFF\x45\x3C\x00\x00\x00\x00\x00\x00\x7C\x00\x9B\x00\xF6\x00\x00\xDD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x59\xA8\xE4\x00\x00\x00\x00\x00\x00\x00\x00\x7B\x00\x0F\x00\x00\x00\x48\x4E\x00\x00\x00\x06\xF3\x00\x00\x00\x00\xD9\x5A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' --udp-fake=10 --auto=none -s1 -o1
\ No newline at end of file
diff --git a/app/src/main/assets/proxytest_sites.txt b/app/src/main/assets/proxytest_sites.txt
new file mode 100644
index 00000000..29fe1da3
--- /dev/null
+++ b/app/src/main/assets/proxytest_sites.txt
@@ -0,0 +1,25 @@
+www.youtube.com
+manifest.googlevideo.com
+i.ytimg.com
+yt3.ggpht.com
+yt4.ggpht.com
+signaler-pa.youtube.com
+jnn-pa.googleapis.com
+rr1---sn-4axm-n8vs.googlevideo.com
+rr1---sn-gvnuxaxjvh-o8ge.googlevideo.com
+rr1---sn-ug5onuxaxjvh-p3ul.googlevideo.com
+rr1---sn-ug5onuxaxjvh-n8v6.googlevideo.com
+rr4---sn-q4flrnsl.googlevideo.com
+rr10---sn-gvnuxaxjvh-304z.googlevideo.com
+rr14---sn-n8v7kn7r.googlevideo.com
+rr16---sn-axq7sn76.googlevideo.com
+rr1---sn-8ph2xajvh-5xge.googlevideo.com
+rr1---sn-gvnuxaxjvh-5gie.googlevideo.com
+rr12---sn-gvnuxaxjvh-bvwz.googlevideo.com
+rr5---sn-n8v7knez.googlevideo.com
+rr1---sn-u5uuxaxjvhg0-ocje.googlevideo.com
+rr2---sn-q4fl6ndl.googlevideo.com
+rr5---sn-gvnuxaxjvh-n8vk.googlevideo.com
+rr4---sn-jvhnu5g-c35d.googlevideo.com
+rr1---sn-q4fl6n6y.googlevideo.com
+rr2---sn-hgn7ynek.googlevideo.com
\ No newline at end of file
diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png
deleted file mode 100644
index b815cc69..00000000
Binary files a/app/src/main/ic_launcher-playstore.png and /dev/null differ
diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/MainActivity.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/MainActivity.kt
index 1db2f63e..b2040223 100644
--- a/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/MainActivity.kt
+++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/MainActivity.kt
@@ -16,7 +16,9 @@ import android.view.MenuItem
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.ContextCompat
+import androidx.core.os.LocaleListCompat
import androidx.lifecycle.lifecycleScope
import io.github.dovecoteescapee.byedpi.R
import io.github.dovecoteescapee.byedpi.data.*
@@ -147,8 +149,10 @@ class MainActivity : AppCompatActivity() {
}
}
- val theme = getPreferences()
- .getString("app_theme", null)
+ val lang = getPreferences().getString("language", "system")
+ MainSettingsFragment.setLang(lang ?: "system")
+
+ val theme = getPreferences().getString("app_theme", null)
MainSettingsFragment.setTheme(theme ?: "system")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
@@ -160,9 +164,7 @@ class MainActivity : AppCompatActivity() {
requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 1)
}
- val autoConnect = getPreferences().getBoolean("auto_connect", false)
-
- if(autoConnect) {
+ if (getPreferences().getBoolean("auto_connect", false) && appStatus.first != AppStatus.Running) {
this.start()
}
}
diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/SettingsActivity.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/SettingsActivity.kt
index 880cc7dc..2231f6f6 100644
--- a/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/SettingsActivity.kt
+++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/SettingsActivity.kt
@@ -34,7 +34,13 @@ class SettingsActivity : AppCompatActivity() {
}
R.id.action_reset_settings -> {
- getPreferences().edit().clear().apply()
+ val prefs = getPreferences()
+ val currentLanguage = prefs.getString("language", "system")
+ val editor = prefs.edit()
+
+ editor.clear()
+ editor.putString("language", currentLanguage)
+ editor.apply()
supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
supportFragmentManager
diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/AppSelectionFragment.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/AppSelectionFragment.kt
index 483177d7..cb22c85e 100644
--- a/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/AppSelectionFragment.kt
+++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/AppSelectionFragment.kt
@@ -66,6 +66,7 @@ class AppSelectionFragment : Fragment() {
}
recyclerView.adapter = adapter
progressBar.visibility = View.GONE
+ searchView.visibility = View.VISIBLE
}
}
diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/MainSettingsFragment.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/MainSettingsFragment.kt
index bbbc7d51..05c07521 100644
--- a/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/MainSettingsFragment.kt
+++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/MainSettingsFragment.kt
@@ -6,6 +6,7 @@ import android.os.Bundle
import android.provider.Settings
import android.util.Log
import androidx.appcompat.app.AppCompatDelegate
+import androidx.core.os.LocaleListCompat
import androidx.preference.*
import io.github.dovecoteescapee.byedpi.BuildConfig
import io.github.dovecoteescapee.byedpi.R
@@ -18,6 +19,21 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
companion object {
private val TAG: String = MainSettingsFragment::class.java.simpleName
+ fun setLang(lang: String) {
+ val appLocale = localeByName(lang) ?: throw IllegalStateException("Invalid value for language: $lang")
+ AppCompatDelegate.setApplicationLocales(appLocale)
+ }
+
+ private fun localeByName(lang: String): LocaleListCompat? = when (lang) {
+ "system" -> LocaleListCompat.getEmptyLocaleList()
+ "ru" -> LocaleListCompat.forLanguageTags("ru")
+ "en" -> LocaleListCompat.forLanguageTags("en")
+ else -> {
+ Log.w(TAG, "Invalid value for language: $lang")
+ null
+ }
+ }
+
fun setTheme(name: String) =
themeByName(name)?.let {
AppCompatDelegate.setDefaultNightMode(it)
@@ -46,15 +62,21 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
it.isBlank() || checkNotLocalIp(it)
}
+ findPreferenceNotNull("language")
+ .setOnPreferenceChangeListener { _, newValue ->
+ setLang(newValue as String)
+ true
+ }
+
findPreferenceNotNull("app_theme")
.setOnPreferenceChangeListener { _, newValue ->
setTheme(newValue as String)
true
}
- val switchCommandLineSettings = findPreferenceNotNull(
- "byedpi_enable_cmd_settings"
- )
+ val accessibilityStatusPref = findPreferenceNotNull("accessibility_service_status")
+ val switchCommandLineSettings = findPreferenceNotNull("byedpi_enable_cmd_settings")
+
val uiSettings = findPreferenceNotNull("byedpi_ui_settings")
val cmdSettings = findPreferenceNotNull("byedpi_cmd_settings")
@@ -70,23 +92,13 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
true
}
- findPreferenceNotNull("version").summary = BuildConfig.VERSION_NAME
-
- val accessibilityStatusPref = findPreference("accessibility_service_status")
- accessibilityStatusPref?.setOnPreferenceClickListener {
+ accessibilityStatusPref.setOnPreferenceClickListener {
val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
startActivity(intent)
true
}
- val selectedApps = findPreference("selected_apps")
- selectedApps?.setOnPreferenceClickListener {
- parentFragmentManager.beginTransaction()
- .replace(R.id.settings, AppSelectionFragment())
- .addToBackStack(null)
- .commit()
- true
- }
+ findPreferenceNotNull("version").summary = BuildConfig.VERSION_NAME
updateAccessibilityStatus(accessibilityStatusPref)
updatePreferences()
diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/services/ByeDpiProxyService.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/services/ByeDpiProxyService.kt
index d3de4093..4b565a32 100644
--- a/app/src/main/java/io/github/dovecoteescapee/byedpi/services/ByeDpiProxyService.kt
+++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/services/ByeDpiProxyService.kt
@@ -30,6 +30,10 @@ class ByeDpiProxyService : LifecycleService() {
private const val NOTIFICATION_CHANNEL_ID: String = "ByeDPI Proxy"
private var status: ServiceStatus = ServiceStatus.Disconnected
+
+ fun getStatus(): ServiceStatus {
+ return status
+ }
}
override fun onCreate() {
@@ -73,6 +77,7 @@ class ByeDpiProxyService : LifecycleService() {
mutex.withLock {
startProxy()
}
+
updateStatus(ServiceStatus.Connected)
startForeground()
} catch (e: Exception) {
@@ -96,11 +101,12 @@ class ByeDpiProxyService : LifecycleService() {
}
private suspend fun stop() {
- Log.i(TAG, "Stopping VPN")
+ Log.i(TAG, "Stopping")
mutex.withLock {
stopProxy()
}
+
updateStatus(ServiceStatus.Disconnected)
stopSelf()
}
diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/utility/GoogleVideoUtils.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/utility/GoogleVideoUtils.kt
new file mode 100644
index 00000000..13c1ab24
--- /dev/null
+++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/utility/GoogleVideoUtils.kt
@@ -0,0 +1,116 @@
+package io.github.dovecoteescapee.byedpi.utility
+
+import android.util.Log
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import java.io.BufferedReader
+import java.io.InputStreamReader
+import java.net.HttpURLConnection
+import java.net.URL
+
+class GoogleVideoUtils {
+
+ companion object {
+ private val lettersListA = listOf(
+ 'u', 'z', 'p', 'k', 'f', 'a', '5', '0', 'v', 'q', 'l', 'g',
+ 'b', '6', '1', 'w', 'r', 'm', 'h', 'c', '7', '2', 'x', 's',
+ 'n', 'i', 'd', '8', '3', 'y', 't', 'o', 'j', 'e', '9', '4', '-'
+ )
+ private val lettersListB = listOf(
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '-'
+ )
+ private val lettersMap = lettersListA.zip(lettersListB).toMap()
+ }
+
+ suspend fun generateGoogleVideoDomain(): String? {
+ val clusterCodename = getClusterCodename()
+ if (clusterCodename == null) {
+ Log.e("AutoGCS", "Failed to obtain cluster codename")
+ return null
+ }
+ Log.i("AutoGCS", "Cluster codename: $clusterCodename")
+ val clusterName = convertClusterCodename(clusterCodename)
+ Log.i("AutoGCS", "Cluster name: $clusterName")
+ val autoGCS = buildAutoGCS(clusterName)
+ Log.i("AutoGCS", "Generated domain: $autoGCS")
+ return autoGCS
+ }
+
+ private suspend fun getClusterCodename(): String? {
+ val urls = listOf(
+ "https://redirector.gvt1.com/report_mapping?di=no",
+ "https://redirector.googlevideo.com/report_mapping?di=no"
+ )
+ for (url in urls) {
+ try {
+ val responseBody = withContext(Dispatchers.IO) { httpGet(url) }
+ if (responseBody != null) {
+ val clusterCodename = extractClusterCodenameFromBody(responseBody)
+ if (clusterCodename != null) {
+ return clusterCodename
+ }
+ }
+ } catch (e: Exception) {
+ Log.e("ClusterCodename", "Error fetching cluster codename from $url", e)
+ }
+ }
+ return null
+ }
+
+ private fun extractClusterCodenameFromBody(body: String): String? {
+ val regex = Regex("""=>\s*(\S+)\s*(?:\(|:)""")
+ val matchResult = regex.find(body)
+ val codename = matchResult?.groupValues?.get(1)
+ if (codename != null) {
+ return codename.trimEnd(':', ' ')
+ }
+ return null
+ }
+
+ private fun convertClusterCodename(clusterCodename: String): String {
+ val clusterNameBuilder = StringBuilder()
+ for (char in clusterCodename) {
+ val mappedChar = lettersMap[char]
+ if (mappedChar != null) {
+ clusterNameBuilder.append(mappedChar)
+ } else {
+ Log.w("ClusterCodename", "Character '$char' not found in mapping")
+ }
+ }
+ return clusterNameBuilder.toString()
+ }
+
+ private fun buildAutoGCS(clusterName: String): String {
+ return "rr1---sn-$clusterName.googlevideo.com"
+ }
+
+ private fun httpGet(urlStr: String): String? {
+ var connection: HttpURLConnection? = null
+ return try {
+ val url = URL(urlStr)
+ connection = url.openConnection() as HttpURLConnection
+ connection.requestMethod = "GET"
+ connection.connectTimeout = 2000
+ connection.readTimeout = 2000
+
+ val responseCode = connection.responseCode
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ val inputStream = connection.inputStream
+ val reader = BufferedReader(InputStreamReader(inputStream))
+ val response = reader.readText()
+ reader.close()
+ response
+ } else {
+ Log.e("HTTPGet", "Non-OK response code: $responseCode")
+ null
+ }
+ } catch (e: Exception) {
+ Log.e("HTTPGet", "Exception during HTTP GET", e)
+ null
+ } finally {
+ connection?.disconnect()
+ }
+ }
+}
diff --git a/app/src/main/res/drawable/ic_telegram.xml b/app/src/main/res/drawable/ic_telegram.xml
new file mode 100644
index 00000000..793bf350
--- /dev/null
+++ b/app/src/main/res/drawable/ic_telegram.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/app_selection.xml b/app/src/main/res/layout/app_selection.xml
index 02ffc35f..3a2eec31 100644
--- a/app/src/main/res/layout/app_selection.xml
+++ b/app/src/main/res/layout/app_selection.xml
@@ -8,6 +8,7 @@
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:visibility="gone"
android:queryHint="@string/search_apps" />
-
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
index 036d09bc..c97e05e3 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp
index 9a593d9d..b304955a 100644
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.webp and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp
index 776d4cf6..a19df84f 100644
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp and b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
index b7c638f8..ccde8b2b 100644
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp
index 974e392b..f41f9e60 100644
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.webp and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
index 06858dcc..444b25ca 100644
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp and b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
index e2f5074f..9b6a465e 100644
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_banner.png b/app/src/main/res/mipmap-xhdpi/ic_banner.png
new file mode 100644
index 00000000..09bacafb
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_banner.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
index 6a2a36be..7dda74d0 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp
index 7ed7293b..f573da7d 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp and b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
index 4a193e27..33c41a0f 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
index b932dd20..dd7e691f 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp
index f4158e02..58e23839 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
index d9eef0f5..51be606f 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
index 9e0b76bd..d0a7bf02 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
index 13da1544..e6ddcf4a 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
index a9ab65cf..7dbfa7bb 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/values-en/arrays.xml b/app/src/main/res/values-en/arrays.xml
new file mode 100644
index 00000000..920a5dd2
--- /dev/null
+++ b/app/src/main/res/values-en/arrays.xml
@@ -0,0 +1,26 @@
+
+
+
+ - Auto
+ - Русский
+ - English
+
+
+
+ - System
+ - Light
+ - Dark
+
+
+
+ - Disable
+ - Blacklist
+ - Whitelist
+
+
+
+ - Disable
+ - Blacklist
+ - Whitelist
+
+
diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml
new file mode 100644
index 00000000..e7a7ad62
--- /dev/null
+++ b/app/src/main/res/values-en/strings.xml
@@ -0,0 +1,119 @@
+
+ https://github.com/hufrea/byedpi/blob/main/README.md
+ ByeByeDPI
+ Connect
+ Disconnect
+ Connected (VPN)
+ Disconnected (VPN)
+ Connected (Proxy)
+ Disconnected (Proxy)
+ Start
+ Stop
+ Settings
+ No permission to activate VPN
+ Disconnect first to access settings
+ Settings
+ Save logs
+ Reset
+ Failed to collect logs
+ %1$s:%2$s
+ Language
+ Theme
+ Mode
+ DNS
+ Listening address
+ Port
+ Max connections
+ Buffer size
+ Default TTL
+ No domain
+ Desync method
+ Split position
+ Split at host
+ TTL of fake packets
+ Host mixed case
+ Domain mixed case
+ Remove spaces from host
+ Split TLS record
+ TLS record split position
+ Split TLS record at SNI
+ ByeByeDPI
+ Source code
+ What does it all mean?
+ Failed to start %1$s
+ VPN
+ Proxy
+ ByeByeDPI
+ VPN is running
+ Proxy is running
+ General
+ ByeDPI
+ About
+ Command line editor
+ UI editor
+ Use command line settings
+ HTTP desync
+ HTTPS desync
+ UDP desync
+ OOB Data
+ SNI of fake packet
+ Proxy
+ Desync
+ Command line arguments
+ Hosts
+ Host blacklist
+ Host whitelist
+ TCP Fast Open
+ Number of fake UDP
+ IPv6
+ Fake packet offset
+ Drop SACK
+ UDP
+ HTTP
+ HTTPS
+ Protocols
+ Uncheck all to desync all traffic
+ Automation
+ Autostart service on device startup
+ Automatically hide application after autostart
+ Automatically connect when the application starts
+ Autostart status
+ Service active, autostart works
+ Enable accessibility service for autostart
+ Apps filter
+ Select apps
+ Search apps
+ Command history
+ Select action
+ Apply
+ Copy
+ Pin
+ Unpin
+ Pinned
+ Delete
+ Telegram group
+ Proxy test
+ Automated testing of prepared command sets
+ Start testing
+ Stop testing
+
+ This section allows you to test the application using a set of pre-prepared commands.
+ \nDuring testing, the system checks the availability of various websites via the proxy, and you can observe the process in real time.
+ \n
+ \nPlease note that this testing functionality is under development, and the command set is currently limited.
+ \nTest results may be helpful for a preliminary assessment of the proxy, but successful completion does not guarantee flawless performance in real-world conditions.
+
+ Checking %1$d/%2$d
+ Proxy error. Test stopped
+ Commands with more than 50% success probability
+ Test completed
+ Tap on a command to copy or apply it
+ Add the nearest GoogleVideo for testing
+ Include response information from hosts in the log
+ Display all commands in the test as clickable
+ Use custom domain list
+ Domain list
+ Use custom command lists
+ Command list
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index 4abc2278..e68bc8f4 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -1,9 +1,20 @@
+
+ - Автоматически
+ - Русский
+ - English
+
+
+ - system
+ - ru
+ - en
+
+
- - System
- - Light
- - Dark
+ - Системная
+ - Светлая
+ - Темная
- system
@@ -38,9 +49,9 @@
- - Disable
- - Blacklist
- - Whitelist
+ - Нет
+ - Черный список
+ - Белый список
- disable
@@ -53,7 +64,6 @@
- Черный список
- Белый список
-
- disable
- blacklist
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index c8524cd9..bcdcb40b 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -2,4 +2,5 @@
#FF000000
#FFFFFFFF
+ #0B4680
\ No newline at end of file
diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml
deleted file mode 100644
index ed74d8c9..00000000
--- a/app/src/main/res/values/ic_launcher_background.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
- #061A23
-
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 25b99d41..8000e332 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -17,6 +17,7 @@
Сбросить
Не удалось собрать логи
%1$s:%2$s
+ Язык
Тема
Режим
DNS
@@ -90,4 +91,28 @@
Открепить
Закреплено
Удалить
+ Группа Telegram
+ Подбор команд
+ Автоматическое тестирование работы подготовленных наборов команд
+ Начать проверку
+ Остановить проверку
+
+ Данный раздел предоставляет возможность протестировать работу приложения с помощью набора заранее подготовленных команд.
+ \nВ процессе тестирования система проверяет доступность различных сайтов через прокси, и вы можете наблюдать за ходом выполнения в режиме реального времени.
+ \n
+ \nОбратите внимание, что функционал данного тестирования находится на этапе разработки, и набор команд пока что ограничен.
+ \nРезультаты тестов могут быть полезны для предварительной оценки работы прокси, однако их успешное прохождение не гарантирует безупречную работу в реальных условиях.
+
+ Проверка %1$d/%2$d
+ Ошибка прокси. Тест остановлен
+ Команды с вероятностью успеха более 50%
+ Проверка завершена
+ Нажмите на команду, чтобы скопировать ее или применить
+ Добавлять ближайший GoogleVideo к тестированию
+ Расширенный лог с выводом ответа хостов
+ Выводить все команды в тесте кликабельными
+ Использовать свой список доменов
+ Список доменов
+ Использовать свой список команд
+ Список команд
\ No newline at end of file
diff --git a/app/src/main/res/xml/main_settings.xml b/app/src/main/res/xml/main_settings.xml
index 9c993045..d926ab7a 100644
--- a/app/src/main/res/xml/main_settings.xml
+++ b/app/src/main/res/xml/main_settings.xml
@@ -7,6 +7,14 @@
+
+
+ android:title="@string/apps_select"
+ app:fragment="io.github.dovecoteescapee.byedpi.fragments.AppSelectionFragment" />
@@ -88,10 +97,13 @@
android:title="@string/about_category">
+ android:key="telegram_group"
+ android:title="@string/telegram_link"
+ android:icon="@drawable/ic_telegram">
+
+
+
+