检查 Android 中是否有 VPN 连接?
Check if a VPN connection is active in Android?
我的无根 Android 4.4 设备上有一个第三方 VPN 应用程序,我想编写一个后台服务来监控 VPN 连接并在 VPN 连接断开时提醒用户。
有办法吗?我找不到任何使用 VPNService API.
的方法
谢谢-D
编写一个点击内部页面或 ping 内部站点的小应用程序...
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(internal_url);
HttpResponse response = client.execute(request);
String html = "";
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder str = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null)
{
str.append(line);
}
in.close();
html = str.toString();
或
String str = "";
try
{
Process process = Runtime.getRuntime().exec(
"/system/bin/ping -c 8 " + internal_url);
BufferedReader reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
int i;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((i = reader.read(buffer)) > 0)
output.append(buffer, 0, i);
reader.close();
str = output.toString();
}
catch (IOException e)
{
e.printStackTrace();
}
return str;
使用 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));
}
这对我有用:
从 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");
P.S。它也可以是另一个名称为 "ppp0" 的网络接口,但在我对不同 VPN 应用程序的测试中,它始终是 "tun0"
查看网络信息如何?如果有一种 VPN,我会假设有 VPN 连接。
需要 ACCESS_NETWORK_STATE 权限。
List<NetworkInfo> connectedNetworks = new ArrayList<>();
if (Build.VERSION.SDK_INT >= 21)
{
Network[] networks = m_ConnectivityManager.getAllNetworks();
for (Network n : networks)
{
NetworkInfo ni = m_ConnectivityManager.getNetworkInfo(n);
if (ni.isConnectedOrConnecting())
{
connectedNetworks.add(ni);
}
}
}
else
{
NetworkInfo[] nis = m_ConnectivityManager.getAllNetworkInfo();
for (NetworkInfo ni : nis)
{
if (ni.isConnectedOrConnecting())
{
connectedNetworks.add(ni);
}
}
}
boolean bHasVPN = false;
if (Build.VERSION.SDK_INT >= 21)
{
for (NetworkInfo ni : connectedNetworks)
{
bHasVPN |= (ni.getType() == ConnectivityManager.TYPE_VPN);
}
}
检查活动网络是否正在使用 VPN 的替代方法:
Network activeNetwork = connectivityManager.getActiveNetwork();
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(activeNetwork);
boolean vpnInUse = caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
迟到的答案,在 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;
}
以上不适用于 wireguard,因为接口名称可以是任何名称(通常是连接名称)。
我为自己编写了一个可以工作的辅助函数 API 21 岁及以上。
public static boolean vpnActive(Context context){
//this method doesn't work below API 21
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
return false;
boolean vpnInUse = false;
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Network activeNetwork = connectivityManager.getActiveNetwork();
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(activeNetwork);
return caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
}
Network[] networks = connectivityManager.getAllNetworks();
for(int i = 0; i < networks.length; i++) {
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(networks[i]);
if(caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
vpnInUse = true;
break;
}
}
return vpnInUse;
}
我的无根 Android 4.4 设备上有一个第三方 VPN 应用程序,我想编写一个后台服务来监控 VPN 连接并在 VPN 连接断开时提醒用户。
有办法吗?我找不到任何使用 VPNService API.
的方法谢谢-D
编写一个点击内部页面或 ping 内部站点的小应用程序...
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(internal_url);
HttpResponse response = client.execute(request);
String html = "";
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder str = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null)
{
str.append(line);
}
in.close();
html = str.toString();
或
String str = "";
try
{
Process process = Runtime.getRuntime().exec(
"/system/bin/ping -c 8 " + internal_url);
BufferedReader reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
int i;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((i = reader.read(buffer)) > 0)
output.append(buffer, 0, i);
reader.close();
str = output.toString();
}
catch (IOException e)
{
e.printStackTrace();
}
return str;
使用 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));
}
这对我有用: 从 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");
P.S。它也可以是另一个名称为 "ppp0" 的网络接口,但在我对不同 VPN 应用程序的测试中,它始终是 "tun0"
查看网络信息如何?如果有一种 VPN,我会假设有 VPN 连接。
需要 ACCESS_NETWORK_STATE 权限。
List<NetworkInfo> connectedNetworks = new ArrayList<>();
if (Build.VERSION.SDK_INT >= 21)
{
Network[] networks = m_ConnectivityManager.getAllNetworks();
for (Network n : networks)
{
NetworkInfo ni = m_ConnectivityManager.getNetworkInfo(n);
if (ni.isConnectedOrConnecting())
{
connectedNetworks.add(ni);
}
}
}
else
{
NetworkInfo[] nis = m_ConnectivityManager.getAllNetworkInfo();
for (NetworkInfo ni : nis)
{
if (ni.isConnectedOrConnecting())
{
connectedNetworks.add(ni);
}
}
}
boolean bHasVPN = false;
if (Build.VERSION.SDK_INT >= 21)
{
for (NetworkInfo ni : connectedNetworks)
{
bHasVPN |= (ni.getType() == ConnectivityManager.TYPE_VPN);
}
}
检查活动网络是否正在使用 VPN 的替代方法:
Network activeNetwork = connectivityManager.getActiveNetwork();
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(activeNetwork);
boolean vpnInUse = caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
迟到的答案,在 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;
}
以上不适用于 wireguard,因为接口名称可以是任何名称(通常是连接名称)。
我为自己编写了一个可以工作的辅助函数 API 21 岁及以上。
public static boolean vpnActive(Context context){
//this method doesn't work below API 21
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
return false;
boolean vpnInUse = false;
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Network activeNetwork = connectivityManager.getActiveNetwork();
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(activeNetwork);
return caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
}
Network[] networks = connectivityManager.getAllNetworks();
for(int i = 0; i < networks.length; i++) {
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(networks[i]);
if(caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
vpnInUse = true;
break;
}
}
return vpnInUse;
}