检查Android中的VPN连接是否处于活动状态?

Dan*_*rgo 12 vpn monitoring android

我的非root用户Android 4.4设备上有第三方VPN应用程序,并且想要编写后台服务来监控VPN连接,并在VPN连接断开时提醒用户.

有没有办法做到这一点?我找不到任何使用VPNService API的方法.

感谢:D

小智 15

使用NetworkCapabilities对我有用.您必须遍历所有现有网络并检查哪些网络VPN_TRANSPORT

ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
Network[] networks = cm.getAllNetworks();

Log.i(TAG, "Network count: " + networks.length);
for(int i = 0; i < networks.length; i++) {

  NetworkCapabilities caps = cm.getNetworkCapabilities(networks[i]);

  Log.i(TAG, "Network " + i + ": " + networks[i].toString());
  Log.i(TAG, "VPN transport is: " + caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN));
  Log.i(TAG, "NOT_VPN capability is: " + caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN));

}
Run Code Online (Sandbox Code Playgroud)


小智 15

这对我有用:从API 16到23进行测试:

List<String> networkList = new ArrayList<>();
try {
    for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) {
        if (networkInterface.isUp())
            networkList.add(networkInterface.getName());
    }
} catch (Exception ex) {
    Timber.d("isVpnUsing Network List didn't received");
}

return networkList.contains("tun0");
Run Code Online (Sandbox Code Playgroud)

PS它也可以是另一个名为"ppp0"的networkInterface,但在我使用不同VPN应用程序的测试中,它始终是"tun0"

  • 这种变化.例如,当使用OpenVPN时,它会说*tunX*,其中X有时是递增的id.使用PPTP时,使用的接口是*pptpX*,其中X再次是从0开始的id. (2认同)

Ped*_*ito 14

迟到的答案,在 Android 上测试过16 <-> 29

public boolean vpn() {
    String iface = "";
    try {
        for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) {
            if (networkInterface.isUp())
                iface = networkInterface.getName();
                Log.d("DEBUG", "IFACE NAME: " + iface);
            if ( iface.contains("tun") || iface.contains("ppp") || iface.contains("pptp")) {
                return true;
            }
        }
    } catch (SocketException e1) {
        e1.printStackTrace();
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

以上不适用于wireguard,因为接口名称可以是任何内容(通常是连接名称)。


Ami*_*ebi 8

Here is kotlin coroutines flow solution

val isVpnActiveFlow = callbackFlow {
    val connectivityManager =
        context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
    if (connectivityManager == null) {
        channel.close(IllegalStateException("connectivity manager is null"))
        return@callbackFlow
    } else {
        val callback = object : ConnectivityManager.NetworkCallback() {
            override fun onAvailable(network: Network) {
                channel.trySend(true)
            }
            override fun onLost(network: Network) {
               channel.trySend(false)
            }
        }
        connectivityManager.registerNetworkCallback(

            //I have to investigate on this builder!
            NetworkRequest.Builder()
                    .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
                    .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
                    .build(),
            callback
        )
        awaitClose {
            connectivityManager.unregisterNetworkCallback(callback)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Alm*_*mer 6

检查活动网络是否正在使用 VPN 的替代方法:

Network activeNetwork = connectivityManager.getActiveNetwork();
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(activeNetwork);
boolean vpnInUse = caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
Run Code Online (Sandbox Code Playgroud)

  • 这才是问题的真正答案。应检查活动网络,而不是循环遍历所有网络。关键是要知道设备是否实际上正在使用 VPN 主动连接 (4认同)