Add device count to other tiles too
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
package be.mygod.vpnhotspot.manage
|
||||
|
||||
import android.service.quicksettings.Tile
|
||||
import androidx.annotation.RequiresApi
|
||||
import be.mygod.vpnhotspot.R
|
||||
import be.mygod.vpnhotspot.net.IpNeighbour
|
||||
import be.mygod.vpnhotspot.net.monitor.IpNeighbourMonitor
|
||||
import be.mygod.vpnhotspot.util.KillableTileService
|
||||
|
||||
@RequiresApi(24)
|
||||
abstract class IpNeighbourMonitoringTileService : KillableTileService(), IpNeighbourMonitor.Callback {
|
||||
private var neighbours: Collection<IpNeighbour> = emptyList()
|
||||
abstract fun updateTile()
|
||||
|
||||
override fun onStartListening() {
|
||||
super.onStartListening()
|
||||
IpNeighbourMonitor.registerCallback(this)
|
||||
}
|
||||
|
||||
override fun onStopListening() {
|
||||
IpNeighbourMonitor.unregisterCallback(this)
|
||||
super.onStopListening()
|
||||
}
|
||||
|
||||
protected fun Tile.subtitleDevices(filter: (String) -> Boolean) {
|
||||
val size = neighbours
|
||||
.filter { it.state != IpNeighbour.State.FAILED && filter(it.dev) }
|
||||
.distinctBy { it.lladdr }
|
||||
.size
|
||||
if (size > 0) subtitle(resources.getQuantityString(
|
||||
R.plurals.quick_settings_hotspot_secondary_label_num_devices, size, size))
|
||||
}
|
||||
|
||||
override fun onIpNeighbourAvailable(neighbours: Collection<IpNeighbour>) {
|
||||
this.neighbours = neighbours
|
||||
updateTile()
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,10 @@ import android.service.quicksettings.Tile
|
||||
import androidx.annotation.RequiresApi
|
||||
import be.mygod.vpnhotspot.LocalOnlyHotspotService
|
||||
import be.mygod.vpnhotspot.R
|
||||
import be.mygod.vpnhotspot.util.KillableTileService
|
||||
import be.mygod.vpnhotspot.util.stopAndUnbind
|
||||
|
||||
@RequiresApi(26)
|
||||
class LocalOnlyHotspotTileService : KillableTileService() {
|
||||
class LocalOnlyHotspotTileService : IpNeighbourMonitoringTileService() {
|
||||
private val tile by lazy { Icon.createWithResource(application, R.drawable.ic_action_perm_scan_wifi) }
|
||||
|
||||
private var binder: LocalOnlyHotspotService.Binder? = null
|
||||
@@ -28,6 +27,24 @@ class LocalOnlyHotspotTileService : KillableTileService() {
|
||||
super.onStopListening()
|
||||
}
|
||||
|
||||
override fun updateTile() {
|
||||
val binder = binder ?: return
|
||||
qsTile?.run {
|
||||
icon = tile
|
||||
subtitle(null)
|
||||
val iface = binder.iface
|
||||
if (iface.isNullOrEmpty()) {
|
||||
state = Tile.STATE_INACTIVE
|
||||
label = getText(R.string.tethering_temp_hotspot)
|
||||
} else {
|
||||
state = Tile.STATE_ACTIVE
|
||||
label = binder.configuration?.ssid ?: getText(R.string.tethering_temp_hotspot)
|
||||
subtitleDevices { it == iface }
|
||||
}
|
||||
updateTile()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick() {
|
||||
val binder = binder
|
||||
when {
|
||||
@@ -39,19 +56,7 @@ class LocalOnlyHotspotTileService : KillableTileService() {
|
||||
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
binder = service as LocalOnlyHotspotService.Binder
|
||||
service.ifaceChanged[this] = {
|
||||
qsTile?.run {
|
||||
icon = tile
|
||||
if (it.isNullOrEmpty()) {
|
||||
state = Tile.STATE_INACTIVE
|
||||
label = getText(R.string.tethering_temp_hotspot)
|
||||
} else {
|
||||
state = Tile.STATE_ACTIVE
|
||||
label = service.configuration?.ssid ?: getText(R.string.tethering_temp_hotspot)
|
||||
}
|
||||
updateTile()
|
||||
}
|
||||
}
|
||||
service.ifaceChanged[this] = { updateTile() }
|
||||
super.onServiceConnected(name, service)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import be.mygod.vpnhotspot.net.TetherType
|
||||
import be.mygod.vpnhotspot.net.TetheringManager
|
||||
import be.mygod.vpnhotspot.net.TetheringManager.tetheredIfaces
|
||||
import be.mygod.vpnhotspot.net.wifi.WifiApManager
|
||||
import be.mygod.vpnhotspot.util.KillableTileService
|
||||
import be.mygod.vpnhotspot.util.broadcastReceiver
|
||||
import be.mygod.vpnhotspot.util.readableMessage
|
||||
import be.mygod.vpnhotspot.util.stopAndUnbind
|
||||
@@ -26,14 +25,14 @@ import java.io.IOException
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
|
||||
@RequiresApi(24)
|
||||
sealed class TetheringTileService : KillableTileService(), TetheringManager.StartTetheringCallback {
|
||||
sealed class TetheringTileService : IpNeighbourMonitoringTileService(), TetheringManager.StartTetheringCallback {
|
||||
protected val tileOff by lazy { Icon.createWithResource(application, icon) }
|
||||
protected val tileOn by lazy { Icon.createWithResource(application, R.drawable.ic_quick_settings_tile_on) }
|
||||
|
||||
protected abstract val labelString: Int
|
||||
protected abstract val tetherType: TetherType
|
||||
protected open val icon get() = tetherType.icon
|
||||
protected var tethered: List<String>? = null
|
||||
private var tethered: List<String>? = null
|
||||
protected val interested get() = tethered?.filter { TetherType.ofInterface(it) == tetherType }
|
||||
protected var binder: TetheringService.Binder? = null
|
||||
|
||||
@@ -73,8 +72,9 @@ sealed class TetheringTileService : KillableTileService(), TetheringManager.Star
|
||||
binder = null
|
||||
}
|
||||
|
||||
protected open fun updateTile() {
|
||||
override fun updateTile() {
|
||||
qsTile?.run {
|
||||
subtitle(null)
|
||||
val interested = interested
|
||||
when {
|
||||
interested == null -> {
|
||||
@@ -89,6 +89,7 @@ sealed class TetheringTileService : KillableTileService(), TetheringManager.Star
|
||||
val binder = binder ?: return
|
||||
state = Tile.STATE_ACTIVE
|
||||
icon = if (interested.all(binder::isActive)) tileOn else tileOff
|
||||
subtitleDevices(interested::contains)
|
||||
}
|
||||
}
|
||||
label = getText(labelString)
|
||||
@@ -172,6 +173,7 @@ sealed class TetheringTileService : KillableTileService(), TetheringManager.Star
|
||||
|
||||
override fun updateTile() {
|
||||
qsTile?.run {
|
||||
subtitle(null)
|
||||
val interested = interested
|
||||
if (interested == null) {
|
||||
state = Tile.STATE_UNAVAILABLE
|
||||
@@ -181,6 +183,7 @@ sealed class TetheringTileService : KillableTileService(), TetheringManager.Star
|
||||
val binder = binder ?: return
|
||||
state = Tile.STATE_ACTIVE
|
||||
icon = if (interested.isNotEmpty() && interested.all(binder::isActive)) tileOn else tileOff
|
||||
subtitleDevices(interested::contains)
|
||||
}
|
||||
false -> {
|
||||
state = Tile.STATE_INACTIVE
|
||||
|
||||
@@ -46,7 +46,8 @@ enum class TetherType(@DrawableRes val icon: Int) {
|
||||
.map { it.toPattern() }
|
||||
|
||||
@RequiresApi(30)
|
||||
private fun updateRegexs() {
|
||||
private fun updateRegexs() = synchronized(this) {
|
||||
if (!requiresUpdate) return@synchronized
|
||||
requiresUpdate = false
|
||||
TetheringManager.registerTetheringEventCallback(null, this)
|
||||
val tethering = "com.android.networkstack.tethering" to app.packageManager.getResourcesForApplication(
|
||||
@@ -59,7 +60,8 @@ enum class TetherType(@DrawableRes val icon: Int) {
|
||||
}
|
||||
|
||||
@RequiresApi(30)
|
||||
override fun onTetherableInterfaceRegexpsChanged(args: Array<out Any?>?) {
|
||||
override fun onTetherableInterfaceRegexpsChanged(args: Array<out Any?>?) = synchronized(this) {
|
||||
if (requiresUpdate) return@synchronized
|
||||
Timber.i("onTetherableInterfaceRegexpsChanged: ${args?.contentToString()}")
|
||||
TetheringManager.unregisterTetheringEventCallback(this)
|
||||
requiresUpdate = true
|
||||
@@ -92,6 +94,7 @@ enum class TetherType(@DrawableRes val icon: Int) {
|
||||
iface == null -> NONE
|
||||
iface == p2pDev -> WIFI_P2P
|
||||
requiresUpdate -> {
|
||||
Timber.d("requiresUpdate")
|
||||
if (Build.VERSION.SDK_INT >= 30) updateRegexs() else error("unexpected requiresUpdate")
|
||||
ofInterface(iface, p2pDev)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user