Last active
April 26, 2023 14:42
-
-
Save gradlevv/49befe05431e19d5670a0cd6a3e33b5b to your computer and use it in GitHub Desktop.
Lifecycle-aware VPN detector
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Suppress("Deprecation") | |
private class LegacyVPNDetector( | |
private val context: Context, | |
connectivityManager: ConnectivityManager | |
) : VPNDetector(connectivityManager) { | |
private val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION) | |
private val isVPNConnected: Boolean | |
get() = checkVPNConnectivity() | |
private fun checkVPNConnectivity(): Boolean { | |
val networkList = mutableListOf<String>() | |
for (networkInterface in NetworkInterface.getNetworkInterfaces()) { | |
if (networkInterface.isUp) { | |
networkList.add(networkInterface.name) | |
} | |
} | |
return networkList.contains("tun0") | |
} | |
override fun startDetecting(callback: (Boolean) -> Unit) { | |
vpnCallback = callback | |
context.registerReceiver(receiver, filter) | |
} | |
override fun stopDetecting() { | |
context.unregisterReceiver(receiver) | |
vpnCallback = {} | |
} | |
private val receiver = object : BroadcastReceiver() { | |
override fun onReceive(context: Context?, intent: Intent?) { | |
vpnCallback(isVPNConnected) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private class MarshmallowVPNDetector(connectivityManager: ConnectivityManager) : | |
VPNDetector(connectivityManager) { | |
private val networkCallback = object : ConnectivityManager.NetworkCallback() { | |
override fun onCapabilitiesChanged( | |
network: Network, | |
networkCapabilities: NetworkCapabilities | |
) { | |
vpnCallback(networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) | |
} | |
} | |
override fun startDetecting(callback: (Boolean) -> Unit) { | |
vpnCallback = callback | |
connectivityManager.registerDefaultNetworkCallback(networkCallback) | |
} | |
override fun stopDetecting() { | |
connectivityManager.unregisterNetworkCallback(networkCallback) | |
vpnCallback = {} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package your.package.name | |
import androidx.lifecycle.MutableLiveData | |
class VPNConnectionListener constructor(context: Context) : MutableLiveData<VpnState>() { | |
private val vpnDetector = VPNDetector.getInstance(context.applicationContext) | |
override fun onActive() { | |
super.onActive() | |
vpnDetector.startDetecting(::checkState) | |
} | |
override fun onInactive() { | |
vpnDetector.stopDetecting() | |
super.onInactive() | |
} | |
private fun checkState(isConnected: Boolean) { | |
postValue(if (isConnected) VpnState.CONNECTED else VpnState.DISCONNECTED) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package your.package.name | |
import android.content.BroadcastReceiver | |
import android.content.Context | |
import android.content.Intent | |
import android.content.IntentFilter | |
import android.net.ConnectivityManager | |
import android.net.Network | |
import android.net.NetworkCapabilities | |
import android.os.Build | |
import java.net.NetworkInterface | |
internal abstract class VPNDetector(protected val connectivityManager: ConnectivityManager) { | |
protected var vpnCallback: ((Boolean) -> Unit) = {} | |
abstract fun startDetecting(callback: (Boolean) -> Unit) | |
abstract fun stopDetecting() | |
companion object { | |
fun getInstance(context: Context): VPNUtils { | |
val connectivityManager = | |
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager | |
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | |
MarshmallowVPNDetector(connectivityManager) | |
} else { | |
LegacyVPNDetector(context, connectivityManager) | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum class VpnState { | |
CONNECTED, DISCONNECTED | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment