11package com.masterdns.vpn.service
22
3+ import android.content.Intent
4+ import android.net.VpnService
35import android.os.Build
46import android.service.quicksettings.Tile
57import android.service.quicksettings.TileService
68import androidx.annotation.RequiresApi
9+ import com.masterdns.vpn.MainActivity
710import com.masterdns.vpn.R
11+ import com.masterdns.vpn.data.local.AppDatabase
812import com.masterdns.vpn.util.VpnManager
13+ import kotlinx.coroutines.CoroutineScope
14+ import kotlinx.coroutines.Dispatchers
15+ import kotlinx.coroutines.SupervisorJob
16+ import kotlinx.coroutines.cancel
17+ import kotlinx.coroutines.launch
918
1019@RequiresApi(Build .VERSION_CODES .N )
1120class VpnTileService : TileService () {
1221
22+ private val tileScope = CoroutineScope (SupervisorJob () + Dispatchers .Main )
23+
1324 override fun onStartListening () {
1425 super .onStartListening()
1526 updateTile()
@@ -18,15 +29,48 @@ class VpnTileService : TileService() {
1829 override fun onClick () {
1930 super .onClick()
2031 val state = VpnManager .state.value
21- if (state == VpnManager .VpnState .CONNECTED ) {
22- VpnManager .disconnect(this )
23- } else if (state == VpnManager .VpnState .DISCONNECTED ) {
24- // Can't start VPN from tile without VPN permission
25- // Just update the tile state
32+ when (state) {
33+ VpnManager .VpnState .CONNECTED -> VpnManager .disconnect(this )
34+ VpnManager .VpnState .DISCONNECTED -> connectFromTileIfReady()
35+ else -> Unit
2636 }
2737 updateTile()
2838 }
2939
40+ override fun onDestroy () {
41+ tileScope.cancel()
42+ super .onDestroy()
43+ }
44+
45+ private fun connectFromTileIfReady () {
46+ val prepareIntent = VpnService .prepare(this )
47+ if (prepareIntent != null ) {
48+ startActivityAndCollapse(prepareIntent.addFlags(Intent .FLAG_ACTIVITY_NEW_TASK ))
49+ return
50+ }
51+
52+ tileScope.launch(Dispatchers .IO ) {
53+ val selectedProfile = AppDatabase .getInstance(this @VpnTileService)
54+ .profileDao()
55+ .getSelectedProfile()
56+
57+ launch(Dispatchers .Main ) {
58+ if (selectedProfile != null ) {
59+ VpnManager .connect(this @VpnTileService, selectedProfile)
60+ updateTile()
61+ } else {
62+ openApp()
63+ }
64+ }
65+ }
66+ }
67+
68+ private fun openApp () {
69+ val intent = Intent (this , MainActivity ::class .java)
70+ .addFlags(Intent .FLAG_ACTIVITY_NEW_TASK )
71+ startActivityAndCollapse(intent)
72+ }
73+
3074 private fun updateTile () {
3175 val tile = qsTile ? : return
3276 when (VpnManager .state.value) {
0 commit comments