diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ea6dde3..e573b28 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -204,5 +204,10 @@
+
+
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/AppModule.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/AppModule.kt
index bb5b780..762d476 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/AppModule.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/AppModule.kt
@@ -3,6 +3,8 @@ package com.zaneschepke.wireguardautotunnel.module
import android.content.Context
import com.zaneschepke.logcatter.LogReader
import com.zaneschepke.logcatter.LogcatCollector
+import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService
+import com.zaneschepke.wireguardautotunnel.service.notification.WireGuardNotification
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@@ -27,4 +29,10 @@ class AppModule {
fun provideLogCollect(@ApplicationContext context: Context): LogReader {
return LogcatCollector.init(context = context)
}
+
+ @Singleton
+ @Provides
+ fun provideNotificationService(@ApplicationContext context: Context): NotificationService {
+ return WireGuardNotification(context)
+ }
}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/ServiceModule.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/ServiceModule.kt
index 3810bb2..0dfb304 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/ServiceModule.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/ServiceModule.kt
@@ -4,8 +4,6 @@ import com.zaneschepke.wireguardautotunnel.service.network.EthernetService
import com.zaneschepke.wireguardautotunnel.service.network.MobileDataService
import com.zaneschepke.wireguardautotunnel.service.network.NetworkService
import com.zaneschepke.wireguardautotunnel.service.network.WifiService
-import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService
-import com.zaneschepke.wireguardautotunnel.service.notification.WireGuardNotification
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
@@ -15,10 +13,6 @@ import dagger.hilt.android.scopes.ServiceScoped
@Module
@InstallIn(ServiceComponent::class)
abstract class ServiceModule {
- @Binds
- @ServiceScoped
- abstract fun provideNotificationService(wireGuardNotification: WireGuardNotification): NotificationService
-
@Binds
@ServiceScoped
abstract fun provideWifiService(wifiService: WifiService): NetworkService
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/TunnelModule.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/TunnelModule.kt
index 5c9ceff..42f5a3d 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/TunnelModule.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/TunnelModule.kt
@@ -10,6 +10,7 @@ import com.wireguard.android.util.ToolsInstaller
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
import com.zaneschepke.wireguardautotunnel.data.repository.TunnelConfigRepository
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
+import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService
import com.zaneschepke.wireguardautotunnel.service.tunnel.TunnelService
import com.zaneschepke.wireguardautotunnel.service.tunnel.WireGuardTunnel
import dagger.Module
@@ -76,6 +77,7 @@ class TunnelModule {
@ApplicationScope applicationScope: CoroutineScope,
@IoDispatcher ioDispatcher: CoroutineDispatcher,
serviceManager: ServiceManager,
+ notificationService: NotificationService,
): TunnelService {
return WireGuardTunnel(
amneziaBackend,
@@ -85,12 +87,17 @@ class TunnelModule {
applicationScope,
ioDispatcher,
serviceManager,
+ notificationService,
)
}
@Singleton
@Provides
- fun provideServiceManager(@ApplicationContext context: Context): ServiceManager {
- return ServiceManager.getInstance(context)
+ fun provideServiceManager(
+ @ApplicationContext context: Context,
+ @IoDispatcher ioDispatcher: CoroutineDispatcher,
+ appDataRepository: AppDataRepository,
+ ): ServiceManager {
+ return ServiceManager(context, ioDispatcher, appDataRepository)
}
}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/KernelReceiver.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/KernelReceiver.kt
index 980b62e..c43d198 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/KernelReceiver.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/KernelReceiver.kt
@@ -5,8 +5,8 @@ import android.content.Context
import android.content.Intent
import com.zaneschepke.wireguardautotunnel.data.repository.TunnelConfigRepository
import com.zaneschepke.wireguardautotunnel.module.ApplicationScope
+import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
import com.zaneschepke.wireguardautotunnel.service.tunnel.TunnelService
-import com.zaneschepke.wireguardautotunnel.util.extensions.requestTunnelTileServiceStateUpdate
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@@ -26,6 +26,9 @@ class KernelReceiver : BroadcastReceiver() {
@Inject
lateinit var tunnelConfigRepository: TunnelConfigRepository
+ @Inject
+ lateinit var serviceManager: ServiceManager
+
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action ?: return
applicationScope.launch {
@@ -37,7 +40,7 @@ class KernelReceiver : BroadcastReceiver() {
tunnelConfigRepository.save(it.copy(isActive = true))
}
}
- context.requestTunnelTileServiceStateUpdate()
+ serviceManager.updateTunnelTile()
}
}
}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt
new file mode 100644
index 0000000..9ae409b
--- /dev/null
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt
@@ -0,0 +1,36 @@
+package com.zaneschepke.wireguardautotunnel.receiver
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import com.zaneschepke.wireguardautotunnel.module.ApplicationScope
+import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
+import com.zaneschepke.wireguardautotunnel.service.notification.NotificationAction
+import com.zaneschepke.wireguardautotunnel.service.tunnel.TunnelService
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class NotificationActionReceiver : BroadcastReceiver() {
+
+ @Inject
+ lateinit var serviceManager: ServiceManager
+
+ @Inject
+ lateinit var tunnelService: TunnelService
+
+ @Inject
+ @ApplicationScope
+ lateinit var applicationScope: CoroutineScope
+
+ override fun onReceive(context: Context, intent: Intent) {
+ applicationScope.launch {
+ when (intent.action) {
+ NotificationAction.AUTO_TUNNEL_OFF.name -> serviceManager.stopAutoTunnel()
+ NotificationAction.TUNNEL_OFF.name -> tunnelService.stopTunnel()
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt
index e1b51b9..4fd3089 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt
@@ -3,20 +3,25 @@ package com.zaneschepke.wireguardautotunnel.service.foreground
import android.app.Service
import android.content.Context
import android.content.Intent
+import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
import com.zaneschepke.wireguardautotunnel.service.foreground.autotunnel.AutoTunnelService
-import com.zaneschepke.wireguardautotunnel.util.SingletonHolder
+import com.zaneschepke.wireguardautotunnel.service.tile.AutoTunnelControlTile
+import com.zaneschepke.wireguardautotunnel.service.tile.TunnelControlTile
+import com.zaneschepke.wireguardautotunnel.util.extensions.requestAutoTunnelTileServiceUpdate
import com.zaneschepke.wireguardautotunnel.util.extensions.requestTunnelTileServiceStateUpdate
import jakarta.inject.Inject
import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.withContext
import timber.log.Timber
@OptIn(ExperimentalCoroutinesApi::class)
class ServiceManager
-@Inject constructor(private val context: Context) {
+@Inject constructor(private val context: Context, private val ioDispatcher: CoroutineDispatcher, private val appDataRepository: AppDataRepository) {
private val _autoTunnelActive = MutableStateFlow(false)
@@ -24,8 +29,8 @@ class ServiceManager
var autoTunnelService = CompletableDeferred()
var backgroundService = CompletableDeferred()
-
- companion object : SingletonHolder(::ServiceManager)
+ var autoTunnelTile = CompletableDeferred()
+ var tunnelControlTile = CompletableDeferred()
private fun startService(cls: Class, background: Boolean) {
runCatching {
@@ -39,12 +44,15 @@ class ServiceManager
}
suspend fun startAutoTunnel(background: Boolean) {
+ val settings = appDataRepository.settings.getSettings()
+ appDataRepository.settings.save(settings.copy(isAutoTunnelEnabled = true))
if (autoTunnelService.isCompleted) return _autoTunnelActive.update { true }
kotlin.runCatching {
startService(AutoTunnelService::class.java, background)
autoTunnelService.await()
autoTunnelService.getCompleted().start()
_autoTunnelActive.update { true }
+ updateAutoTunnelTile()
}.onFailure {
Timber.e(it)
}
@@ -70,17 +78,41 @@ class ServiceManager
}
}
- fun stopAutoTunnel() {
- if (!autoTunnelService.isCompleted) return
- runCatching {
- autoTunnelService.getCompleted().stop()
- _autoTunnelActive.update { false }
- }.onFailure {
- Timber.e(it)
+ suspend fun toggleAutoTunnel(background: Boolean) {
+ withContext(ioDispatcher) {
+ if (_autoTunnelActive.value) return@withContext stopAutoTunnel()
+ startAutoTunnel(background)
}
}
- fun requestTunnelTileUpdate() {
- context.requestTunnelTileServiceStateUpdate()
+ fun updateAutoTunnelTile() {
+ if (autoTunnelTile.isCompleted) {
+ autoTunnelTile.getCompleted().updateTileState()
+ } else {
+ context.requestAutoTunnelTileServiceUpdate()
+ }
+ }
+
+ fun updateTunnelTile() {
+ if (tunnelControlTile.isCompleted) {
+ tunnelControlTile.getCompleted().updateTileState()
+ } else {
+ context.requestTunnelTileServiceStateUpdate()
+ }
+ }
+
+ suspend fun stopAutoTunnel() {
+ withContext(ioDispatcher) {
+ val settings = appDataRepository.settings.getSettings()
+ appDataRepository.settings.save(settings.copy(isAutoTunnelEnabled = false))
+ if (!autoTunnelService.isCompleted) return@withContext
+ runCatching {
+ autoTunnelService.getCompleted().stop()
+ _autoTunnelActive.update { false }
+ updateAutoTunnelTile()
+ }.onFailure {
+ Timber.e(it)
+ }
+ }
}
}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/TunnelBackgroundService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/TunnelBackgroundService.kt
index 7bec3d5..02e6dbe 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/TunnelBackgroundService.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/TunnelBackgroundService.kt
@@ -7,6 +7,7 @@ import androidx.core.app.ServiceCompat
import androidx.lifecycle.LifecycleService
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService
+import com.zaneschepke.wireguardautotunnel.service.notification.WireGuardNotification
import com.zaneschepke.wireguardautotunnel.util.Constants
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CompletableDeferred
@@ -21,8 +22,6 @@ class TunnelBackgroundService : LifecycleService() {
@Inject
lateinit var serviceManager: ServiceManager
- private val foregroundId = 123
-
override fun onCreate() {
super.onCreate()
start()
@@ -42,7 +41,7 @@ class TunnelBackgroundService : LifecycleService() {
fun start() {
ServiceCompat.startForeground(
this,
- foregroundId,
+ NotificationService.KERNEL_SERVICE_NOTIFICATION_ID,
createNotification(),
Constants.SYSTEM_EXEMPT_SERVICE_TYPE_ID,
)
@@ -60,8 +59,7 @@ class TunnelBackgroundService : LifecycleService() {
private fun createNotification(): Notification {
return notificationService.createNotification(
- getString(R.string.vpn_channel_id),
- getString(R.string.vpn_channel_name),
+ WireGuardNotification.NotificationChannels.VPN,
getString(R.string.tunnel_running),
description = "",
)
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/autotunnel/AutoTunnelService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/autotunnel/AutoTunnelService.kt
index 6e71b3f..d8c1b1b 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/autotunnel/AutoTunnelService.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/autotunnel/AutoTunnelService.kt
@@ -24,7 +24,9 @@ import com.zaneschepke.wireguardautotunnel.service.network.MobileDataService
import com.zaneschepke.wireguardautotunnel.service.network.NetworkService
import com.zaneschepke.wireguardautotunnel.service.network.NetworkStatus
import com.zaneschepke.wireguardautotunnel.service.network.WifiService
+import com.zaneschepke.wireguardautotunnel.service.notification.NotificationAction
import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService
+import com.zaneschepke.wireguardautotunnel.service.notification.WireGuardNotification
import com.zaneschepke.wireguardautotunnel.service.tunnel.TunnelService
import com.zaneschepke.wireguardautotunnel.util.Constants
import com.zaneschepke.wireguardautotunnel.util.extensions.TunnelConfigs
@@ -41,7 +43,6 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
@@ -54,7 +55,6 @@ import javax.inject.Provider
@AndroidEntryPoint
class AutoTunnelService : LifecycleService() {
- private val foregroundId = 122
@Inject
@AppShell
@@ -148,14 +148,16 @@ class AutoTunnelService : LifecycleService() {
private fun launchWatcherNotification(description: String = getString(R.string.monitoring_state_changes)) {
val notification =
notificationService.createNotification(
- channelId = getString(R.string.watcher_channel_id),
- channelName = getString(R.string.watcher_channel_name),
+ WireGuardNotification.NotificationChannels.AUTO_TUNNEL,
title = getString(R.string.auto_tunnel_title),
description = description,
+ actions = listOf(
+ notificationService.createNotificationAction(NotificationAction.AUTO_TUNNEL_OFF),
+ ),
)
ServiceCompat.startForeground(
this,
- foregroundId,
+ NotificationService.AUTO_TUNNEL_NOTIFICATION_ID,
notification,
Constants.SYSTEM_EXEMPT_SERVICE_TYPE_ID,
)
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/NotificationAction.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/NotificationAction.kt
new file mode 100644
index 0000000..5ff2e8c
--- /dev/null
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/NotificationAction.kt
@@ -0,0 +1,17 @@
+package com.zaneschepke.wireguardautotunnel.service.notification
+
+import android.content.Context
+import com.zaneschepke.wireguardautotunnel.R
+
+enum class NotificationAction {
+ TUNNEL_OFF,
+ AUTO_TUNNEL_OFF,
+ ;
+
+ fun title(context: Context): String {
+ return when (this) {
+ TUNNEL_OFF -> context.getString(R.string.stop)
+ AUTO_TUNNEL_OFF -> context.getString(R.string.stop)
+ }
+ }
+}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/NotificationService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/NotificationService.kt
index 0cc604d..d948c74 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/NotificationService.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/NotificationService.kt
@@ -2,21 +2,25 @@ package com.zaneschepke.wireguardautotunnel.service.notification
import android.app.Notification
import android.app.NotificationManager
-import android.app.PendingIntent
+import androidx.core.app.NotificationCompat
+import com.zaneschepke.wireguardautotunnel.service.notification.WireGuardNotification.NotificationChannels
interface NotificationService {
fun createNotification(
- channelId: String,
- channelName: String,
+ channel: NotificationChannels,
title: String = "",
- action: PendingIntent? = null,
- actionText: String? = null,
- description: String,
+ actions: Collection = emptyList(),
+ description: String = "",
showTimestamp: Boolean = false,
importance: Int = NotificationManager.IMPORTANCE_HIGH,
- vibration: Boolean = false,
onGoing: Boolean = true,
- lights: Boolean = true,
onlyAlertOnce: Boolean = true,
): Notification
+
+ fun createNotificationAction(action: NotificationAction): NotificationCompat.Action
+
+ companion object {
+ const val KERNEL_SERVICE_NOTIFICATION_ID = 123
+ const val AUTO_TUNNEL_NOTIFICATION_ID = 122
+ }
}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/WireGuardNotification.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/WireGuardNotification.kt
index 1409697..a8d2f25 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/WireGuardNotification.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/WireGuardNotification.kt
@@ -1,15 +1,19 @@
package com.zaneschepke.wireguardautotunnel.service.notification
+import android.Manifest
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
+import android.content.pm.PackageManager
import android.graphics.Color
+import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
import com.zaneschepke.wireguardautotunnel.R
-import com.zaneschepke.wireguardautotunnel.ui.MainActivity
+import com.zaneschepke.wireguardautotunnel.receiver.NotificationActionReceiver
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
@@ -17,89 +21,120 @@ class WireGuardNotification
@Inject
constructor(
@ApplicationContext private val context: Context,
-) :
- NotificationService {
+) : NotificationService {
+
+ enum class NotificationChannels {
+ VPN,
+ AUTO_TUNNEL,
+ }
+
private val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
- private val watcherBuilder: NotificationCompat.Builder =
- NotificationCompat.Builder(
- context,
- context.getString(R.string.watcher_channel_id),
- )
- private val tunnelBuilder: NotificationCompat.Builder =
- NotificationCompat.Builder(
- context,
- context.getString(R.string.vpn_channel_id),
- )
-
override fun createNotification(
- channelId: String,
- channelName: String,
+ channel: NotificationChannels,
title: String,
- action: PendingIntent?,
- actionText: String?,
+ actions: Collection,
description: String,
showTimestamp: Boolean,
importance: Int,
- vibration: Boolean,
onGoing: Boolean,
- lights: Boolean,
onlyAlertOnce: Boolean,
): Notification {
- val channel =
- NotificationChannel(
- channelId,
- channelName,
- importance,
- )
- .let {
- it.description = title
- it.enableLights(lights)
- it.lightColor = Color.RED
- it.enableVibration(vibration)
- it.vibrationPattern = longArrayOf(100, 200, 300)
- it
- }
- notificationManager.createNotificationChannel(channel)
- val pendingIntent: PendingIntent =
- Intent(context, MainActivity::class.java).let { notificationIntent ->
- PendingIntent.getActivity(
+ notificationManager.createNotificationChannel(channel.asChannel())
+ return channel.asBuilder().apply {
+ actions.forEach {
+ addAction(it)
+ }
+ setContentTitle(title)
+ setContentText(description)
+ setOnlyAlertOnce(onlyAlertOnce)
+ setOngoing(onGoing)
+ setPriority(NotificationCompat.PRIORITY_HIGH)
+ setShowWhen(showTimestamp)
+ setSmallIcon(R.drawable.ic_launcher)
+ }.build()
+ }
+
+ override fun createNotificationAction(notificationAction: NotificationAction): NotificationCompat.Action {
+ val pendingIntent = PendingIntent.getBroadcast(
+ context,
+ 0,
+ Intent(context, NotificationActionReceiver::class.java).apply {
+ action = notificationAction.name
+ },
+ PendingIntent.FLAG_IMMUTABLE,
+ )
+ return NotificationCompat.Action.Builder(
+ R.drawable.ic_launcher,
+ notificationAction.title(context).uppercase(),
+ pendingIntent,
+ ).build()
+ }
+
+ fun Notification.show(notificationId: Int = defaultId()) {
+ val notification = this
+ with(NotificationManagerCompat.from(context)) {
+ if (ActivityCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
+ return
+ }
+ notify(notificationId, notification)
+ }
+ }
+
+ fun Notification.defaultId(): Int {
+ return when (this.channelId) {
+ context.getString(R.string.vpn_channel_id) -> 100
+ context.getString(R.string.auto_tunnel_channel_id) -> 101
+ else -> 102
+ }
+ }
+
+ fun NotificationChannels.asBuilder(): NotificationCompat.Builder {
+ return when (this) {
+ NotificationChannels.VPN -> {
+ NotificationCompat.Builder(
context,
- 0,
- notificationIntent,
- PendingIntent.FLAG_IMMUTABLE,
+ context.getString(R.string.auto_tunnel_channel_id),
)
}
+ NotificationChannels.AUTO_TUNNEL -> {
+ NotificationCompat.Builder(
+ context,
+ context.getString(R.string.vpn_channel_id),
+ )
+ }
+ }
+ }
- val builder =
- when (channelId) {
- context.getString(R.string.watcher_channel_id) -> watcherBuilder
- context.getString(R.string.vpn_channel_id) -> tunnelBuilder
- else -> {
- NotificationCompat.Builder(
- context,
- channelId,
- )
+ fun NotificationChannels.asChannel(): NotificationChannel {
+ return when (this) {
+ NotificationChannels.VPN -> {
+ NotificationChannel(
+ context.getString(R.string.vpn_channel_id),
+ context.getString(R.string.vpn_channel_name),
+ NotificationManager.IMPORTANCE_HIGH,
+ ).apply {
+ description = context.getString(R.string.vpn_channel_description)
+ enableLights(true)
+ lightColor = Color.WHITE
+ enableVibration(false)
+ vibrationPattern = longArrayOf(100, 200, 300)
}
}
-
- return builder.let {
- if (action != null && actionText != null) {
- it.addAction(
- NotificationCompat.Action.Builder(0, actionText, action).build(),
- )
- it.setAutoCancel(true)
+ NotificationChannels.AUTO_TUNNEL -> {
+ NotificationChannel(
+ context.getString(R.string.auto_tunnel_channel_id),
+ context.getString(R.string.auto_tunnel_channel_name),
+ NotificationManager.IMPORTANCE_HIGH,
+ ).apply {
+ description = context.getString(R.string.auto_tunnel_channel_description)
+ enableLights(true)
+ lightColor = Color.WHITE
+ enableVibration(false)
+ vibrationPattern = longArrayOf(100, 200, 300)
+ }
}
- it.setContentTitle(title)
- .setContentText(description)
- .setOnlyAlertOnce(onlyAlertOnce)
- .setContentIntent(pendingIntent)
- .setOngoing(onGoing)
- .setPriority(NotificationCompat.PRIORITY_HIGH)
- .setShowWhen(showTimestamp)
- .setSmallIcon(R.drawable.ic_launcher)
- .build()
}
}
}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/AutoTunnelControlTile.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/AutoTunnelControlTile.kt
index 0a445e3..20dc8cc 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/AutoTunnelControlTile.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/AutoTunnelControlTile.kt
@@ -1,24 +1,18 @@
package com.zaneschepke.wireguardautotunnel.service.tile
-import android.content.Intent
-import android.os.IBinder
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleOwner
-import androidx.lifecycle.LifecycleRegistry
-import androidx.lifecycle.lifecycleScope
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
import com.zaneschepke.wireguardautotunnel.module.ApplicationScope
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
-import timber.log.Timber
import javax.inject.Inject
@AndroidEntryPoint
-class AutoTunnelControlTile : TileService(), LifecycleOwner {
+class AutoTunnelControlTile : TileService() {
@Inject
lateinit var appDataRepository: AppDataRepository
@@ -29,32 +23,26 @@ class AutoTunnelControlTile : TileService(), LifecycleOwner {
@ApplicationScope
lateinit var applicationScope: CoroutineScope
- private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)
-
override fun onCreate() {
super.onCreate()
- lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
- }
-
- override fun onStopListening() {
- lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
+ serviceManager.autoTunnelTile.complete(this)
}
override fun onDestroy() {
super.onDestroy()
- lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+ serviceManager.autoTunnelTile = CompletableDeferred()
}
override fun onStartListening() {
super.onStartListening()
- lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)
- lifecycleScope.launch {
+ serviceManager.autoTunnelTile.complete(this)
+ applicationScope.launch {
if (appDataRepository.tunnels.getAll().isEmpty()) return@launch setUnavailable()
updateTileState()
}
}
- private fun updateTileState() {
+ fun updateTileState() {
serviceManager.autoTunnelActive.value.let {
if (it) setActive() else setInactive()
}
@@ -63,7 +51,7 @@ class AutoTunnelControlTile : TileService(), LifecycleOwner {
override fun onClick() {
super.onClick()
unlockAndRun {
- lifecycleScope.launch {
+ applicationScope.launch {
if (serviceManager.autoTunnelActive.value) {
serviceManager.stopAutoTunnel()
setInactive()
@@ -95,18 +83,4 @@ class AutoTunnelControlTile : TileService(), LifecycleOwner {
qsTile.updateTile()
}
}
-
- /* This works around an annoying unsolved frameworks bug some people are hitting. */
- override fun onBind(intent: Intent): IBinder? {
- var ret: IBinder? = null
- try {
- ret = super.onBind(intent)
- } catch (_: Throwable) {
- Timber.e("Failed to bind to TunnelControlTile")
- }
- return ret
- }
-
- override val lifecycle: Lifecycle
- get() = lifecycleRegistry
}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt
index e672f9e..ad7cb02 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt
@@ -1,27 +1,22 @@
package com.zaneschepke.wireguardautotunnel.service.tile
-import android.content.Intent
import android.os.Build
-import android.os.IBinder
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleOwner
-import androidx.lifecycle.LifecycleRegistry
-import androidx.lifecycle.lifecycleScope
import com.zaneschepke.wireguardautotunnel.data.domain.TunnelConfig
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
import com.zaneschepke.wireguardautotunnel.module.ApplicationScope
+import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
import com.zaneschepke.wireguardautotunnel.service.tunnel.TunnelService
import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
-import timber.log.Timber
import javax.inject.Inject
import javax.inject.Provider
@AndroidEntryPoint
-class TunnelControlTile : TileService(), LifecycleOwner {
+class TunnelControlTile : TileService() {
@Inject
lateinit var appDataRepository: AppDataRepository
@@ -32,33 +27,29 @@ class TunnelControlTile : TileService(), LifecycleOwner {
@ApplicationScope
lateinit var applicationScope: CoroutineScope
- private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)
+ @Inject
+ lateinit var serviceManager: ServiceManager
override fun onCreate() {
super.onCreate()
- lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
- }
-
- override fun onStopListening() {
- lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
+ serviceManager.tunnelControlTile.complete(this)
}
override fun onDestroy() {
super.onDestroy()
- lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+ serviceManager.tunnelControlTile = CompletableDeferred()
}
override fun onStartListening() {
super.onStartListening()
- lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)
- Timber.d("Updating tile!")
- lifecycleScope.launch {
+ serviceManager.tunnelControlTile.complete(this)
+ applicationScope.launch {
if (appDataRepository.tunnels.getAll().isEmpty()) return@launch setUnavailable()
updateTileState()
}
}
- private suspend fun updateTileState() {
+ fun updateTileState() = applicationScope.launch {
val lastActive = appDataRepository.getStartTunnelConfig()
lastActive?.let {
updateTile(it)
@@ -68,7 +59,7 @@ class TunnelControlTile : TileService(), LifecycleOwner {
override fun onClick() {
super.onClick()
unlockAndRun {
- lifecycleScope.launch {
+ applicationScope.launch {
val lastActive = appDataRepository.getStartTunnelConfig()
lastActive?.let { tunnel ->
if (tunnel.isActive) {
@@ -125,18 +116,4 @@ class TunnelControlTile : TileService(), LifecycleOwner {
}
}
}
-
- /* This works around an annoying unsolved frameworks bug some people are hitting. */
- override fun onBind(intent: Intent): IBinder? {
- var ret: IBinder? = null
- try {
- ret = super.onBind(intent)
- } catch (_: Throwable) {
- Timber.e("Failed to bind to TunnelControlTile")
- }
- return ret
- }
-
- override val lifecycle: Lifecycle
- get() = lifecycleRegistry
}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt
index dd10821..a5de289 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt
@@ -9,6 +9,7 @@ import com.zaneschepke.wireguardautotunnel.module.ApplicationScope
import com.zaneschepke.wireguardautotunnel.module.IoDispatcher
import com.zaneschepke.wireguardautotunnel.module.Kernel
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
+import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService
import com.zaneschepke.wireguardautotunnel.service.tunnel.statistics.AmneziaStatistics
import com.zaneschepke.wireguardautotunnel.service.tunnel.statistics.TunnelStatistics
import com.zaneschepke.wireguardautotunnel.service.tunnel.statistics.WireGuardStatistics
@@ -41,6 +42,7 @@ constructor(
@ApplicationScope private val applicationScope: CoroutineScope,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
private val serviceManager: ServiceManager,
+ private val notificationService: NotificationService,
) : TunnelService {
private val _vpnState = MutableStateFlow(VpnState())
@@ -161,9 +163,7 @@ constructor(
}
callback()
}
- is Backend -> {
- callback()
- }
+ is Backend -> callback()
}
}
@@ -181,9 +181,7 @@ constructor(
is org.amnezia.awg.backend.Backend -> {
backend.backendState.asBackendState()
}
- is Backend -> {
- BackendState.SERVICE_ACTIVE
- }
+ is Backend -> BackendState.SERVICE_ACTIVE
else -> BackendState.INACTIVE
}
}
@@ -213,12 +211,12 @@ constructor(
private suspend fun startBackgroundService() {
serviceManager.startBackgroundService()
- serviceManager.requestTunnelTileUpdate()
+ serviceManager.updateTunnelTile()
}
- private fun stopBackgroundService() {
+ private suspend fun stopBackgroundService() {
serviceManager.stopBackgroundService()
- serviceManager.requestTunnelTileUpdate()
+ serviceManager.updateTunnelTile()
}
private suspend fun onBeforeStart(background: Boolean) {
@@ -320,14 +318,14 @@ constructor(
_vpnState.update {
it.copy(status = TunnelState.from(newState))
}
- serviceManager.requestTunnelTileUpdate()
+ serviceManager.updateTunnelTile()
}
override fun onStateChange(state: State) {
_vpnState.update {
it.copy(status = TunnelState.from(state))
}
- serviceManager.requestTunnelTileUpdate()
+ serviceManager.updateTunnelTile()
}
companion object {
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt
index d5d0bc3..c96912d 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt
@@ -159,18 +159,7 @@ constructor(
}
fun onToggleAutoTunnel() = viewModelScope.launch {
- val settings = appDataRepository.settings.getSettings()
- val toggled = !settings.isAutoTunnelEnabled
- if (toggled) {
- serviceManager.startAutoTunnel(false)
- } else {
- serviceManager.stopAutoTunnel()
- }
- appDataRepository.settings.save(
- settings.copy(
- isAutoTunnelEnabled = toggled,
- ),
- )
+ serviceManager.toggleAutoTunnel(false)
}
private suspend fun saveTunnelsFromZipUri(uri: Uri, context: Context) {
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/appearance/language/LanguageScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/appearance/language/LanguageScreen.kt
index 131e6cf..1746353 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/appearance/language/LanguageScreen.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/appearance/language/LanguageScreen.kt
@@ -50,7 +50,7 @@ fun LanguageScreen(appUiState: AppUiState, appViewModel: AppViewModel) {
modifier =
Modifier
.fillMaxSize().padding(padding)
- .padding(horizontal = 24.dp.scaledWidth())
+ .padding(horizontal = 24.dp.scaledWidth()),
) {
item {
Box(modifier = Modifier.padding(top = 24.dp.scaledHeight())) {
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/autotunnel/AutoTunnelScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/autotunnel/AutoTunnelScreen.kt
index 1afc971..d6536f9 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/autotunnel/AutoTunnelScreen.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/autotunnel/AutoTunnelScreen.kt
@@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 1c8c1bb..bbd33fa 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -81,7 +81,6 @@
Version
Einstellungen
Unterstützung
- Wächterkanal
Authentifizierung fehlgeschlagen
Konfigurationen exportieren
Unbekannter Fehler aufgetreten
@@ -99,7 +98,6 @@
Als Primären Tunnel setzen
VPN Kanal
VPN Benachrichtigungskanal
- Wächterbenachrichtigungskanal
Aktion erfordert deaktivierten Tunnel
Kernel
Kernelmodul verwenden
@@ -171,4 +169,4 @@
Wildcards für Namen verwenden
Auto-Tunnel stoppen
Überwache Statusänderungen
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index f728098..fadb178 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -101,10 +101,8 @@
WG Tunnel
Canal VPN
Canal de notificación VPN
- Canal del obvervador
- Canal de notificación del obvervador
- La monitorización SSID Wi-Fi necesita de permiso de ubicación en segundo plano incluso si la app está cerrada. Mira el enlace a la Política de Privacidad en la pantalla de ayuda para más detalles.
+ La monitorización SSID Wi-Fi necesita de permiso de ubicación en segundo plano incluso si la app está cerrada. Mira el enlace a la Política de Privacidad en la pantalla de ayuda para más detalles.
Recuento de paquetes basura
Tamaño mínimo del paquete basura
Agregar desde el portapapeles
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 94df80e..25fcb63 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -1,8 +1,6 @@
Canal VPN
- Canal de surveillance
- Canal de notification de surveillance
Cette action nécessite la désactivation du tunnel
Aucun tunnel n\'a été ajouté pour le moment !
Tunnels
@@ -171,4 +169,4 @@
Noyau non supporté
Démarrer l\'auto-tunnel
Cette modification nécessite un redémarrage de l\'application. Voulez-vous continuer ?
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml
index 3b07fb2..281b9b8 100644
--- a/app/src/main/res/values-in/strings.xml
+++ b/app/src/main/res/values-in/strings.xml
@@ -6,7 +6,6 @@
Kernel
Ukuran sampah paket init
WG Tunnel
- Notifikasi Saluran Pengamat
File bukan .conf atau .zip
Aksi memerlukan tunnel mati
Belum ada tunnel yang ditambahkan!
@@ -99,7 +98,6 @@
handshake
Saluran VPN
Notifikasi Saluran VPN
- Saluran Pengamat
Fitur ini memerlukan izin lokasi latar belakang untuk mengaktifkan pemantauan SSID Wi-Fi bahkan saat aplikasi ditutup. Untuk detail lebih lanjut, silakan lihat Kebijakan Privasi yang ditautkan di layar Dukungan.
Salin kunci publik
kunci base64
@@ -117,4 +115,4 @@
Buat pin
Ditetapkan sebagai tunnel data seluler
Ditetapkan sebagai tunnel utama
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index 059c32f..d232539 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -15,8 +15,6 @@
Icoon
Meenemen
Adres
- Watcher Kanaal
- Watcher Notificatiekanaal
Peer (extern systeem)
Allowed IPs
Altijd-aan VPN toestaan
@@ -138,4 +136,4 @@
De app kan geen ingeschakelde locatieservices op je apparaat vinden. Afhankelijk van het type apparaat kan dit leiden tot een niet functionerende herkenning van het verbonden WiFi netwerk. De niet-vertrouwde WiFi functionaliteit werkt daardoor mogelijk niet. Toch doorgaan?
Permanente achtergrondtoegang tot exacte locatie is vereist voor deze functie. Bekijk aub de
Transport packet magic header
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml
index 63561b2..800967c 100644
--- a/app/src/main/res/values-pt-rPT/strings.xml
+++ b/app/src/main/res/values-pt-rPT/strings.xml
@@ -99,8 +99,6 @@
WG Tunnel
Canal de VPN
Canal de notificações VPN
- Canal de vigia
- Canal de notificações de vigia
Este recurso precisa de permissões de localização em segundo plano para ativar o monitoramento do SSID da rede Wi-Fi mesmo quando a aplicação está fechado. Para mais pormenores, por favor veja a Política de Privacidade no ecrã de Suporte.
Envie o SSID
Adicionar a partir de ficheiro ou zip
@@ -132,4 +130,4 @@
guia de início rápido
para ter certeza que VPN Sempre-ligada é desligada para todas as outras aplicações e tente novamente
Reiniciar no arranque
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index af028ba..14e8909 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -110,8 +110,6 @@
Formato de configuração inválido
Canal de VPN
Canal de notificações VPN
- Canal de vigia
- Canal de notificações de vigia
wg-tunnel-db
Definir ip ping personalizado
Permissão negada
@@ -130,4 +128,4 @@
handshake
Permitir que toda a permissão de localização do tempo e/ou localização precisa é necessária para este recurso. Por favor, veja
seg
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index a8a6f89..481ea04 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -63,8 +63,6 @@
WG Tunnel
Канал VPN
Канал уведомлений VPN
- Канал наблюдателя
- Канал уведомлений наблюдателя
Туннели
Хорошо
Фоновая передача местоположения
@@ -171,4 +169,4 @@
Отслеживание изменений состояния
Включить ведение журнала
Добавить из буфера обмена
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index f305881..e0f2421 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -3,8 +3,6 @@
WG Tunnel
VPN Kanalı
VPN Bildirim Kanalı
- İzleyici Kanalı
- İzleyici Bildirim Kanalı
https://github.com/zaneschepke/wgtunnel/issues
https://zaneschepke.com/wgtunnel-docs/overview.html
https://zaneschepke.com/wgtunnel-docs/privacypolicy.html
@@ -124,4 +122,4 @@
başlangıç kılavuzu
Geçersiz tünel yapılandırma formatı
Önyüklemede yeniden başlat
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index fc7db67..ff7f4f8 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -97,12 +97,10 @@
没有安装浏览器
密码不正确
自定义 Ping 的目标 ip
- 守护者通知频道
VPN 频道
无效包计数
WG Tunnel
VPN 通知频道
- 守护者频道
查看问题
查看日志
(自动)
@@ -171,4 +169,4 @@
开启本地日志
配置更改
此更改需要重新启动应用程序。您是否要继续?
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fafc672..7117deb 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2,9 +2,7 @@
WG Tunnel
VPN Channel
VPN Notification Channel
- Watcher Channel
- Watcher Notification Channel
- https://github.com/zaneschepke/wgtunnel/issues
+ https://github.com/zaneschepke/wgtunnel/issues
https://zaneschepke.com/wgtunnel-docs/overview.html
https://zaneschepke.com/wgtunnel-docs/privacypolicy.html
https://zaneschepke.com/wgtunnel-docs/features.html#wildcard-wi-fi-name-support
@@ -82,7 +80,7 @@
No file explorer installed
Invalid QR code
The app is not detecting any location services enabled on your device. Depending on the device, this could cause the untrusted wifi feature to fail to read the wifi name. Would you like to continue anyways?
- Auto-tunnel Service
+ Auto-tunnel service
Delete tunnel
Are you sure you would like to delete this tunnel?
Yes
@@ -187,4 +185,9 @@
Kill switch options
Allow LAN traffic
Bypass LAN for kill switch
+ A channel for VPN state notifications
+ Auto-tunnel Channel
+ Auto-tunnel Notification Channel
+ A channel for auto-tunnel state notifications
+ stop