Skip to content

Commit 13bb300

Browse files
committed
feat: add worker to restart killed services
1 parent 1375a46 commit 13bb300

File tree

8 files changed

+95
-7
lines changed

8 files changed

+95
-7
lines changed

app/build.gradle.kts

+6-2
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,7 @@ dependencies {
172172
debugImplementation(libs.androidx.compose.ui.tooling)
173173
debugImplementation(libs.androidx.compose.manifest)
174174

175-
// get tunnel lib from github packages or mavenLocal
176-
// implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar"))))
175+
// tunnel
177176
implementation(libs.tunnel)
178177
implementation(libs.amneziawg.android)
179178
coreLibraryDesugaring(libs.desugar.jdk.libs)
@@ -188,6 +187,7 @@ dependencies {
188187
// hilt
189188
implementation(libs.hilt.android)
190189
ksp(libs.hilt.android.compiler)
190+
ksp(libs.androidx.hilt.compiler)
191191

192192
// accompanist
193193
implementation(libs.accompanist.permissions)
@@ -221,6 +221,10 @@ dependencies {
221221

222222
// splash
223223
implementation(libs.androidx.core.splashscreen)
224+
225+
// worker
226+
implementation(libs.androidx.work.runtime)
227+
implementation(libs.androidx.hilt.work)
224228
}
225229

226230
fun determineVersionName(): String {

app/src/main/AndroidManifest.xml

+7
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@
106106
android:resource="@xml/file_paths" />
107107
</provider>
108108

109+
<provider
110+
android:name="androidx.startup.InitializationProvider"
111+
android:authorities="${applicationId}.androidx-startup"
112+
android:multiprocess="true"
113+
tools:node="remove">
114+
</provider>
115+
109116
<service
110117
android:name=".core.service.tile.TunnelControlTile"
111118
android:exported="true"

app/src/main/java/com/zaneschepke/wireguardautotunnel/MainActivity.kt

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import androidx.navigation.compose.rememberNavController
4040
import androidx.navigation.toRoute
4141
import com.zaneschepke.wireguardautotunnel.core.shortcut.ShortcutManager
4242
import com.zaneschepke.wireguardautotunnel.core.tunnel.TunnelManager
43+
import com.zaneschepke.wireguardautotunnel.core.worker.ServiceWorker
4344
import com.zaneschepke.wireguardautotunnel.domain.repository.AppStateRepository
4445
import com.zaneschepke.wireguardautotunnel.ui.Route
4546
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.BottomNavBar
@@ -134,6 +135,8 @@ class MainActivity : AppCompatActivity() {
134135
}
135136
}
136137

138+
ServiceWorker.start(this)
139+
137140
CompositionLocalProvider(LocalNavController provides navController) {
138141
SnackbarControllerProvider { host ->
139142
WireguardAutoTunnelTheme(theme = appUiState.generalState.theme) {

app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt

+11-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package com.zaneschepke.wireguardautotunnel
33
import android.app.Application
44
import android.os.StrictMode
55
import android.os.StrictMode.ThreadPolicy
6+
import androidx.hilt.work.HiltWorkerFactory
67
import androidx.lifecycle.DefaultLifecycleObserver
78
import androidx.lifecycle.LifecycleOwner
89
import androidx.lifecycle.ProcessLifecycleOwner
10+
import androidx.work.Configuration
911
import com.wireguard.android.backend.GoBackend
1012
import com.zaneschepke.logcatter.LogReader
1113
import com.zaneschepke.wireguardautotunnel.core.tunnel.TunnelManager
@@ -26,7 +28,15 @@ import timber.log.Timber
2628
import javax.inject.Inject
2729

2830
@HiltAndroidApp
29-
class WireGuardAutoTunnel : Application() {
31+
class WireGuardAutoTunnel : Application(), Configuration.Provider {
32+
33+
@Inject
34+
lateinit var workerFactory: HiltWorkerFactory
35+
36+
override val workManagerConfiguration: Configuration
37+
get() = Configuration.Builder()
38+
.setWorkerFactory(workerFactory)
39+
.build()
3040

3141
@Inject
3242
@ApplicationScope

app/src/main/java/com/zaneschepke/wireguardautotunnel/core/broadcast/AppUpdateReceiver.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class AppUpdateReceiver : BroadcastReceiver() {
3636
with(appDataRepository.settings.get()) {
3737
if (isRestoreOnBootEnabled) {
3838
// If auto tunnel is enabled, just start it and let auto tunnel start appropriate tun
39-
if (isAutoTunnelEnabled) return@launch serviceManager.startAutoTunnel(true)
39+
if (isAutoTunnelEnabled && !serviceManager.autoTunnelActive.value) return@launch serviceManager.startAutoTunnel(true)
4040
tunnelManager.restorePreviousState()
4141
}
4242
}

app/src/main/java/com/zaneschepke/wireguardautotunnel/core/broadcast/BootReceiver.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class BootReceiver : BroadcastReceiver() {
3535
with(appDataRepository.settings.get()) {
3636
if (isRestoreOnBootEnabled) {
3737
// If auto tunnel is enabled, just start it and let auto tunnel start appropriate tun
38-
if (isAutoTunnelEnabled) return@launch serviceManager.startAutoTunnel(true)
38+
if (isAutoTunnelEnabled && !serviceManager.autoTunnelActive.value) return@launch serviceManager.startAutoTunnel(true)
3939
tunnelManager.restorePreviousState()
4040
}
4141
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.zaneschepke.wireguardautotunnel.core.worker
2+
3+
import android.content.Context
4+
import androidx.hilt.work.HiltWorker
5+
import androidx.work.CoroutineWorker
6+
import androidx.work.ExistingPeriodicWorkPolicy
7+
import androidx.work.PeriodicWorkRequestBuilder
8+
import androidx.work.WorkManager
9+
import androidx.work.WorkerParameters
10+
import com.zaneschepke.wireguardautotunnel.core.service.ServiceManager
11+
import com.zaneschepke.wireguardautotunnel.core.tunnel.TunnelManager
12+
import com.zaneschepke.wireguardautotunnel.di.IoDispatcher
13+
import com.zaneschepke.wireguardautotunnel.domain.repository.AppDataRepository
14+
import dagger.assisted.Assisted
15+
import dagger.assisted.AssistedInject
16+
import kotlinx.coroutines.CoroutineDispatcher
17+
import kotlinx.coroutines.withContext
18+
import timber.log.Timber
19+
import java.util.concurrent.TimeUnit
20+
21+
@HiltWorker
22+
class ServiceWorker @AssistedInject constructor(
23+
@Assisted private val context: Context,
24+
@Assisted private val params: WorkerParameters,
25+
private val serviceManager: ServiceManager,
26+
private val appDataRepository: AppDataRepository,
27+
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
28+
private val tunnelManager: TunnelManager,
29+
) : CoroutineWorker(context, params) {
30+
31+
companion object {
32+
private const val TAG = "service_worker"
33+
34+
fun stop(context: Context) {
35+
WorkManager.getInstance(context).cancelAllWorkByTag(TAG)
36+
}
37+
38+
fun start(context: Context) {
39+
val periodicWorkRequest = PeriodicWorkRequestBuilder<ServiceWorker>(
40+
repeatInterval = 15,
41+
repeatIntervalTimeUnit = TimeUnit.MINUTES,
42+
).build()
43+
WorkManager.getInstance(context)
44+
.enqueueUniquePeriodicWork(
45+
TAG,
46+
ExistingPeriodicWorkPolicy.KEEP,
47+
periodicWorkRequest,
48+
)
49+
}
50+
}
51+
52+
override suspend fun doWork(): Result = withContext(ioDispatcher) {
53+
Timber.i("Service worker started")
54+
with(appDataRepository.settings.get()) {
55+
if (isAutoTunnelEnabled && !serviceManager.autoTunnelActive.value) return@with serviceManager.startAutoTunnel(true)
56+
if (tunnelManager.activeTunnels().value.isEmpty()) tunnelManager.restorePreviousState()
57+
}
58+
Result.success()
59+
}
60+
}

gradle/libs.versions.toml

+6-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ datastorePreferences = "1.1.2"
1010
desugar_jdk_libs = "2.1.4"
1111
espressoCore = "3.6.1"
1212
hiltAndroid = "2.55"
13-
hiltNavigationCompose = "1.2.0"
13+
hiltCompiler = "1.2.0"
1414
junit = "4.13.2"
1515
kotlinx-serialization-json = "1.8.0"
1616
lifecycle-runtime-compose = "2.8.7"
@@ -25,6 +25,7 @@ kotlin = "2.1.10"
2525
ksp = "2.1.10-1.0.30"
2626
composeBom = "2025.02.00"
2727
compose = "1.7.8"
28+
workRuntimeKtxVersion = "2.10.0"
2829
zxingAndroidEmbedded = "4.3.0"
2930
coreSplashscreen = "1.0.1"
3031
gradlePlugins-grgit = "5.3.0"
@@ -45,6 +46,7 @@ amneziawg-android = { module = "com.zaneschepke:amneziawg-android", version.ref
4546
androidx-biometric-ktx = { module = "androidx.biometric:biometric-ktx", version.ref = "biometricKtx" }
4647
androidx-core = { module = "androidx.core:core", version.ref = "coreKtx" }
4748
androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
49+
androidx-hilt-work = { module = "androidx.hilt:hilt-work", version.ref = "hiltCompiler" }
4850
androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "lifecycle-runtime-compose" }
4951
androidx-lifecycle-service = { module = "androidx.lifecycle:lifecycle-service", version.ref = "lifecycle-runtime-compose" }
5052
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomVersion" }
@@ -62,15 +64,17 @@ androidx-compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compos
6264

6365
#hilt
6466
androidx-room-testing = { module = "androidx.room:room-testing", version.ref = "roomVersion" }
67+
androidx-work-runtime = { module = "androidx.work:work-runtime-ktx", version.ref = "workRuntimeKtxVersion" }
6568
desugar_jdk_libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar_jdk_libs" }
6669
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" }
6770
hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" }
71+
androidx-hilt-compiler = { module = "androidx.hilt:hilt-compiler", version.ref = "hiltCompiler" }
6872

6973
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
7074
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
7175
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
7276
androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espressoCore" }
73-
androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" }
77+
androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltCompiler" }
7478
androidx-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-junit" }
7579
androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "coreSplashscreen" }
7680
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle-runtime-compose" }

0 commit comments

Comments
 (0)