fix: foreground service start crashes
Attempt to fix startForegrounService causing crashes on some devices by not meeting the 5 second notification rule. Add notification to onCreate of services. Limit startForeground to only be called where it is truly necessary in the TileService to allow starting the VPN while app is not running. Attempt to manually initialize mlkit for QR code scanning to remediate some crashes caused by config scanning.
This commit is contained in:
parent
c1b560e822
commit
64bb9f3b82
|
@ -17,7 +17,7 @@ android {
|
|||
|
||||
val versionMajor = 2
|
||||
val versionMinor = 4
|
||||
val versionPatch = 2
|
||||
val versionPatch = 3
|
||||
val versionBuild = 0
|
||||
|
||||
defaultConfig {
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.app.Application
|
|||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.google.mlkit.common.MlKit
|
||||
import com.zaneschepke.wireguardautotunnel.repository.Repository
|
||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
|
@ -22,6 +23,11 @@ class WireGuardAutoTunnel : Application() {
|
|||
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(false);
|
||||
Timber.plant(Timber.DebugTree())
|
||||
}
|
||||
try {
|
||||
MlKit.initialize(this)
|
||||
} catch (e : Exception) {
|
||||
Timber.e(e.message)
|
||||
}
|
||||
settingsRepo.init()
|
||||
}
|
||||
|
||||
|
|
|
@ -2,5 +2,6 @@ package com.zaneschepke.wireguardautotunnel.service.foreground
|
|||
|
||||
enum class Action {
|
||||
START,
|
||||
START_FOREGROUND,
|
||||
STOP
|
||||
}
|
|
@ -22,7 +22,7 @@ open class ForegroundService : Service() {
|
|||
val action = intent.action
|
||||
Timber.d("using an intent with action $action")
|
||||
when (action) {
|
||||
Action.START.name -> startService(intent.extras)
|
||||
Action.START.name, Action.START_FOREGROUND.name -> startService(intent.extras)
|
||||
Action.STOP.name -> stopService(intent.extras)
|
||||
"android.net.VpnService" -> {
|
||||
Timber.d("Always-on VPN starting service")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
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
|
||||
|
@ -9,7 +8,6 @@ import android.content.Intent
|
|||
import com.google.firebase.crashlytics.ktx.crashlytics
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import com.zaneschepke.wireguardautotunnel.R
|
||||
import timber.log.Timber
|
||||
|
||||
object ServiceManager {
|
||||
@Suppress("DEPRECATION")
|
||||
|
@ -36,13 +34,11 @@ object ServiceManager {
|
|||
intent.component?.javaClass
|
||||
try {
|
||||
when(action) {
|
||||
Action.START_FOREGROUND -> {
|
||||
context.startForegroundService(intent)
|
||||
}
|
||||
Action.START -> {
|
||||
try {
|
||||
context.startForegroundService(intent)
|
||||
} catch (e : Exception) {
|
||||
Timber.e("Unable to start service foreground ${e.message}")
|
||||
context.startService(intent)
|
||||
}
|
||||
context.startService(intent)
|
||||
}
|
||||
Action.STOP -> context.startService(intent)
|
||||
}
|
||||
|
@ -66,6 +62,22 @@ object ServiceManager {
|
|||
)
|
||||
}
|
||||
|
||||
fun startVpnServiceForeground(context : Context, tunnelConfig : String) {
|
||||
actionOnService(
|
||||
Action.START_FOREGROUND,
|
||||
context,
|
||||
WireGuardTunnelService::class.java,
|
||||
mapOf(context.getString(R.string.tunnel_extras_key) to tunnelConfig))
|
||||
}
|
||||
|
||||
private fun startWatcherServiceForeground(context : Context, tunnelConfig : String) {
|
||||
actionOnService(
|
||||
Action.START, context,
|
||||
WireGuardConnectivityWatcherService::class.java, mapOf(context.
|
||||
getString(R.string.tunnel_extras_key) to
|
||||
tunnelConfig))
|
||||
}
|
||||
|
||||
fun startWatcherService(context : Context, tunnelConfig : String) {
|
||||
actionOnService(
|
||||
Action.START, context,
|
||||
|
@ -87,4 +99,12 @@ object ServiceManager {
|
|||
ServiceState.STOPPED -> startWatcherService(context, tunnelConfig)
|
||||
}
|
||||
}
|
||||
|
||||
fun toggleWatcherServiceForeground(context: Context, tunnelConfig : String) {
|
||||
when(getServiceState( context,
|
||||
WireGuardConnectivityWatcherService::class.java,)) {
|
||||
ServiceState.STARTED -> stopWatcherService(context)
|
||||
ServiceState.STOPPED -> startWatcherServiceForeground(context, tunnelConfig)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,8 +59,16 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
|
|||
private val tag = this.javaClass.name;
|
||||
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
launchWatcherNotification()
|
||||
}
|
||||
}
|
||||
|
||||
override fun startService(extras: Bundle?) {
|
||||
super.startService(extras)
|
||||
launchWatcherNotification()
|
||||
val tunnelId = extras?.getString(getString(R.string.tunnel_extras_key))
|
||||
if (tunnelId != null) {
|
||||
this.tunnelConfig = tunnelId
|
||||
|
@ -68,7 +76,6 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
|
|||
// we need this lock so our service gets not affected by Doze Mode
|
||||
initWakeLock()
|
||||
cancelWatcherJob()
|
||||
launchWatcherNotification()
|
||||
if(this::tunnelConfig.isInitialized) {
|
||||
startWatcherJob()
|
||||
} else {
|
||||
|
@ -181,7 +188,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
|
|||
}
|
||||
|
||||
private suspend fun manageVpn() {
|
||||
while(watcherJob.isActive) {
|
||||
while(true) {
|
||||
if(setting.isTunnelOnMobileDataEnabled &&
|
||||
!isWifiConnected &&
|
||||
isMobileDataConnected
|
||||
|
|
|
@ -37,8 +37,16 @@ class WireGuardTunnelService : ForegroundService() {
|
|||
|
||||
private var tunnelName : String = ""
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
launchVpnStartingNotification()
|
||||
}
|
||||
}
|
||||
|
||||
override fun startService(extras : Bundle?) {
|
||||
super.startService(extras)
|
||||
launchVpnStartingNotification()
|
||||
val tunnelConfigString = extras?.getString(getString(R.string.tunnel_extras_key))
|
||||
cancelJob()
|
||||
job = CoroutineScope(Dispatchers.IO).launch {
|
||||
|
@ -47,7 +55,6 @@ class WireGuardTunnelService : ForegroundService() {
|
|||
val tunnelConfig = TunnelConfig.from(tunnelConfigString)
|
||||
tunnelName = tunnelConfig.name
|
||||
vpnService.startTunnel(tunnelConfig)
|
||||
launchVpnStartingNotification()
|
||||
} catch (e : Exception) {
|
||||
Timber.e("Problem starting tunnel: ${e.message}")
|
||||
stopService(extras)
|
||||
|
@ -61,7 +68,6 @@ class WireGuardTunnelService : ForegroundService() {
|
|||
val tunnelConfig = TunnelConfig.from(setting.defaultTunnel!!)
|
||||
tunnelName = tunnelConfig.name
|
||||
vpnService.startTunnel(tunnelConfig)
|
||||
launchVpnStartingNotification()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +106,7 @@ class WireGuardTunnelService : ForegroundService() {
|
|||
|
||||
override fun stopService(extras : Bundle?) {
|
||||
super.stopService(extras)
|
||||
CoroutineScope(Dispatchers.IO).launch() {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
vpnService.stopTunnel()
|
||||
}
|
||||
cancelJob()
|
||||
|
|
|
@ -66,7 +66,7 @@ class TunnelControlTile : TileService() {
|
|||
if(vpnService.getState() == Tunnel.State.UP) {
|
||||
ServiceManager.stopVpnService(this@TunnelControlTile)
|
||||
} else {
|
||||
ServiceManager.startVpnService(this@TunnelControlTile, tunnel.toString())
|
||||
ServiceManager.startVpnServiceForeground(this@TunnelControlTile, tunnel.toString())
|
||||
}
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
|
@ -100,7 +100,7 @@ class TunnelControlTile : TileService() {
|
|||
if (!settings.isNullOrEmpty()) {
|
||||
val setting = settings.first()
|
||||
if(setting.isAutoTunnelEnabled) {
|
||||
ServiceManager.toggleWatcherService(this@TunnelControlTile, tunnelConfig)
|
||||
ServiceManager.toggleWatcherServiceForeground(this@TunnelControlTile, tunnelConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
|
@ -103,6 +102,7 @@ fun MainScreen(
|
|||
val state by viewModel.state.collectAsStateWithLifecycle(Tunnel.State.DOWN)
|
||||
val tunnelName by viewModel.tunnelName.collectAsStateWithLifecycle("")
|
||||
|
||||
|
||||
// Nested scroll for control FAB
|
||||
val nestedScrollConnection = remember {
|
||||
object : NestedScrollConnection {
|
||||
|
@ -242,7 +242,8 @@ fun MainScreen(
|
|||
) {
|
||||
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.nestedScroll(nestedScrollConnection),
|
||||
) {
|
||||
itemsIndexed(tunnels.toList()) { index, tunnel ->
|
||||
|
|
|
@ -13,7 +13,7 @@ buildscript {
|
|||
}
|
||||
|
||||
plugins {
|
||||
id("com.android.application") version "8.2.0-beta01" apply false
|
||||
id("com.android.application") version "8.2.0-beta03" apply false
|
||||
id("org.jetbrains.kotlin.android") version "1.8.22" apply false
|
||||
id("com.google.dagger.hilt.android") version "2.44" apply false
|
||||
kotlin("plugin.serialization") version "1.8.22" apply false
|
||||
|
|
Loading…
Reference in New Issue