How to detect programatically if traffic is going through VPN without using intent to connect to VPNService. Is there some system call?
This works :
private boolean checkVPN() {
ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getNetworkInfo(ConnectivityManager.TYPE_VPN).isConnectedOrConnecting();
}
It is possible to check it in Android API 21 an higher, but it seems doesn't work (on nexus 5 @ 5.0.1, nexus 7 @ 5.0.2). Why its not working?
Snippet of new API for check it (and all traffic is routed by vpn if connected):
@Inject
boolean checkVPN(ConnectivityManager connMgr) {
//don't know why always returns null:
NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_VPN);
boolean isVpnConn = networkInfo == null ? false : networkInfo.isConnected();
return isVpnConn;
}
The Android OS is aware of when a VPN connection is active (as it shows an icon in the status bar for the duration of a VPN connection) but there is no public API method (which would appear on the VpnService) to check for an active connection.
Two solutions occur. If you are dealing with a specific situation where you know the network topology, run 'ping' to see if a particular IP address is available - use System.exec
. the ping command is present on Android devices with stock ROMs, I've used it as part of a solution to to provide a more granular view of the state of a data connection (ip address not allocated, ip address allocated but can't access the internet, can access the internet)
A better solution would be to run a traceroute instead and analyse the output. I've not checked if traceroute is present on Android devices with stock ROMs, I'll edit this answer later with more complete information.
You can detect VPN with following code in android. Code will work in new and older version of android. Below code is in Kotlin.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if(checkVPNStatus()) {
Log.d("VPN-RAJ", "is VPN Connected YES")
} else {
Log.d("VPN-RAJ", "is VPN Connected NO")
}
}
private fun checkVPNStatus(): Boolean {
val connectivityManager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
val network = connectivityManager.activeNetwork
val capabilities = connectivityManager.getNetworkCapabilities(network)
Log.d("VPN-RAJ", "in New Android Version")
capabilities!= null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
} else {
Log.d("VPN-RAJ", "in Old Android Version")
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_VPN)!!.isConnectedOrConnecting
}
}
}
I guess for most use-cases you want to check if the actively used network is using VPN instead of if just any network available is using VPN.
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_VPN)
... is returning a NetworkInfo for an available VPN Network. This might not be the active Network! Instead you could use the following snippet to test if the active Network is using VPN:
Network activeNetwork = connectivityManager.getActiveNetwork();
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(activeNetwork);
boolean vpnInUse = caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
Nothing worked for me so i created my own. It's workin for me on Android 11 (although deprecated)
static boolean checkVpn(Context context){
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
for(NetworkInfo o:cm.getAllNetworkInfo()){
if(o.getTypeName().toLowerCase().contains("vpn")&&o.isConnected()){
return true;
}
}
return false;
}
© 2022 - 2024 — McMap. All rights reserved.