Skip to content

Commit 613defa

Browse files
feat(android): connect from quick settings tile (#20)
1 parent 64e1b6a commit 613defa

1 file changed

Lines changed: 49 additions & 5 deletions

File tree

android/app/src/main/java/com/masterdns/vpn/service/VpnTileService.kt

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
11
package com.masterdns.vpn.service
22

3+
import android.content.Intent
4+
import android.net.VpnService
35
import android.os.Build
46
import android.service.quicksettings.Tile
57
import android.service.quicksettings.TileService
68
import androidx.annotation.RequiresApi
9+
import com.masterdns.vpn.MainActivity
710
import com.masterdns.vpn.R
11+
import com.masterdns.vpn.data.local.AppDatabase
812
import 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)
1120
class 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

Comments
 (0)