new method to detect default network
This commit is contained in:
6 files changed
+92
-75
No files matched your search
@@ -114,8 +114,7 @@ class ClashNotification(private val context: ClashService, enableRefresh: Boolea
|
||||
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
Log.d("Clash Notification Stopped")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ import android.os.IBinder
|
||||
import com.github.kr328.clash.core.Clash
|
||||
import com.github.kr328.clash.service.data.ClashDatabase
|
||||
import com.github.kr328.clash.service.util.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
|
||||
class ClashService : BaseService() {
|
||||
@@ -98,7 +100,7 @@ class ClashService : BaseService() {
|
||||
}
|
||||
|
||||
private suspend fun reloadProfile() {
|
||||
if ( !loadLock.tryLock() )
|
||||
if (!loadLock.tryLock())
|
||||
return
|
||||
|
||||
try {
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.github.kr328.clash.core.utils.Log
|
||||
import com.github.kr328.clash.service.net.DefaultNetworkChannel
|
||||
import com.github.kr328.clash.service.util.broadcastNetworkChanged
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.broadcast
|
||||
import java.net.InetAddress
|
||||
|
||||
class TunService : VpnService(), CoroutineScope by MainScope() {
|
||||
@@ -71,18 +70,22 @@ class TunService : VpnService(), CoroutineScope by MainScope() {
|
||||
|
||||
Log.i("Network changed to ${d?.second}")
|
||||
|
||||
if ( d == null ) {
|
||||
if (d == null) {
|
||||
setUnderlyingNetworks(null)
|
||||
continue
|
||||
}
|
||||
|
||||
setUnderlyingNetworks(arrayOf(d.first))
|
||||
|
||||
if ( settings.get(Settings.AUTO_ADD_SYSTEM_DNS) ) {
|
||||
if (settings.get(Settings.AUTO_ADD_SYSTEM_DNS)) {
|
||||
withContext(Dispatchers.Default) {
|
||||
Clash.appendDns(d.second.dnsServers
|
||||
.map(InetAddress::getHostName)
|
||||
.filter(String::isNotBlank))
|
||||
val dnsServers = d.second?.dnsServers ?: emptyList()
|
||||
|
||||
Clash.appendDns(
|
||||
dnsServers
|
||||
.map(InetAddress::getHostName)
|
||||
.filter(String::isNotBlank)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
package com.github.kr328.clash.service.data
|
||||
|
||||
import androidx.room.*
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
|
||||
@Entity(
|
||||
tableName = "profile_select_proxies",
|
||||
|
||||
@@ -1,29 +1,41 @@
|
||||
// from https://github.com/shadowsocks/shadowsocks-android/blob/master/core/src/main/java/com/github/shadowsocks/net/DefaultNetworkListener.kt
|
||||
package com.github.kr328.clash.service.net
|
||||
|
||||
import android.content.Context
|
||||
import android.net.*
|
||||
import com.github.kr328.clash.core.utils.Log
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
|
||||
class DefaultNetworkChannel(val context: Context, scope: CoroutineScope) :
|
||||
CoroutineScope by scope, Channel<Pair<Network, LinkProperties>?> by Channel(Channel.CONFLATED) {
|
||||
CoroutineScope by scope,
|
||||
Channel<Pair<Network, LinkProperties?>?> by Channel(Channel.CONFLATED) {
|
||||
private val sendLock = Mutex()
|
||||
private val connectivity = context.getSystemService(ConnectivityManager::class.java)!!
|
||||
private val callback = object : ConnectivityManager.NetworkCallback() {
|
||||
var current: Network? = null
|
||||
private val capabilitiesCache = mutableMapOf<Network, NetworkCapabilities?>()
|
||||
|
||||
override fun onLost(network: Network) {
|
||||
if ( current == network )
|
||||
offer(null)
|
||||
override fun onAvailable(network: Network) {
|
||||
sendDefaultNetwork()
|
||||
}
|
||||
|
||||
override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) {
|
||||
if ( linkProperties.routes.any { it.isDefaultRoute } ) {
|
||||
offer(network to linkProperties)
|
||||
current = network
|
||||
}
|
||||
override fun onLost(network: Network) {
|
||||
sendDefaultNetwork()
|
||||
|
||||
capabilitiesCache.remove(network)
|
||||
}
|
||||
|
||||
override fun onCapabilitiesChanged(
|
||||
network: Network,
|
||||
networkCapabilities: NetworkCapabilities?
|
||||
) {
|
||||
val cap = capabilitiesCache[network]
|
||||
|
||||
if (cap?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||
!= networkCapabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||
)
|
||||
sendDefaultNetwork()
|
||||
|
||||
capabilitiesCache[network] = networkCapabilities
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,54 +47,55 @@ class DefaultNetworkChannel(val context: Context, scope: CoroutineScope) :
|
||||
connectivity.unregisterNetworkCallback(callback)
|
||||
}
|
||||
|
||||
// private fun sendDefaultNetwork() {
|
||||
// if (detectDelayLock.tryLock()) {
|
||||
// launch {
|
||||
// delay(1000)
|
||||
//
|
||||
// val network = detectDefaultNetwork()
|
||||
// val linkProperties = network?.let { connectivity.getLinkProperties(it) }
|
||||
//
|
||||
// if ( network != null && linkProperties != null )
|
||||
// send(network to linkProperties)
|
||||
// else
|
||||
// send(null)
|
||||
//
|
||||
// detectDelayLock.unlock()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private suspend fun detectDefaultNetwork(): Network? = withContext(Dispatchers.Default) {
|
||||
// return@withContext try {
|
||||
// connectivity.allNetworks
|
||||
// .asSequence()
|
||||
// .mapNotNull { network ->
|
||||
// connectivity.getNetworkCapabilities(network)?.let { it to network }
|
||||
// }
|
||||
// .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 {
|
||||
// it.second
|
||||
// }
|
||||
// .firstOrNull()
|
||||
// } catch (e: Exception) {
|
||||
// null
|
||||
// }
|
||||
// }
|
||||
private fun sendDefaultNetwork() {
|
||||
if (!sendLock.tryLock())
|
||||
return
|
||||
|
||||
launch {
|
||||
delay(1000)
|
||||
|
||||
val network = detectDefaultNetwork()
|
||||
val link = network?.let(connectivity::getLinkProperties)
|
||||
|
||||
if (network != null)
|
||||
send(network to link)
|
||||
else
|
||||
send(null)
|
||||
|
||||
sendLock.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun detectDefaultNetwork() = withContext(Dispatchers.Default) {
|
||||
try {
|
||||
connectivity.allNetworks
|
||||
.asSequence()
|
||||
.mapNotNull { network ->
|
||||
connectivity.getNetworkCapabilities(network)?.let { it to network }
|
||||
}
|
||||
.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 {
|
||||
it.second
|
||||
}
|
||||
.firstOrNull()
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,7 @@ package com.github.kr328.clash.service.util
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.github.kr328.clash.service.Intents
|
||||
import com.github.kr328.clash.service.data.ClashDatabase
|
||||
import com.github.kr328.clash.service.data.ClashProfileEntity
|
||||
import com.github.kr328.clash.service.data.ClashProfileProxyEntity
|
||||
|
||||
fun Context.sendBroadcastSelf(intent: Intent) {
|
||||
this.sendBroadcast(intent.setPackage(this.packageName))
|
||||
|
||||
Reference in new issue
Block a user