mirror of
https://github.com/wgtunnel/android.git
synced 2026-07-03 14:07:49 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b74a50de2c |
@@ -172,7 +172,8 @@ dependencies {
|
||||
debugImplementation(libs.androidx.compose.ui.tooling)
|
||||
debugImplementation(libs.androidx.compose.manifest)
|
||||
|
||||
// tunnel
|
||||
// get tunnel lib from github packages or mavenLocal
|
||||
// implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar"))))
|
||||
implementation(libs.tunnel)
|
||||
implementation(libs.amneziawg.android)
|
||||
coreLibraryDesugaring(libs.desugar.jdk.libs)
|
||||
@@ -187,7 +188,6 @@ dependencies {
|
||||
// hilt
|
||||
implementation(libs.hilt.android)
|
||||
ksp(libs.hilt.android.compiler)
|
||||
ksp(libs.androidx.hilt.compiler)
|
||||
|
||||
// accompanist
|
||||
implementation(libs.accompanist.permissions)
|
||||
@@ -221,10 +221,6 @@ dependencies {
|
||||
|
||||
// splash
|
||||
implementation(libs.androidx.core.splashscreen)
|
||||
|
||||
// worker
|
||||
implementation(libs.androidx.work.runtime)
|
||||
implementation(libs.androidx.hilt.work)
|
||||
}
|
||||
|
||||
fun determineVersionName(): String {
|
||||
|
||||
@@ -106,13 +106,6 @@
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
<provider
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup"
|
||||
android:multiprocess="true"
|
||||
tools:node="remove">
|
||||
</provider>
|
||||
|
||||
<service
|
||||
android:name=".core.service.tile.TunnelControlTile"
|
||||
android:exported="true"
|
||||
|
||||
@@ -40,7 +40,6 @@ import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.toRoute
|
||||
import com.zaneschepke.wireguardautotunnel.core.shortcut.ShortcutManager
|
||||
import com.zaneschepke.wireguardautotunnel.core.tunnel.TunnelManager
|
||||
import com.zaneschepke.wireguardautotunnel.core.worker.ServiceWorker
|
||||
import com.zaneschepke.wireguardautotunnel.domain.repository.AppStateRepository
|
||||
import com.zaneschepke.wireguardautotunnel.ui.Route
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.BottomNavBar
|
||||
@@ -135,8 +134,6 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
ServiceWorker.start(this)
|
||||
|
||||
CompositionLocalProvider(LocalNavController provides navController) {
|
||||
SnackbarControllerProvider { host ->
|
||||
WireguardAutoTunnelTheme(theme = appUiState.generalState.theme) {
|
||||
|
||||
@@ -3,11 +3,9 @@ package com.zaneschepke.wireguardautotunnel
|
||||
import android.app.Application
|
||||
import android.os.StrictMode
|
||||
import android.os.StrictMode.ThreadPolicy
|
||||
import androidx.hilt.work.HiltWorkerFactory
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import androidx.work.Configuration
|
||||
import com.wireguard.android.backend.GoBackend
|
||||
import com.zaneschepke.logcatter.LogReader
|
||||
import com.zaneschepke.wireguardautotunnel.core.tunnel.TunnelManager
|
||||
@@ -28,15 +26,7 @@ import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltAndroidApp
|
||||
class WireGuardAutoTunnel : Application(), Configuration.Provider {
|
||||
|
||||
@Inject
|
||||
lateinit var workerFactory: HiltWorkerFactory
|
||||
|
||||
override val workManagerConfiguration: Configuration
|
||||
get() = Configuration.Builder()
|
||||
.setWorkerFactory(workerFactory)
|
||||
.build()
|
||||
class WireGuardAutoTunnel : Application() {
|
||||
|
||||
@Inject
|
||||
@ApplicationScope
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ class AppUpdateReceiver : BroadcastReceiver() {
|
||||
with(appDataRepository.settings.get()) {
|
||||
if (isRestoreOnBootEnabled) {
|
||||
// If auto tunnel is enabled, just start it and let auto tunnel start appropriate tun
|
||||
if (isAutoTunnelEnabled && !serviceManager.autoTunnelActive.value) return@launch serviceManager.startAutoTunnel(true)
|
||||
if (isAutoTunnelEnabled) return@launch serviceManager.startAutoTunnel(true)
|
||||
tunnelManager.restorePreviousState()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ class BootReceiver : BroadcastReceiver() {
|
||||
with(appDataRepository.settings.get()) {
|
||||
if (isRestoreOnBootEnabled) {
|
||||
// If auto tunnel is enabled, just start it and let auto tunnel start appropriate tun
|
||||
if (isAutoTunnelEnabled && !serviceManager.autoTunnelActive.value) return@launch serviceManager.startAutoTunnel(true)
|
||||
if (isAutoTunnelEnabled) return@launch serviceManager.startAutoTunnel(true)
|
||||
tunnelManager.restorePreviousState()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.zaneschepke.wireguardautotunnel.core.worker
|
||||
|
||||
import android.content.Context
|
||||
import androidx.hilt.work.HiltWorker
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ExistingPeriodicWorkPolicy
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import com.zaneschepke.wireguardautotunnel.core.service.ServiceManager
|
||||
import com.zaneschepke.wireguardautotunnel.core.tunnel.TunnelManager
|
||||
import com.zaneschepke.wireguardautotunnel.di.IoDispatcher
|
||||
import com.zaneschepke.wireguardautotunnel.domain.repository.AppDataRepository
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@HiltWorker
|
||||
class ServiceWorker @AssistedInject constructor(
|
||||
@Assisted private val context: Context,
|
||||
@Assisted private val params: WorkerParameters,
|
||||
private val serviceManager: ServiceManager,
|
||||
private val appDataRepository: AppDataRepository,
|
||||
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
|
||||
private val tunnelManager: TunnelManager,
|
||||
) : CoroutineWorker(context, params) {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "service_worker"
|
||||
|
||||
fun stop(context: Context) {
|
||||
WorkManager.getInstance(context).cancelAllWorkByTag(TAG)
|
||||
}
|
||||
|
||||
fun start(context: Context) {
|
||||
val periodicWorkRequest = PeriodicWorkRequestBuilder<ServiceWorker>(
|
||||
repeatInterval = 15,
|
||||
repeatIntervalTimeUnit = TimeUnit.MINUTES,
|
||||
).build()
|
||||
WorkManager.getInstance(context)
|
||||
.enqueueUniquePeriodicWork(
|
||||
TAG,
|
||||
ExistingPeriodicWorkPolicy.KEEP,
|
||||
periodicWorkRequest,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun doWork(): Result = withContext(ioDispatcher) {
|
||||
Timber.i("Service worker started")
|
||||
with(appDataRepository.settings.get()) {
|
||||
if (isAutoTunnelEnabled && !serviceManager.autoTunnelActive.value) return@with serviceManager.startAutoTunnel(true)
|
||||
if (tunnelManager.activeTunnels().value.isEmpty()) tunnelManager.restorePreviousState()
|
||||
}
|
||||
Result.success()
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.zaneschepke.wireguardautotunnel.domain.enums
|
||||
|
||||
enum class ConfigType {
|
||||
AMNEZIA,
|
||||
WG,
|
||||
}
|
||||
+3
-58
@@ -5,9 +5,8 @@ import androidx.compose.foundation.focusable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
@@ -16,7 +15,6 @@ import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.ViewQuilt
|
||||
import androidx.compose.material.icons.filled.AppShortcut
|
||||
import androidx.compose.material.icons.filled.FolderZip
|
||||
import androidx.compose.material.icons.outlined.Bolt
|
||||
import androidx.compose.material.icons.outlined.Code
|
||||
import androidx.compose.material.icons.outlined.FolderZip
|
||||
@@ -25,11 +23,7 @@ import androidx.compose.material.icons.outlined.Pin
|
||||
import androidx.compose.material.icons.outlined.Restore
|
||||
import androidx.compose.material.icons.outlined.VpnKeyOff
|
||||
import androidx.compose.material.icons.outlined.VpnLock
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -44,7 +38,6 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.zaneschepke.wireguardautotunnel.R
|
||||
import com.zaneschepke.wireguardautotunnel.domain.enums.ConfigType
|
||||
import com.zaneschepke.wireguardautotunnel.ui.state.AppUiState
|
||||
import com.zaneschepke.wireguardautotunnel.viewmodel.AppViewModel
|
||||
import com.zaneschepke.wireguardautotunnel.ui.Route
|
||||
@@ -63,7 +56,7 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.showToast
|
||||
import com.zaneschepke.wireguardautotunnel.viewmodel.SettingsViewModel
|
||||
import xyz.teamgravity.pin_lock_compose.PinManager
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun SettingsScreen(viewModel: SettingsViewModel = hiltViewModel(), appViewModel: AppViewModel, uiState: AppUiState) {
|
||||
val context = LocalContext.current
|
||||
@@ -75,13 +68,11 @@ fun SettingsScreen(viewModel: SettingsViewModel = hiltViewModel(), appViewModel:
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
var showAuthPrompt by remember { mutableStateOf(false) }
|
||||
|
||||
var showExportSheet by remember { mutableStateOf(false) }
|
||||
|
||||
if (showAuthPrompt) {
|
||||
AuthorizationPrompt(
|
||||
onSuccess = {
|
||||
showAuthPrompt = false
|
||||
showExportSheet = true
|
||||
viewModel.exportAllConfigs(context)
|
||||
},
|
||||
onError = { _ ->
|
||||
showAuthPrompt = false
|
||||
@@ -98,52 +89,6 @@ fun SettingsScreen(viewModel: SettingsViewModel = hiltViewModel(), appViewModel:
|
||||
)
|
||||
}
|
||||
|
||||
if (showExportSheet) {
|
||||
ModalBottomSheet(onDismissRequest = { showExportSheet = false }) {
|
||||
Row(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
showExportSheet = false
|
||||
viewModel.exportAllConfigs(context, ConfigType.AMNEZIA)
|
||||
}
|
||||
.padding(10.dp),
|
||||
) {
|
||||
Icon(
|
||||
Icons.Filled.FolderZip,
|
||||
contentDescription = stringResource(id = R.string.export_amnezia),
|
||||
modifier = Modifier.padding(10.dp),
|
||||
)
|
||||
Text(
|
||||
stringResource(id = R.string.export_amnezia),
|
||||
modifier = Modifier.padding(10.dp),
|
||||
)
|
||||
}
|
||||
HorizontalDivider()
|
||||
Row(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
showExportSheet = false
|
||||
viewModel.exportAllConfigs(context, ConfigType.WG)
|
||||
}
|
||||
.padding(10.dp),
|
||||
) {
|
||||
Icon(
|
||||
Icons.Filled.FolderZip,
|
||||
contentDescription = stringResource(id = R.string.export_wireguard),
|
||||
modifier = Modifier.padding(10.dp),
|
||||
)
|
||||
Text(
|
||||
stringResource(id = R.string.export_wireguard),
|
||||
modifier = Modifier.padding(10.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.Top),
|
||||
|
||||
+6
-15
@@ -5,13 +5,11 @@ import androidx.core.content.FileProvider
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.zaneschepke.wireguardautotunnel.R
|
||||
import com.zaneschepke.wireguardautotunnel.domain.enums.ConfigType
|
||||
import com.zaneschepke.wireguardautotunnel.domain.repository.AppDataRepository
|
||||
import com.zaneschepke.wireguardautotunnel.util.FileUtils
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.launchShareFile
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import java.time.Instant
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -23,23 +21,16 @@ constructor(
|
||||
private val fileUtils: FileUtils,
|
||||
) : ViewModel() {
|
||||
|
||||
fun exportAllConfigs(context: Context, configType: ConfigType) = viewModelScope.launch {
|
||||
fun exportAllConfigs(context: Context) = viewModelScope.launch {
|
||||
runCatching {
|
||||
val shareFile = fileUtils.createNewShareFile("wg-export_${Instant.now().epochSecond}.zip")
|
||||
val tunnels = appDataRepository.tunnels.getAll()
|
||||
val (files, shareFileName) = when (configType) {
|
||||
ConfigType.AMNEZIA -> {
|
||||
Pair(fileUtils.createAmFiles(tunnels), "am-export_${Instant.now().epochSecond}.zip")
|
||||
}
|
||||
ConfigType.WG -> {
|
||||
Pair(fileUtils.createWgFiles(tunnels), "wg-export_${Instant.now().epochSecond}.zip")
|
||||
}
|
||||
}
|
||||
val shareFile = fileUtils.createNewShareFile(shareFileName)
|
||||
fileUtils.zipAll(shareFile, files)
|
||||
val wgFiles = fileUtils.createWgFiles(tunnels)
|
||||
val amFiles = fileUtils.createAmFiles(tunnels)
|
||||
val allFiles = wgFiles + amFiles
|
||||
fileUtils.zipAll(shareFile, allFiles)
|
||||
val uri = FileProvider.getUriForFile(context, context.getString(R.string.provider), shareFile)
|
||||
context.launchShareFile(uri)
|
||||
}.onFailure {
|
||||
Timber.e(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +213,4 @@
|
||||
<string name="unauthorized">Failed to start tunnel, unauthorized.</string>
|
||||
<string name="tunne_start_failed_title">Tunnel failure</string>
|
||||
<string name="multiple">Multiple</string>
|
||||
<string name="export_amnezia">Export as Amnezia</string>
|
||||
<string name="export_wireguard">Export as WireGuard</string>
|
||||
</resources>
|
||||
|
||||
@@ -10,7 +10,7 @@ datastorePreferences = "1.1.2"
|
||||
desugar_jdk_libs = "2.1.4"
|
||||
espressoCore = "3.6.1"
|
||||
hiltAndroid = "2.55"
|
||||
hiltCompiler = "1.2.0"
|
||||
hiltNavigationCompose = "1.2.0"
|
||||
junit = "4.13.2"
|
||||
kotlinx-serialization-json = "1.8.0"
|
||||
lifecycle-runtime-compose = "2.8.7"
|
||||
@@ -20,12 +20,11 @@ pinLockCompose = "1.0.4"
|
||||
roomVersion = "2.6.1"
|
||||
timber = "5.0.1"
|
||||
tunnel = "1.2.2"
|
||||
androidGradlePlugin = "8.8.0-alpha05"
|
||||
androidGradlePlugin = "8.10.0-alpha05"
|
||||
kotlin = "2.1.10"
|
||||
ksp = "2.1.10-1.0.30"
|
||||
composeBom = "2025.02.00"
|
||||
compose = "1.7.8"
|
||||
workRuntimeKtxVersion = "2.10.0"
|
||||
zxingAndroidEmbedded = "4.3.0"
|
||||
coreSplashscreen = "1.0.1"
|
||||
gradlePlugins-grgit = "5.3.0"
|
||||
@@ -46,7 +45,6 @@ amneziawg-android = { module = "com.zaneschepke:amneziawg-android", version.ref
|
||||
androidx-biometric-ktx = { module = "androidx.biometric:biometric-ktx", version.ref = "biometricKtx" }
|
||||
androidx-core = { module = "androidx.core:core", version.ref = "coreKtx" }
|
||||
androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
|
||||
androidx-hilt-work = { module = "androidx.hilt:hilt-work", version.ref = "hiltCompiler" }
|
||||
androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "lifecycle-runtime-compose" }
|
||||
androidx-lifecycle-service = { module = "androidx.lifecycle:lifecycle-service", version.ref = "lifecycle-runtime-compose" }
|
||||
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomVersion" }
|
||||
@@ -64,17 +62,15 @@ androidx-compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compos
|
||||
|
||||
#hilt
|
||||
androidx-room-testing = { module = "androidx.room:room-testing", version.ref = "roomVersion" }
|
||||
androidx-work-runtime = { module = "androidx.work:work-runtime-ktx", version.ref = "workRuntimeKtxVersion" }
|
||||
desugar_jdk_libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar_jdk_libs" }
|
||||
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" }
|
||||
hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" }
|
||||
androidx-hilt-compiler = { module = "androidx.hilt:hilt-compiler", version.ref = "hiltCompiler" }
|
||||
|
||||
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
|
||||
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
|
||||
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
|
||||
androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espressoCore" }
|
||||
androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltCompiler" }
|
||||
androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" }
|
||||
androidx-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-junit" }
|
||||
androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "coreSplashscreen" }
|
||||
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle-runtime-compose" }
|
||||
|
||||
Reference in New Issue
Block a user