Improve: disable network observer on screen off

This commit is contained in:
kr328 2021-11-16 20:23:54 +08:00
parent a3686c16d4
commit c7cb1dab38

View File

@ -1,14 +1,16 @@
package com.github.kr328.clash.service.clash.module
import android.app.Service
import android.content.Intent
import android.net.*
import android.os.Build
import android.os.PowerManager
import androidx.core.content.getSystemService
import com.github.kr328.clash.common.log.Log
import com.github.kr328.clash.core.Clash
import com.github.kr328.clash.service.util.resolveDns
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.selects.select
import kotlinx.coroutines.withContext
class NetworkObserveModule(service: Service) :
@ -18,23 +20,9 @@ class NetworkObserveModule(service: Service) :
private val connectivity = service.getSystemService<ConnectivityManager>()!!
private val networks: Channel<Network?> = Channel(Channel.CONFLATED)
private val request = NetworkRequest.Builder().apply {
addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
addTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH)
addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
if (Build.VERSION.SDK_INT >= 26)
addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
if (Build.VERSION.SDK_INT >= 27)
addTransportType(NetworkCapabilities.TRANSPORT_LOWPAN)
if (Build.VERSION.SDK_INT >= 31)
addTransportType(NetworkCapabilities.TRANSPORT_USB)
if (Build.VERSION.SDK_INT == 23) { // workarounds for OEM bugs
removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
removeCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)
}
}.build()
private val callback = object : ConnectivityManager.NetworkCallback() {
@ -53,30 +41,70 @@ class NetworkObserveModule(service: Service) :
}
}
override suspend fun run() {
try {
private fun register(): Boolean {
return try {
connectivity.registerNetworkCallback(request, callback)
true
} catch (e: Exception) {
Log.w("Observe network changed: $e", e)
return
false
}
}
private fun unregister(): Boolean {
try {
connectivity.unregisterNetworkCallback(callback)
} catch (e: Exception) {
// ignored
}
return false
}
override suspend fun run() {
val screenToggle = receiveBroadcast(false, Channel.CONFLATED) {
addAction(Intent.ACTION_SCREEN_ON)
addAction(Intent.ACTION_SCREEN_OFF)
}
if (service.getSystemService<PowerManager>()?.isInteractive != false) {
register()
}
try {
while (true) {
val network = networks.receive()
val quit = select<Boolean> {
screenToggle.onReceive {
when (it.action) {
Intent.ACTION_SCREEN_ON ->
register()
Intent.ACTION_SCREEN_OFF ->
unregister()
else ->
false
}
}
networks.onReceive {
val dns = connectivity.resolveDns(it)
val dns = connectivity.resolveDns(network)
Clash.notifyDnsChanged(dns)
Clash.notifyDnsChanged(dns)
Log.d("Network changed, system dns = $dns")
Log.d("Network changed, system dns = $dns")
enqueueEvent(NetworkChanged(it))
enqueueEvent(NetworkChanged(network))
false
}
}
if (quit) {
return
}
}
} finally {
withContext(NonCancellable) {
connectivity.unregisterNetworkCallback(callback)
unregister()
Clash.notifyDnsChanged(emptyList())
}