diff --git a/mobile/src/main/AndroidManifest.xml b/mobile/src/main/AndroidManifest.xml
index f20ffba0..a3452401 100644
--- a/mobile/src/main/AndroidManifest.xml
+++ b/mobile/src/main/AndroidManifest.xml
@@ -34,6 +34,9 @@
+
+
+
@@ -41,9 +44,9 @@
diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterTileService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterTileService.kt
new file mode 100644
index 00000000..3637dbe6
--- /dev/null
+++ b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterTileService.kt
@@ -0,0 +1,85 @@
+package be.mygod.vpnhotspot
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
+import android.graphics.drawable.Icon
+import android.os.IBinder
+import android.service.quicksettings.Tile
+import android.service.quicksettings.TileService
+import android.support.annotation.RequiresApi
+import android.support.v4.content.ContextCompat
+import android.support.v4.content.LocalBroadcastManager
+import be.mygod.vpnhotspot.net.VpnMonitor
+
+@RequiresApi(24)
+class RepeaterTileService : TileService(), ServiceConnection, VpnMonitor.Callback {
+ private val statusListener = broadcastReceiver { _, _ -> updateTile() }
+ private val tileOff by lazy { Icon.createWithResource(application, R.drawable.ic_quick_settings_tile_off) }
+ private val tileOn by lazy { Icon.createWithResource(application, R.drawable.ic_quick_settings_tile_on) }
+
+ private var binder: RepeaterService.RepeaterBinder? = null
+
+ override fun onStartListening() {
+ super.onStartListening()
+ bindService(Intent(this, RepeaterService::class.java), this, Context.BIND_AUTO_CREATE)
+ }
+
+ override fun onStopListening() {
+ super.onStopListening()
+ unbindService(this)
+ }
+
+ override fun onClick() {
+ val binder = binder
+ when (binder?.service?.status) {
+ RepeaterService.Status.ACTIVE -> binder.shutdown()
+ RepeaterService.Status.IDLE ->
+ ContextCompat.startForegroundService(this, Intent(this, RepeaterService::class.java))
+ else -> { }
+ }
+ }
+
+ override fun onServiceConnected(name: ComponentName?, service: IBinder) {
+ binder = service as RepeaterService.RepeaterBinder
+ updateTile()
+ VpnMonitor.registerCallback(this)
+ LocalBroadcastManager.getInstance(this).registerReceiver(statusListener,
+ intentFilter(RepeaterService.ACTION_STATUS_CHANGED))
+ }
+
+ override fun onServiceDisconnected(name: ComponentName?) {
+ binder = null
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(statusListener)
+ VpnMonitor.unregisterCallback(this)
+ }
+
+ private fun updateTile() {
+ when (if (VpnMonitor.available.isEmpty()) null else binder?.service?.status) {
+ RepeaterService.Status.IDLE -> {
+ qsTile.state = Tile.STATE_INACTIVE
+ qsTile.icon = tileOff
+ qsTile.label = getString(R.string.title_repeater)
+ }
+ RepeaterService.Status.STARTING -> {
+ qsTile.state = Tile.STATE_UNAVAILABLE
+ qsTile.icon = tileOn
+ qsTile.label = getString(R.string.title_repeater)
+ }
+ RepeaterService.Status.ACTIVE -> {
+ qsTile.state = Tile.STATE_ACTIVE
+ qsTile.icon = tileOn
+ qsTile.label = binder?.service?.ssid
+ }
+ null -> {
+ qsTile.state = Tile.STATE_UNAVAILABLE
+ qsTile.icon = tileOff
+ qsTile.label = getString(R.string.title_repeater)
+ }
+ }
+ qsTile.updateTile()
+ }
+ override fun onAvailable(ifname: String) = updateTile()
+ override fun onLost(ifname: String) = updateTile()
+}
diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/TileService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/TileService.kt
deleted file mode 100644
index bbe1f3b4..00000000
--- a/mobile/src/main/java/be/mygod/vpnhotspot/TileService.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-package be.mygod.vpnhotspot
-
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.content.ServiceConnection
-import android.graphics.drawable.Icon
-import android.os.Build
-import android.os.IBinder
-import android.service.quicksettings.Tile
-import android.support.annotation.RequiresApi
-import android.support.v4.content.ContextCompat
-import android.support.v4.content.LocalBroadcastManager
-import android.service.quicksettings.TileService as BaseTileService
-
-@RequiresApi(Build.VERSION_CODES.N)
-class TileService : BaseTileService(), ServiceConnection {
- private var binder: RepeaterService.RepeaterBinder? = null
-
- val onStatusChangedReceive = broadcastReceiver { _, _ ->
- updateTile()
- }
-
- var qsTileState: Int
- get() = qsTile.state
- set(value) {
- qsTile.state = value
- when (value) {
- Tile.STATE_ACTIVE -> {
- qsTile.icon = Icon.createWithResource(application,
- R.drawable.ic_quick_settings_tile_on)
- qsTile.label = "${getString(R.string.repeater_password)}:\n${binder?.service?.password}"
- }
- Tile.STATE_INACTIVE -> {
- qsTile.icon = Icon.createWithResource(application,
- R.drawable.ic_quick_settings_tile_off)
- qsTile.label = getString(R.string.app_name)
- }
- }
- qsTile.updateTile()
- }
-
- override fun onStartListening() {
- super.onStartListening()
- bindService(Intent(this, RepeaterService::class.java), this,
- Context.BIND_AUTO_CREATE)
- }
-
- override fun onStopListening() {
- super.onStopListening()
- unbindService(this)
- }
-
- override fun onClick() {
- val binder = binder
- when (binder?.service?.status) {
- RepeaterService.Status.ACTIVE -> binder.shutdown()
- RepeaterService.Status.IDLE -> ContextCompat.startForegroundService(this,
- Intent(this, RepeaterService::class.java))
- else -> {
- }
- }
- }
-
- override fun onServiceConnected(name: ComponentName?, service: IBinder) {
- binder = service as RepeaterService.RepeaterBinder
- updateTile()
- LocalBroadcastManager.getInstance(this).registerReceiver(onStatusChangedReceive,
- intentFilter(RepeaterService.ACTION_STATUS_CHANGED))
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
- binder = null
- LocalBroadcastManager.getInstance(this).unregisterReceiver(onStatusChangedReceive)
- }
-
- fun updateTile() {
- qsTileState = when (binder?.service?.status) {
- RepeaterService.Status.ACTIVE -> Tile.STATE_ACTIVE
- RepeaterService.Status.IDLE -> Tile.STATE_INACTIVE
- else -> Tile.STATE_UNAVAILABLE
- }
- }
-}
diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/VpnMonitor.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/VpnMonitor.kt
index 19fef160..d41ba434 100644
--- a/mobile/src/main/java/be/mygod/vpnhotspot/net/VpnMonitor.kt
+++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/VpnMonitor.kt
@@ -27,7 +27,7 @@ object VpnMonitor : ConnectivityManager.NetworkCallback() {
/**
* Obtaining ifname in onLost doesn't work so we need to cache it in onAvailable.
*/
- private val available = HashMap()
+ val available = HashMap()
override fun onAvailable(network: Network) {
val ifname = manager.getLinkProperties(network)?.interfaceName ?: return
if (available.put(network, ifname) != null) return
diff --git a/mobile/src/main/res/drawable/ic_quick_settings_tile_on.xml b/mobile/src/main/res/drawable/ic_quick_settings_tile_on.xml
index e0cfecb4..4a858b04 100644
--- a/mobile/src/main/res/drawable/ic_quick_settings_tile_on.xml
+++ b/mobile/src/main/res/drawable/ic_quick_settings_tile_on.xml
@@ -11,7 +11,7 @@
L21.78,13.78 L23.56,13.78 L23.56,10.22 Z M9.36,13.78 A1.78,1.78,0,1,1,11.11,12
A1.78,1.78,0,0,1,9.33,13.78 Z" />