fix: tile auto tunnel toggle and wifi internet connection check
Change tile toggle behavior to also toggle auto tunnel service to allow user temporary override and re-enablement of auto tunnel from the tile. Add tunnel name to tile. Fix bug where wifi networks without internet access were impacting auto tunneling determinations. Closes #22
This commit is contained in:
parent
0e64bbb4e1
commit
eeccc71469
|
@ -17,7 +17,7 @@ android {
|
|||
|
||||
val versionMajor = 2
|
||||
val versionMinor = 3
|
||||
val versionPatch = 6
|
||||
val versionPatch = 7
|
||||
val versionBuild = 0
|
||||
|
||||
defaultConfig {
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.wireguard.android.backend.Tunnel
|
|||
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
|
||||
|
@ -39,18 +40,15 @@ class TunnelControlTile : TileService() {
|
|||
private lateinit var job : Job
|
||||
|
||||
override fun onStartListening() {
|
||||
if (!this::job.isInitialized) {
|
||||
job = scope.launch {
|
||||
updateTileState()
|
||||
}
|
||||
job = scope.launch {
|
||||
updateTileState()
|
||||
}
|
||||
Timber.d("On start listening")
|
||||
super.onStartListening()
|
||||
}
|
||||
|
||||
override fun onTileAdded() {
|
||||
super.onTileAdded()
|
||||
qsTile.contentDescription = "Toggle VPN"
|
||||
qsTile.contentDescription = this.resources.getString(R.string.toggle_vpn)
|
||||
scope.launch {
|
||||
updateTileState();
|
||||
}
|
||||
|
@ -62,43 +60,50 @@ class TunnelControlTile : TileService() {
|
|||
}
|
||||
|
||||
override fun onClick() {
|
||||
super.onClick()
|
||||
unlockAndRun {
|
||||
scope.launch {
|
||||
try {
|
||||
if(vpnService.getState() == Tunnel.State.UP) {
|
||||
stopTunnel();
|
||||
return@launch
|
||||
}
|
||||
val settings = settingsRepo.getAll()
|
||||
if (!settings.isNullOrEmpty()) {
|
||||
val setting = settings.first()
|
||||
if (setting.defaultTunnel != null) {
|
||||
startTunnel(setting.defaultTunnel!!)
|
||||
val tunnel = determineTileTunnel();
|
||||
if(tunnel != null) {
|
||||
attemptWatcherServiceToggle(tunnel.toString())
|
||||
if(vpnService.getState() == Tunnel.State.UP) {
|
||||
stopTunnelService();
|
||||
} else {
|
||||
val config = configRepo.getAll()?.first();
|
||||
if(config != null) {
|
||||
startTunnel(config.toString());
|
||||
}
|
||||
startTunnelService(tunnel.toString())
|
||||
}
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
Timber.e(e.message)
|
||||
} finally {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
super.onClick()
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopTunnel() {
|
||||
private suspend fun determineTileTunnel() : TunnelConfig? {
|
||||
var tunnelConfig : TunnelConfig? = null;
|
||||
val settings = settingsRepo.getAll()
|
||||
if (!settings.isNullOrEmpty()) {
|
||||
val setting = settings.first()
|
||||
tunnelConfig = if (setting.defaultTunnel != null) {
|
||||
TunnelConfig.from(setting.defaultTunnel!!);
|
||||
} else {
|
||||
val config = configRepo.getAll()?.first();
|
||||
config;
|
||||
}
|
||||
}
|
||||
return tunnelConfig;
|
||||
}
|
||||
|
||||
private fun stopTunnelService() {
|
||||
ServiceTracker.actionOnService(
|
||||
Action.STOP, this@TunnelControlTile,
|
||||
WireGuardConnectivityWatcherService::class.java)
|
||||
ServiceTracker.actionOnService(
|
||||
Action.STOP, this@TunnelControlTile,
|
||||
Action.STOP, this.applicationContext,
|
||||
WireGuardTunnelService::class.java)
|
||||
}
|
||||
|
||||
private fun startTunnel(tunnelConfig : String) {
|
||||
private fun startTunnelService(tunnelConfig : String) {
|
||||
ServiceTracker.actionOnService(
|
||||
Action.START, this.applicationContext,
|
||||
WireGuardTunnelService::class.java,
|
||||
|
@ -107,42 +112,64 @@ class TunnelControlTile : TileService() {
|
|||
tunnelConfig))
|
||||
}
|
||||
|
||||
private fun startWatcherService(tunnelConfig : String) {
|
||||
ServiceTracker.actionOnService(
|
||||
Action.START, this,
|
||||
WireGuardConnectivityWatcherService::class.java, mapOf(this.resources.
|
||||
getString(R.string.tunnel_extras_key) to
|
||||
tunnelConfig))
|
||||
}
|
||||
|
||||
private fun stopWatcherService() {
|
||||
ServiceTracker.actionOnService(
|
||||
Action.STOP, this,
|
||||
WireGuardConnectivityWatcherService::class.java)
|
||||
}
|
||||
|
||||
private fun attemptWatcherServiceToggle(tunnelConfig : String) {
|
||||
scope.launch {
|
||||
val settings = settingsRepo.getAll()
|
||||
if (!settings.isNullOrEmpty()) {
|
||||
val setting = settings.first()
|
||||
if(setting.isAutoTunnelEnabled) {
|
||||
when(ServiceTracker.getServiceState( this@TunnelControlTile,
|
||||
WireGuardConnectivityWatcherService::class.java,)) {
|
||||
ServiceState.STARTED -> stopWatcherService()
|
||||
ServiceState.STOPPED -> startWatcherService(tunnelConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateTileState() {
|
||||
vpnService.state.collect {
|
||||
when(it) {
|
||||
Tunnel.State.UP -> {
|
||||
setTileOn()
|
||||
qsTile.state = Tile.STATE_ACTIVE
|
||||
}
|
||||
Tunnel.State.DOWN -> {
|
||||
setTileOff()
|
||||
qsTile.state = Tile.STATE_INACTIVE;
|
||||
}
|
||||
else -> {
|
||||
qsTile.state = Tile.STATE_UNAVAILABLE
|
||||
}
|
||||
}
|
||||
val config = determineTileTunnel();
|
||||
setTileDescription(config?.name ?: this.resources.getString(R.string.no_tunnel_available))
|
||||
qsTile.updateTile()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setTileOff() {
|
||||
qsTile.state = Tile.STATE_INACTIVE;
|
||||
private fun setTileDescription(description : String) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
qsTile.subtitle = "Off"
|
||||
qsTile.subtitle = description
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
qsTile.stateDescription = "VPN Off";
|
||||
qsTile.stateDescription = description;
|
||||
}
|
||||
}
|
||||
|
||||
private fun setTileOn() {
|
||||
qsTile.state = Tile.STATE_ACTIVE;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
qsTile.subtitle = "On"
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
qsTile.stateDescription = "VPN On";
|
||||
}
|
||||
}
|
||||
private fun cancelJob() {
|
||||
if(this::job.isInitialized) {
|
||||
job.cancel();
|
||||
|
|
|
@ -4,10 +4,7 @@ import android.app.Service
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import com.zaneschepke.wireguardautotunnel.repository.Repository
|
||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
open class ForegroundService : Service() {
|
||||
|
|
|
@ -24,6 +24,7 @@ object ServiceTracker {
|
|||
|
||||
fun <T : Service> actionOnService(action: Action, application: Application, cls : Class<T>, extras : Map<String,String>? = null) {
|
||||
if (getServiceState(application, cls) == ServiceState.STOPPED && action == Action.STOP) return
|
||||
if (getServiceState(application, cls) == ServiceState.STARTED && action == Action.START) return
|
||||
val intent = Intent(application, cls).also {
|
||||
it.action = action.name
|
||||
extras?.forEach {(k, v) ->
|
||||
|
@ -40,6 +41,7 @@ object ServiceTracker {
|
|||
|
||||
fun <T : Service> actionOnService(action: Action, context: Context, cls : Class<T>, extras : Map<String,String>? = null) {
|
||||
if (getServiceState(context, cls) == ServiceState.STOPPED && action == Action.STOP) return
|
||||
if (getServiceState(context, cls) == ServiceState.STARTED && action == Action.START) return
|
||||
val intent = Intent(context, cls).also {
|
||||
it.action = action.name
|
||||
extras?.forEach {(k, v) ->
|
||||
|
|
|
@ -85,7 +85,6 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
|
|||
}
|
||||
}
|
||||
cancelWatcherJob()
|
||||
stopVPN()
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ abstract class BaseNetworkService<T : BaseNetworkService<T>>(val context: Contex
|
|||
object : ConnectivityManager.NetworkCallback(
|
||||
FLAG_INCLUDE_LOCATION_INFO
|
||||
) {
|
||||
|
||||
override fun onAvailable(network: Network) {
|
||||
trySend(NetworkStatus.Available(network))
|
||||
}
|
||||
|
@ -68,6 +67,8 @@ abstract class BaseNetworkService<T : BaseNetworkService<T>>(val context: Contex
|
|||
}
|
||||
val request = NetworkRequest.Builder()
|
||||
.addTransportType(networkCapability)
|
||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
|
||||
.build()
|
||||
connectivityManager.registerNetworkCallback(request, networkStatusCallback)
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ class WireGuardTunnel @Inject constructor(private val backend : Backend,
|
|||
override val tunnelName get() = _tunnelName.asStateFlow()
|
||||
|
||||
private val _state = MutableSharedFlow<Tunnel.State>(
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST,
|
||||
replay = 1)
|
||||
|
||||
private val _handshakeStatus = MutableSharedFlow<HandshakeStatus>(replay = 1,
|
||||
|
|
|
@ -11,5 +11,5 @@ data class Settings(
|
|||
var isTunnelOnMobileDataEnabled : Boolean = false,
|
||||
var trustedNetworkSSIDs : MutableList<String> = mutableListOf(),
|
||||
var defaultTunnel : String? = null,
|
||||
var isAlwaysOnVpnEnabled : Boolean = false
|
||||
var isAlwaysOnVpnEnabled : Boolean = false,
|
||||
)
|
||||
|
|
|
@ -84,4 +84,6 @@
|
|||
<string name="detecting_location_services_disabled">Detecting Location Services disabled</string>
|
||||
<string name="precise_location_message">This feature requires precise location to access Wi-Fi SSID name. Please enable precise location here or in the app settings.</string>
|
||||
<string name="request">Request</string>
|
||||
<string name="toggle_vpn">Toggle VPN</string>
|
||||
<string name="no_tunnel_available">No tunnels available</string>
|
||||
</resources>
|
Loading…
Reference in New Issue