From 456c853923aba4740b22934c29f87445c77b4f69 Mon Sep 17 00:00:00 2001 From: Kr328 <39107975+Kr328@users.noreply.github.com> Date: Tue, 26 Nov 2019 00:48:01 +0800 Subject: [PATCH] new default network observer --- .../github/kr328/clash/service/TunService.kt | 3 +- .../service/net/DefaultNetworkObserver.kt | 82 +++++++++++++------ 2 files changed, 59 insertions(+), 26 deletions(-) diff --git a/service/src/main/java/com/github/kr328/clash/service/TunService.kt b/service/src/main/java/com/github/kr328/clash/service/TunService.kt index dc69d51..d5b5706 100644 --- a/service/src/main/java/com/github/kr328/clash/service/TunService.kt +++ b/service/src/main/java/com/github/kr328/clash/service/TunService.kt @@ -8,6 +8,7 @@ import android.content.ServiceConnection import android.net.VpnService import android.os.* import com.github.kr328.clash.core.event.* +import com.github.kr328.clash.core.utils.Log import com.github.kr328.clash.service.net.DefaultNetworkObserver class TunService : VpnService(), IClashEventObserver { @@ -65,7 +66,7 @@ class TunService : VpnService(), IClashEventObserver { bindService(Intent(this, ClashService::class.java), connection, Context.BIND_AUTO_CREATE) defaultNetworkObserver = DefaultNetworkObserver(this) { - setUnderlyingNetworks(it?.run { arrayOf(this) }) + setUnderlyingNetworks(it?.run { arrayOf(it) }) } defaultNetworkObserver.register() diff --git a/service/src/main/java/com/github/kr328/clash/service/net/DefaultNetworkObserver.kt b/service/src/main/java/com/github/kr328/clash/service/net/DefaultNetworkObserver.kt index 877e8cd..31de7b4 100644 --- a/service/src/main/java/com/github/kr328/clash/service/net/DefaultNetworkObserver.kt +++ b/service/src/main/java/com/github/kr328/clash/service/net/DefaultNetworkObserver.kt @@ -7,54 +7,86 @@ import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest import android.os.Handler +import com.github.kr328.clash.core.utils.Log +import java.lang.Exception class DefaultNetworkObserver(val context: Context, val listener: (Network?) -> Unit) { private val handler = Handler() private val connectivity = context.getSystemService(ConnectivityManager::class.java)!! - private var blocking: Boolean = true - private var current: Network? = null private val callback = object: ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { - if ( blocking ) - return - - current = network - - listener(current) + handler.removeMessages(0) + handler.postDelayed({ + listener(rebuildNetworkList()) + }, 500) } override fun onLost(network: Network) { - if ( blocking ) - return - - if ( current == network ) - current = null - - listener(current) + handler.removeMessages(0) + handler.postDelayed({ + listener(rebuildNetworkList()) + }, 500) } override fun onCapabilitiesChanged( network: Network, networkCapabilities: NetworkCapabilities ) { - if ( blocking ) - return - - if ( network == current ) - listener(current) + handler.removeMessages(0) + handler.postDelayed({ + listener(rebuildNetworkList()) + }, 500) } } fun register() { connectivity.registerNetworkCallback(NetworkRequest.Builder().build(), callback) - - handler.postDelayed({ - blocking = false - listener(connectivity.activeNetwork) - }, 3000) } fun unregister() { connectivity.unregisterNetworkCallback(callback) } + + private fun rebuildNetworkList(): Network? { + return try { + connectivity.allNetworks + .map { + connectivity.getNetworkCapabilities(it) to it + } + .filter { + it.first != null + } + .map { + it.first!! to it.second + } + .filterNot { + it.first.hasTransport(NetworkCapabilities.TRANSPORT_VPN) || + !it.first.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + } + .sortedBy { + when { + it.first.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> 0 + it.first.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> 1 + it.first.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> 2 + it.first.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN) -> 3 + it.first.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> 4 + else -> 5 + } + if ( it.first.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) ) + -1000 + else + 0 + } + .map { + Log.i("Network ${it.first}") + it + } + .map { + it.second + } + .firstOrNull() + } + catch (e: Exception) { + null + } + } } \ No newline at end of file