fix: service status out of sync
This fixes the status of service becoming out of sync with the user settings by getting service status from ActivityManager.
This commit is contained in:
parent
f894a3e0c9
commit
98da234ef9
|
@ -17,7 +17,7 @@ android {
|
|||
|
||||
val versionMajor = 1
|
||||
val versionMinor = 1
|
||||
val versionPatch = 3
|
||||
val versionPatch = 4
|
||||
val versionBuild = 0
|
||||
|
||||
defaultConfig {
|
||||
|
|
|
@ -45,7 +45,6 @@ open class ForegroundService : Service() {
|
|||
if (isServiceStarted) return
|
||||
Timber.d("Starting ${this.javaClass.simpleName}")
|
||||
isServiceStarted = true
|
||||
ServiceTracker.setServiceState(this, ServiceState.STARTED, this.javaClass)
|
||||
}
|
||||
|
||||
protected open fun stopService(extras : Bundle?) {
|
||||
|
@ -57,6 +56,5 @@ open class ForegroundService : Service() {
|
|||
Timber.d("Service stopped without being started: ${e.message}")
|
||||
}
|
||||
isServiceStarted = false
|
||||
ServiceTracker.setServiceState(this, ServiceState.STOPPED, this.javaClass)
|
||||
}
|
||||
}
|
|
@ -1,29 +1,25 @@
|
|||
package com.zaneschepke.wireguardautotunnel.service.foreground
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.app.Application
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Context.ACTIVITY_SERVICE
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import com.zaneschepke.wireguardautotunnel.R
|
||||
|
||||
object ServiceTracker {
|
||||
fun <T : Service> setServiceState(context: Context, state: ServiceState, cls : Class<T>) {
|
||||
val sharedPrefs = getPreferences(context)
|
||||
sharedPrefs.edit().let {
|
||||
it.putString(cls.simpleName, state.name)
|
||||
it.apply()
|
||||
}
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
private // Deprecated for third party Services.
|
||||
fun <T> Context.isServiceRunning(service: Class<T>) =
|
||||
(getSystemService(ACTIVITY_SERVICE) as ActivityManager)
|
||||
.getRunningServices(Integer.MAX_VALUE)
|
||||
.any { it.service.className == service.name }
|
||||
|
||||
private fun <T : Service> getServiceState(context: Context, cls : Class<T>): ServiceState {
|
||||
val sharedPrefs = getPreferences(context)
|
||||
val value = sharedPrefs.getString(cls.simpleName, ServiceState.STOPPED.name)
|
||||
return ServiceState.valueOf(value!!)
|
||||
}
|
||||
|
||||
private fun getPreferences(context: Context): SharedPreferences {
|
||||
return context.getSharedPreferences(context.resources.getString(R.string.foreground_file), 0)
|
||||
fun <T : Service> getServiceState(context: Context, cls : Class<T>): ServiceState {
|
||||
val isServiceRunning = context.isServiceRunning(cls)
|
||||
return if(isServiceRunning) ServiceState.STARTED else ServiceState.STOPPED
|
||||
}
|
||||
|
||||
fun <T : Service> actionOnService(action: Action, application: Application, cls : Class<T>, extras : Map<String,String>? = null) {
|
||||
|
|
|
@ -131,12 +131,12 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
|
|||
if(!settings.isNullOrEmpty()) {
|
||||
setting = settings[0]
|
||||
}
|
||||
watchForWifiConnectivityChanges()
|
||||
if(setting.isTunnelOnMobileDataEnabled) {
|
||||
GlobalScope.launch {
|
||||
watchForMobileDataConnectivityChanges()
|
||||
}
|
||||
}
|
||||
watchForWifiConnectivityChanges()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,16 +171,18 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
|
|||
isWifiConnected = true
|
||||
}
|
||||
is NetworkStatus.CapabilitiesChanged -> {
|
||||
Timber.d("Wifi capabilities changed")
|
||||
isWifiConnected = true
|
||||
if (!connecting && !disconnecting) {
|
||||
Timber.d("Not connect and not disconnecting")
|
||||
val ssid = wifiService.getNetworkName(it.networkCapabilities);
|
||||
Timber.d("SSID: $ssid")
|
||||
if ((setting.trustedNetworkSSIDs?.contains(ssid) == false) && vpnService.getState() == Tunnel.State.DOWN) {
|
||||
Timber.d("Starting VPN Tunnel for untrusted network: $ssid")
|
||||
startVPN()
|
||||
} else if (!disconnecting && vpnService.getState() == Tunnel.State.UP && (setting.trustedNetworkSSIDs?.contains(
|
||||
} else if (!disconnecting && vpnService.getState() == Tunnel.State.UP && setting.trustedNetworkSSIDs.contains(
|
||||
ssid
|
||||
) == true)
|
||||
)
|
||||
) {
|
||||
Timber.d("Stopping VPN Tunnel for trusted network with ssid: $ssid")
|
||||
stopVPN()
|
||||
|
@ -191,7 +193,10 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
|
|||
isWifiConnected = false
|
||||
Timber.d("Lost Wi-Fi connection")
|
||||
if(setting.isTunnelOnMobileDataEnabled && vpnService.getState() == Tunnel.State.DOWN
|
||||
&& isMobileDataConnected) startVPN()
|
||||
&& isMobileDataConnected){
|
||||
Timber.d("Wifi not available so starting vpn for mobile data")
|
||||
startVPN()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.wireguard.config.Config
|
|||
import com.zaneschepke.wireguardautotunnel.R
|
||||
import com.zaneschepke.wireguardautotunnel.repository.Repository
|
||||
import com.zaneschepke.wireguardautotunnel.service.foreground.Action
|
||||
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceState
|
||||
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceTracker
|
||||
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardConnectivityWatcherService
|
||||
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardTunnelService
|
||||
|
@ -23,6 +24,7 @@ import kotlinx.coroutines.delay
|
|||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
|
@ -48,11 +50,26 @@ class MainViewModel @Inject constructor(private val application : Application,
|
|||
viewModelScope.launch {
|
||||
settingsRepo.itemFlow.collect {
|
||||
val settings = it.first()
|
||||
validateWatcherServiceState(settings)
|
||||
_settings.emit(settings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun validateWatcherServiceState(settings: Settings) {
|
||||
val watcherState = ServiceTracker.getServiceState(application, WireGuardConnectivityWatcherService::class.java)
|
||||
if(settings.isAutoTunnelEnabled && watcherState == ServiceState.STOPPED && settings.defaultTunnel != null) {
|
||||
startWatcherService(settings.defaultTunnel!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun startWatcherService(tunnel : String) {
|
||||
ServiceTracker.actionOnService(
|
||||
Action.START, application,
|
||||
WireGuardConnectivityWatcherService::class.java,
|
||||
mapOf(application.resources.getString(R.string.tunnel_extras_key) to tunnel))
|
||||
}
|
||||
|
||||
fun onDelete(tunnel : TunnelConfig) {
|
||||
viewModelScope.launch {
|
||||
if(tunnelRepo.count() == 1L) {
|
||||
|
|
Loading…
Reference in New Issue