fix metered vpn

This commit is contained in:
Kr328 committed 2019-11-23 03:44:23 +08:00
1 parent 600537af9c
commit 838d492334
2 files changed
+70 -20

No files matched your search

@@ -8,6 +8,7 @@ import android.os.IBinder
import android.os.ParcelFileDescriptor
import android.util.Log
import com.github.kr328.clash.core.ClashProcessStatus
import com.github.kr328.clash.service.net.DefaultNetworkObserver
class TunService : VpnService() {
companion object {
@@ -28,11 +29,11 @@ class TunService : VpnService() {
private const val PRIVATE_VLAN6_CLIENT = "fdfe:dcba:9876::1"
}
private var fileDescriptor: ParcelFileDescriptor? = null
private var clash: IClashService? = null
private lateinit var fileDescriptor: ParcelFileDescriptor
private lateinit var clash: IClashService
private lateinit var defaultNetworkObserver: DefaultNetworkObserver
private val connection = object: ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
clash = null
stopSelf()
}
@@ -66,16 +67,7 @@ class TunService : VpnService() {
this@TunService.clash = clash
}
}
private val networkChangedCallback = object: ConnectivityManager.NetworkCallback() {
override fun onCapabilitiesChanged(
network: Network,
networkCapabilities: NetworkCapabilities
) {
val connectivity = getSystemService(ConnectivityManager::class.java)!!
setUnderlyingNetworks(connectivity.activeNetwork?.run { arrayOf(this) })
}
}
override fun onCreate() {
super.onCreate()
@@ -94,13 +86,19 @@ class TunService : VpnService() {
.addRoute("::", 0)
.setMtu(VPN_MTU)
.setBlocking(false)
.setUnderlyingNetworks(null)
.setMeteredCompat(false)
.establish() ?: throw NullPointerException("Unable to establish VPN")
bindService(Intent(this, ClashService::class.java), connection, Context.BIND_AUTO_CREATE)
getSystemService(ConnectivityManager::class.java)!!
.registerDefaultNetworkCallback(networkChangedCallback)
defaultNetworkObserver = DefaultNetworkObserver(this) {
val data = getSystemService(ConnectivityManager::class.java)!!.getNetworkCapabilities(it)
Log.d(TAG, "Network $data")
setUnderlyingNetworks(it?.run { arrayOf(this) })
}
defaultNetworkObserver.register()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
@@ -110,15 +108,14 @@ class TunService : VpnService() {
}
override fun onDestroy() {
fileDescriptor?.close()
fileDescriptor.close()
clash?.stopTunDevice()
clash?.stop()
clash.stopTunDevice()
clash.stop()
unbindService(connection)
getSystemService(ConnectivityManager::class.java)!!
.unregisterNetworkCallback(networkChangedCallback)
defaultNetworkObserver.unregister()
super.onDestroy()
}
@@ -129,4 +126,10 @@ class TunService : VpnService() {
}
return this
}
private fun Builder.setMeteredCompat(isMetered: Boolean): Builder {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
setMetered(isMetered)
return this
}
}
@@ -0,0 +1,47 @@
// 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.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
class DefaultNetworkObserver(val context: Context, val listener: (Network?) -> Unit) {
private val connectivity = context.getSystemService(ConnectivityManager::class.java)!!
private val active: Network?
get() = connectivity.activeNetwork
private var current: Network? = null
private val callback = object: ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
current = active
listener(current)
}
override fun onCapabilitiesChanged(
network: Network,
networkCapabilities: NetworkCapabilities
) {
if ( current == active )
listener(active)
}
override fun onLost(network: Network) {
if ( active == current )
current = null
listener(current)
}
}
fun register() {
listener(active)
connectivity.registerDefaultNetworkCallback(callback)
}
fun unregister() {
connectivity.unregisterNetworkCallback(callback)
}
}