Compare commits

..

5 Commits

Author SHA1 Message Date
zaneschepke 0a9773d202 chore: release 5.0.6 2026-06-25 13:10:15 -04:00
zaneschepke 3cb4480a65 fix: android 17 local devices/network permission requirement
closes #1299
2026-06-25 04:41:18 -04:00
zaneschepke a7f3255a76 refactor: remove legacy round icons 2026-06-25 02:32:03 -04:00
zaneschepke 7d7b99f448 fix: quick tile logo for samsung OneUI
#1301
2026-06-25 01:12:40 -04:00
zaneschepke 74e9e462bb fix: app shortcuts crash
closes #1302
2026-06-24 02:11:02 -04:00
19 changed files with 232 additions and 29 deletions
+2 -3
View File
@@ -53,7 +53,6 @@
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.App.Start"
tools:targetApi="tiramisu">
@@ -178,7 +177,7 @@
<service
android:name=".service.tile.TunnelControlTile"
android:exported="true"
android:icon="@drawable/ic_notification"
android:icon="@drawable/ic_qs_logo"
android:label="@string/tunnel_control"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<meta-data
@@ -195,7 +194,7 @@
<service
android:name=".service.tile.AutoTunnelControlTile"
android:exported="true"
android:icon="@drawable/ic_notification"
android:icon="@drawable/ic_qs_logo"
android:label="@string/auto_tunnel"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<meta-data
@@ -1,12 +1,14 @@
package com.zaneschepke.wireguardautotunnel
import ProxySettingsScreen
import android.Manifest
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.net.VpnService
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.view.WindowManager
import androidx.activity.SystemBarStyle
import androidx.activity.compose.rememberLauncherForActivityResult
@@ -50,6 +52,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -61,6 +64,7 @@ import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import androidx.core.app.ActivityCompat
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
@@ -83,6 +87,7 @@ import com.zaneschepke.wireguardautotunnel.ui.LocalIsAndroidTV
import com.zaneschepke.wireguardautotunnel.ui.LocalNavController
import com.zaneschepke.wireguardautotunnel.ui.common.banner.AppAlertBanner
import com.zaneschepke.wireguardautotunnel.ui.common.dialog.InfoDialog
import com.zaneschepke.wireguardautotunnel.ui.common.dialog.LocalNetworkPermissionDialog
import com.zaneschepke.wireguardautotunnel.ui.common.dialog.VpnDeniedDialog
import com.zaneschepke.wireguardautotunnel.ui.navigation.Route
import com.zaneschepke.wireguardautotunnel.ui.navigation.SecureRoute
@@ -132,6 +137,7 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.installApk
import com.zaneschepke.wireguardautotunnel.util.extensions.isRunningOnTv
import com.zaneschepke.wireguardautotunnel.util.extensions.openWebUrl
import com.zaneschepke.wireguardautotunnel.util.extensions.restartApp
import com.zaneschepke.wireguardautotunnel.util.permission.LocalNetworkPermissionHelper
import com.zaneschepke.wireguardautotunnel.viewmodel.ConfigEditViewModel
import com.zaneschepke.wireguardautotunnel.viewmodel.SharedAppViewModel
import com.zaneschepke.wireguardautotunnel.viewmodel.SplitTunnelViewModel
@@ -202,6 +208,68 @@ class MainActivity : AppCompatActivity() {
var requestingTunnelMode by remember {
mutableStateOf<Pair<TunnelMode?, TunnelConfig?>>(Pair(null, null))
}
var showLocalNetworkRationale by remember { mutableStateOf(false) }
var hasPromptedLocalNetwork by rememberSaveable { mutableStateOf(false) }
val localNetworkPermissionLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission()
) { isGranted ->
if (!isGranted) {
val canAskAgain =
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.ACCESS_LOCAL_NETWORK,
)
if (!canAskAgain) {
val intent =
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts("package", packageName, null)
}
startActivity(intent)
} else {
toaster.show(
message =
context.getString(R.string.local_network_permission_denied),
type = ToastType.Warning,
duration = 6000.milliseconds,
)
}
}
}
LaunchedEffect(uiState.isAppLoaded) {
if (
uiState.isAppLoaded &&
!hasPromptedLocalNetwork &&
LocalNetworkPermissionHelper.shouldRequestPermission() &&
!LocalNetworkPermissionHelper.isPermissionGranted(context)
) {
hasPromptedLocalNetwork = true
showLocalNetworkRationale = true
}
}
if (showLocalNetworkRationale) {
LocalNetworkPermissionDialog(
onDismiss = {
showLocalNetworkRationale = false
toaster.show(
message = context.getString(R.string.local_network_permission_denied),
type = ToastType.Warning,
duration = 6000.milliseconds,
)
},
onContinue = {
showLocalNetworkRationale = false
localNetworkPermissionLauncher.launch(
Manifest.permission.ACCESS_LOCAL_NETWORK
)
},
)
}
val startingStack = buildList {
add(Route.Tunnels)
@@ -117,7 +117,7 @@ class TunnelCoordinator(
// enforce single tunnel, for now
if (backendStatus.value.activeTunnels.isNotEmpty()) {
stopActiveTunnelsInternal()
stopActiveTunnelsInternal(source)
}
startTunnelInternal(config, source)
@@ -131,7 +131,13 @@ class TunnelCoordinator(
stopTunnelInternal(id, source)
}
suspend fun stopActiveTunnels() = tunnelMutex.withLock { stopActiveTunnelsInternal() }
suspend fun stopActiveTunnels(source: TunnelActionSource = TunnelActionSource.USER) =
tunnelMutex.withLock {
if (source == TunnelActionSource.USER) {
_userOverrideFlow.tryEmit(Unit)
}
stopActiveTunnelsInternal(source)
}
private suspend fun startTunnelInternal(
tunnelConfig: TunnelConfig,
@@ -218,7 +224,7 @@ class TunnelCoordinator(
_actions.emit(TunnelActionEvent.Stopped(tunnelId = id, source = source))
}
stopActiveTunnelsInternal()
stopActiveTunnelsInternal(source)
return@withLock
}
@@ -243,7 +249,15 @@ class TunnelCoordinator(
.onFailure { _errors.emit(TunnelErrorEvent.from(it, id)) }
}
private suspend fun stopActiveTunnelsInternal() {
private suspend fun stopActiveTunnelsInternal(
source: TunnelActionSource = TunnelActionSource.USER
) {
val active = tunnelProvider.backendStatus.value.activeTunnels
active.keys.forEach { id ->
_actions.emit(TunnelActionEvent.Stopped(tunnelId = id, source = source))
}
tunnelProvider.stopActiveTunnels()
}
}
@@ -19,9 +19,8 @@ class ShortcutsActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
applicationScope.launch {
shortcutCoordinator.handle(intent)
finish()
}
finish()
applicationScope.launch { shortcutCoordinator.handle(intent) }
}
}
@@ -4,14 +4,11 @@ import com.zaneschepke.tunnel.Tunnel
import com.zaneschepke.tunnel.backend.Backend
import com.zaneschepke.tunnel.model.BackendMode
import com.zaneschepke.tunnel.state.BackendStatus
import com.zaneschepke.wireguardautotunnel.domain.events.BackendCoreException
import com.zaneschepke.wireguardautotunnel.domain.events.BackendMessage
import com.zaneschepke.wireguardautotunnel.domain.model.LockdownSettings
import kotlin.concurrent.atomics.ExperimentalAtomicApi
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
@@ -52,10 +49,4 @@ class TunnelBackendProvider(
override suspend fun disableLockDown(): Result<Unit> {
return backend.disableKillSwitch()
}
@OptIn(ExperimentalCoroutinesApi::class)
private val localErrorEvents = MutableSharedFlow<Pair<String?, BackendCoreException>>()
@OptIn(ExperimentalCoroutinesApi::class)
private val localMessageEvents = MutableSharedFlow<Pair<String?, BackendMessage>>()
}
@@ -0,0 +1,75 @@
package com.zaneschepke.wireguardautotunnel.ui.common.dialog
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.zaneschepke.wireguardautotunnel.R
@Composable
fun LocalNetworkPermissionDialog(onDismiss: () -> Unit, onContinue: () -> Unit) {
AlertDialog(
onDismissRequest = onDismiss,
title = { Text(text = stringResource(R.string.local_network_permission_title)) },
text = {
Column {
Text(
text = stringResource(R.string.local_network_permission_intro),
style = MaterialTheme.typography.bodyMedium,
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = stringResource(R.string.local_network_permission_issues_intro),
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium,
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = stringResource(R.string.local_network_permission_feature_tunnels),
style = MaterialTheme.typography.bodyMedium,
)
Text(
text = stringResource(R.string.local_network_permission_feature_autotunnel),
style = MaterialTheme.typography.bodyMedium,
)
Text(
text = stringResource(R.string.local_network_permission_feature_proxy),
style = MaterialTheme.typography.bodyMedium,
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = stringResource(R.string.local_network_permission_nearby_devices),
style = MaterialTheme.typography.bodyMedium,
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = stringResource(R.string.local_network_permission_recommendation),
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium,
)
}
},
confirmButton = {
TextButton(onClick = onContinue) { Text(text = stringResource(R.string._continue)) }
},
dismissButton = {
TextButton(onClick = onDismiss) { Text(text = stringResource(R.string.not_now)) }
},
)
}
@@ -0,0 +1,23 @@
package com.zaneschepke.wireguardautotunnel.util.permission
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.content.ContextCompat
object LocalNetworkPermissionHelper {
fun shouldRequestPermission(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.CINNAMON_BUN
}
fun isPermissionGranted(context: Context): Boolean {
return if (shouldRequestPermission()) {
ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_LOCAL_NETWORK) ==
PackageManager.PERMISSION_GRANTED
} else {
true
}
}
}
+20
View File
@@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<group
android:scaleX="1.18"
android:scaleY="1.18"
android:pivotX="512"
android:pivotY="512"
android:translateX="-45"
android:translateY="-45">
<path
android:pathData="M779.7,207.8C782.5,207.8 785.4,207.8 788.2,207.8C851.8,207.6 851.8,207.6 871.1,225.5C882.4,237.3 887.6,250.9 887.5,267.1C886.9,284.9 879,300.9 872,317C871,319.2 870.1,321.4 869.1,323.7C867.7,327.1 866.2,330.6 864.7,334.1C861,342.7 857.3,351.4 853.7,360.1C847.1,375.7 840.5,391.3 833.8,406.9C831.1,413.1 828.5,419.2 825.8,425.4C822.9,432.3 819.9,439.2 817,446C804.9,474 804.9,474 793.3,502.2C791,507.8 788.5,513.3 785.9,518.7C782,527 778.5,535.5 775,544C772,551 769,557.9 766.1,564.9C765.6,566 765.1,567.2 764.6,568.4C763.5,570.7 762.5,573.1 761.5,575.5C760,579 758.5,582.6 757,586.1C751.8,598.2 746.6,610.4 741.2,622.4C737.3,631.3 733.4,640.3 729.5,649.2C725.8,657.9 722,666.6 718,675.2C715.7,680.4 713.5,685.6 711.4,690.8C708.5,697.8 705.4,704.7 702.1,711.6C700.8,714.5 699.4,717.4 698,720.4C685.7,746.7 672.9,772.5 643.9,783.1C639.6,784.4 635.5,784.7 631,785C630.2,785.1 629.5,785.1 628.7,785.2C610.7,785.8 596.7,779.5 583.5,767.8C569.4,754.5 562,735.7 554.3,718.3C552.1,713.5 549.9,708.7 547.5,704.1C543.9,696.9 540.8,689.6 537.6,682.2C534.6,675 531.4,667.8 528.3,660.6C522.3,646.9 516.3,633.3 510.4,619.6C508.5,615.1 506.5,610.6 504.6,606.1C494.1,582.1 494.1,582.1 489.6,571.2C488,567.4 486.4,563.6 484.6,559.8C481.8,553.6 479.2,547.4 476.6,541.1C472.4,531.2 472.4,531.2 468,521.5C461.3,507.3 455.5,492.6 449.5,478.1C444.9,466.9 440.2,455.8 435.3,444.7C431.5,436.1 427.7,427.4 424.1,418.8C423.8,418.1 423.5,417.4 423.2,416.6C420,409.1 416.8,401.6 413.7,394C413.4,393.3 413.2,392.7 412.9,392C411.6,389 410.4,386 409.2,383C406.8,377.1 404.3,371.4 401.6,365.7C397.9,357.9 394.6,349.9 391.3,341.9C390.4,339.6 389.5,337.4 388.6,335.2C388,333.7 387.3,332.2 386.7,330.7C384.7,325.7 382.6,320.7 380.6,315.8C380,314.5 379.5,313.2 378.9,311.9C377.9,309.5 376.9,307.1 375.9,304.7C368.4,286.7 361.9,264.8 369.7,245.7C373.8,237.4 377.9,230 385,224C385.6,223.5 386.2,223 386.8,222.4C397,213.9 412.5,209.7 425.8,210.1C442.3,212.1 455.2,220.4 466,233C471.9,241.6 476.5,250.7 480.9,260.1C481.5,261.3 482.2,262.6 482.8,263.9C487.3,273.5 491.7,283.1 496,292.8C497,294.9 497.9,297.1 498.9,299.2C503.6,309.6 508.1,320.1 512.5,330.6C515.1,336.6 517.7,342.5 520.5,348.4C524.1,356.1 527.4,363.9 530.6,371.8C531.7,374.4 532.8,377 533.9,379.7C534.3,380.6 534.3,380.6 534.7,381.6C536.3,385.3 537.8,388.9 539.5,392.5C541.5,396.7 543.3,401 545.1,405.3C545.4,406 545.6,406.6 545.9,407.3C547,409.9 548.1,412.6 549.2,415.2C552.5,423.2 555.9,431.1 559.6,438.9C561.7,443.4 563.7,447.9 565.5,452.5C567.6,457.7 569.8,462.9 572.3,467.9C575.9,475.7 579.2,483.5 582.5,491.4C585.8,499.2 589.1,507 592.5,514.7C617.2,571.5 617.2,571.5 625.1,591.7C625.8,593.9 625.8,593.9 627,595C627.3,594.3 627.6,593.5 627.9,592.7C632.8,580 637.7,567.3 643.4,554.9C646.9,547.2 650.2,539.5 653.4,531.8C653.7,531.1 654,530.4 654.3,529.7C657.2,522.9 660,516 662.9,509.1C663.3,508 663.8,506.9 664.2,505.8C665,503.9 665.9,501.9 666.7,499.9C668.9,494.5 671.3,489.1 673.8,483.7C675.7,479.4 677.6,475 679.5,470.7C679.9,469.7 680.3,468.7 680.8,467.7C682.2,464.5 683.6,461.2 685,458C686,455.6 687.1,453.3 688.1,450.9C689.7,447.1 691.3,443.4 693,439.6C695.8,433.2 698.5,426.8 701.3,420.3C714.6,389.7 714.6,389.7 727.2,358.9C729.7,352.7 732.4,346.8 735.3,340.8C736.9,337.4 738.2,333.8 739.6,330.3C740.1,329.1 740.5,327.9 741,326.7C741.3,325.8 741.6,324.9 742,324C741.2,324 741.2,324 740.3,324C726.5,324.1 712.7,324.1 698.9,324.1C692.2,324.1 685.5,324.1 678.9,324.2C672.4,324.2 665.9,324.2 659.5,324.2C657,324.2 654.6,324.2 652.1,324.2C640.5,324.3 629,324.2 617.4,323.1C616.6,323.1 615.8,323 614.9,322.9C597,321 581.4,314.3 569,301C566.5,297.8 564.7,294.6 563,291C562.5,290 562,289 561.5,288C556.5,276.1 555.8,261.8 559.6,249.4C562,243.5 565.3,238.2 569,233C569.7,232 569.7,232 570.4,231C581.2,217.3 599.1,212.3 615.8,210.2C637.1,208 659,208.7 680.4,208.5C683.5,208.4 686.5,208.4 689.5,208.4C719.6,208.1 749.6,207.9 779.7,207.8Z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M263.3,223.5C276.3,234.5 282.6,248.9 289.6,264C290.9,266.8 292.2,269.5 293.5,272.2C303,291.5 311.4,311.3 320,331C320.3,331.7 320.6,332.5 321,333.2C323.4,338.9 325.9,344.5 328.3,350.2C332.2,359.1 336.1,368.1 340,377C346.2,391.1 352.3,405.2 358.4,419.3C360.8,424.9 363.3,430.5 365.7,436.1C366.5,438 367.3,439.9 368.1,441.7C370.6,447.4 373,453 375.5,458.7C382.5,474.8 389.4,491 396.4,507.2C398.1,511.3 399.9,515.5 401.7,519.6C408.7,536 415.8,552.5 422.7,568.9C424,572 425.3,575.2 426.7,578.3C433,593.2 439.2,608.1 445.5,623C447.5,627.7 449.4,632.4 451.4,637C453.8,642.9 456.3,648.7 458.7,654.6C459.9,657.5 461.2,660.4 462.4,663.3C467.1,674.6 471.8,685.9 476.4,697.3C477.1,698.8 477.1,698.8 477.7,700.4C484.3,716.8 488.7,735.5 482,752.6C479.3,758.3 475.9,763.2 472,768C471.6,768.6 471.1,769.2 470.7,769.8C464.5,777.8 455.6,782.4 446,785C445,785.3 444,785.7 443,786C431.6,787 420.6,786.5 410,782C408.7,781.5 408.7,781.5 407.4,781C380.7,769.4 369.2,736.1 358.2,711.6C356.7,708.3 355.1,705 353.6,701.7C340.8,674.4 329,646.7 317.5,618.9C316,615.2 314.3,611.5 312.7,607.9C309.7,601.4 306.9,594.9 304.1,588.4C303.9,587.8 303.6,587.2 303.3,586.5C299.7,578 296.1,569.4 292.6,560.8C291,556.9 289.2,553 287.4,549.1C284.7,543 282,536.9 279.3,530.8C278.7,529.3 278.1,527.9 277.4,526.5C276.2,523.6 274.9,520.8 273.7,517.9C272.3,514.6 270.8,511.3 269.4,508C264.2,496.1 259.1,484.2 254.1,472.3C250.4,463.6 246.7,455 242.9,446.3C242.5,445.4 242.2,444.5 241.8,443.6C240,439.6 238.3,435.6 236.5,431.6C234.9,427.8 233.2,424.1 231.6,420.4C231.4,419.7 231.1,419.1 230.8,418.5C226.1,407.6 221.5,396.7 217,385.8C214.5,379.6 211.9,373.5 209.2,367.5C207.4,363.7 205.8,359.9 204.1,356.1C203.8,355.2 203.4,354.4 203,353.5C199.1,344.2 195.2,334.9 191.3,325.6C191,324.9 190.7,324.1 190.3,323.3C187.1,315.5 183.8,307.6 180.7,299.8C180.2,298.6 179.7,297.4 179.2,296.2C177.6,291.9 176.2,287.5 175,283C174.8,282.4 174.7,281.8 174.5,281.2C171.2,266.5 173.7,250.9 181.4,238.2C191.3,223.5 203.1,215.7 220.6,212.3C236.3,210.9 250.7,213.5 263.3,223.5Z"
android:fillColor="#FFFFFF"/>
</group>
</vector>
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

+17
View File
@@ -537,4 +537,21 @@
<string name="restore_failed_wrong_password">Restore failed. Wrong password</string>
<string name="restore_failed_invalid_file">Restore failed. Select a valid backup file (.sqlite3 or .sqlite3.aes)</string>
<string name="error_invalid_config_url">This link returned an invalid config file. Make sure you are using a direct download link</string>
<string name="local_network_permission_title">Local Network Access Needed</string>
<string name="local_network_permission_intro">WG Tunnel needs access to your local network for several features to work properly.</string>
<string name="local_network_permission_issues_intro">Without this permission, you may experience issues with:</string>
<string name="local_network_permission_feature_tunnels">- Connecting to certain tunnels</string>
<string name="local_network_permission_feature_autotunnel">- Auto-tunneling and split tunneling features</string>
<string name="local_network_permission_feature_proxy">- Local proxy and bypass functionality</string>
<string name="local_network_permission_recommendation">Granting this permission is strongly recommended.</string>
<string name="local_network_permission_nearby_devices">Note: Android labels this permission as “nearby devices”.</string>
<string name="not_now">Not now</string>
<string name="local_network_permission_denied">Local network access denied. Some features may not work properly</string>
</resources>
-1
View File
@@ -1,5 +1,4 @@
import com.ncorti.ktfmt.gradle.tasks.KtfmtFormatTask
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.android.application) apply false
+2 -2
View File
@@ -1,6 +1,6 @@
object Constants {
const val VERSION_NAME = "5.0.5"
const val VERSION_CODE = 50005
const val VERSION_NAME = "5.0.6"
const val VERSION_CODE = 50006
const val TARGET_SDK = 37
const val MIN_SDK = 26
@@ -0,0 +1,3 @@
What's new:
- Bugfix for Android 17 local network permission requirement
- Bugfix for app shortcuts causing crash
+1
View File
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_LOCAL_NETWORK" />
<!--foreground service special use for non VPN service tunnels, android 14-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<!--foreground service special use for VPN service tunnels, android 14-->