Skip to content

Commit 4c1c57a

Browse files
committed
Bind to the service in a coroutine to avoid a crash
1 parent 4227f4a commit 4c1c57a

File tree

1 file changed

+21
-23
lines changed

1 file changed

+21
-23
lines changed

android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt

+21-23
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ import androidx.activity.ComponentActivity
99
import androidx.activity.compose.setContent
1010
import androidx.activity.result.contract.ActivityResultContracts
1111
import androidx.core.view.WindowCompat
12+
import androidx.lifecycle.Lifecycle
13+
import androidx.lifecycle.lifecycleScope
14+
import androidx.lifecycle.repeatOnLifecycle
1215
import kotlinx.coroutines.flow.filterIsInstance
1316
import kotlinx.coroutines.flow.first
17+
import kotlinx.coroutines.launch
1418
import net.mullvad.mullvadvpn.compose.screen.MullvadApp
1519
import net.mullvad.mullvadvpn.di.paymentModule
1620
import net.mullvad.mullvadvpn.di.uiModule
@@ -60,46 +64,40 @@ class MainActivity : ComponentActivity() {
6064
super.onCreate(savedInstanceState)
6165

6266
setContent { AppTheme { MullvadApp() } }
63-
}
6467

65-
fun initializeStateHandlerAndServiceConnection() {
66-
requestNotificationPermissionIfMissing(requestNotificationPermissionLauncher)
67-
serviceConnectionManager.bind(
68-
vpnPermissionRequestHandler = ::requestVpnPermission,
69-
apiEndpointConfiguration = intent?.getApiEndpointConfigurationExtras()
70-
)
68+
// We use lifecycleScope here to get less start service in background exceptions
69+
// Se this article for more information:
70+
// https://medium.com/@lepicekmichal/android-background-service-without-hiccup-501e4479110f
71+
lifecycleScope.launch {
72+
repeatOnLifecycle(Lifecycle.State.STARTED) {
73+
if (privacyDisclaimerRepository.hasAcceptedPrivacyDisclosure()) {
74+
startServiceSuspend(waitForConnectedReady = false)
75+
}
76+
}
77+
}
7178
}
7279

73-
suspend fun startServiceSuspend() {
80+
suspend fun startServiceSuspend(waitForConnectedReady: Boolean = true) {
7481
requestNotificationPermissionIfMissing(requestNotificationPermissionLauncher)
7582
serviceConnectionManager.bind(
7683
vpnPermissionRequestHandler = ::requestVpnPermission,
7784
apiEndpointConfiguration = intent?.getApiEndpointConfigurationExtras()
7885
)
79-
// Ensure we wait until the service is ready
80-
serviceConnectionManager.connectionState
81-
.filterIsInstance<ServiceConnectionState.ConnectedReady>()
82-
.first()
86+
if (waitForConnectedReady) {
87+
// Ensure we wait until the service is ready
88+
serviceConnectionManager.connectionState
89+
.filterIsInstance<ServiceConnectionState.ConnectedReady>()
90+
.first()
91+
}
8392
}
8493

8594
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
8695
serviceConnectionManager.onVpnPermissionResult(resultCode == Activity.RESULT_OK)
8796
}
8897

89-
override fun onStart() {
90-
super.onStart()
91-
92-
if (privacyDisclaimerRepository.hasAcceptedPrivacyDisclosure()) {
93-
initializeStateHandlerAndServiceConnection()
94-
}
95-
}
96-
9798
override fun onStop() {
9899
Log.d("mullvad", "Stopping main activity")
99100
super.onStop()
100-
101-
// NOTE: `super.onStop()` must be called before unbinding due to the fragment state handling
102-
// otherwise the fragments will believe there was an unexpected disconnect.
103101
serviceConnectionManager.unbind()
104102
}
105103

0 commit comments

Comments
 (0)