在android上检测USB网络共享
Posted
技术标签:
【中文标题】在android上检测USB网络共享【英文标题】:Detect USB tethering on android 【发布时间】:2011-11-22 12:30:20 【问题描述】:有什么方法可以在您的活动/应用程序中(以编程方式)知道用户已在他的手机上启用 USB 网络共享?
【问题讨论】:
【参考方案1】:您可以像这样获取网络接口并检查处于活动状态的内容:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
NetworkInterface rndis = null;
NetworkInterface wlan = null;
while(interfaces.hasMoreElements())
NetworkInterface nif = interfaces.nextElement();
if(hasIP4Address(nif))
if(nif.getDisplayName().startsWith("rndis"))
rndis = nif;
else if (nif.getDisplayName().startsWith("wlan"))
wlan = nif;
// Let the user choose Wi-Fi or rndis connect
if (rndis != null)
socket.setNetworkInterface(rndis);
Log.i(TAG, "Subscribe: with interface rndis");
else if(wlan != null)
socket.setNetworkInterface(wlan);
Log.i(TAG, "Subscribe: with interface wlan");
【讨论】:
【参考方案2】:这应该适用于所有手机,并在某些 android 7,6 和 5 设备上得到确认;
方法:接口 rndisX(通常为 rndis0)仅在启用 USB 共享时显示。
代码示例:
private static boolean isTetheringActive(Context context)
try
for(Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();)
NetworkInterface intf=en.nextElement();
for(Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();)
InetAddress inetAddress=enumIpAddr.nextElement();
if(!intf.isLoopback())
if(intf.getName().contains("rndis"))
return true;
catch(Exception e)e.printStackTrace();
return false;
【讨论】:
【参考方案3】:这是一个监听网络共享状态变化的解决方案:
首先您需要熟悉广播接收器。 你可以找到很多教程(谷歌:如何监听连接变化......)
为了获得 Tethering 状态更新,您需要使用 Android 的隐藏过滤器操作(请参阅 ConnectivityManager)
在你的 BroadcastReceiver 类中:
IntentFilter filter = new IntentFilter("android.net.conn.TETHER_STATE_CHANGED");
然后将过滤器注册到您的广播接收器:
myApplicationContext.registerReceiver(this, filter);
在您的 onReceive(final Context context,final Intent intent) 方法中,Intent.extras 信息包含 3 个数组,其中填充了相应的系留网络接口: erroredArray / availableArray / activeArray
这有点棘手,但您可以获取网络共享状态信息。
另外,你可以对Android代码的隐藏功能做一些反思:
在连接管理器中搜索getTetherableIfaces()
。
这是一个链接:https://github.com/android/platform_frameworks_base/blob/master/core/java/android/net/ConnectivityManager.java#L1604
【讨论】:
请注意,从 Android 8(API 级别 26)开始,EXTRA_ACTIVE_TETHER
的值是 "tetherArray" 而不是“activeArray”(在 BroadcastReceiver
的 onReceive()
中检索收到的附加信息将为“activeArray”键返回一个空字符串数组)【参考方案4】:
我发现如果我检查 usb0 网络接口 一旦设置了网络共享,它就只有一个 IP 地址。
public static String getIPAddressUsb(final boolean useIPv4)
try
final List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
for (final NetworkInterface intf : interfaces)
if (intf.getDisplayName().startsWith("usb"))
final List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
for (final InetAddress addr : addrs)
final String sAddr = addr.getHostAddress().toUpperCase();
final boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
if (useIPv4)
if (isIPv4) return sAddr;
else
if (!isIPv4)
final int delim = sAddr.indexOf('%');
return delim < 0 ? sAddr : sAddr.substring(0, delim);
catch (final Exception ex)
// for now eat exceptions
return "";
boolean isUsbTethered()
String ipAddr = MipnAndroidApplication.getIPAddressUsb(true);
if (ipAddr.length() == 0)
Log.i(LOG_TAG, "tethering not enabled");
return false;
else
Log.i(LOG_TAG, "tethering enabled :)");
return true;
【讨论】:
这确实有效。即使我知道我已经启动并运行了网络共享,我仍然会收到“网络共享未启用”的消息 是的,您可能需要一个新的解决方案,因为我的回答是在 2013 年。事情继续发展。【参考方案5】:您还可以使用反射来访问隐藏功能以设置 USB 网络共享。 这是我的代码。
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
Log.d(TAG,"test enable usb tethering");
String[] available = null;
int code=-1;
Method[] wmMethods = cm.getClass().getDeclaredMethods();
for(Method method: wmMethods)
if(method.getName().equals("getTetherableIfaces"))
try
available = (String[]) method.invoke(cm);
break;
catch (IllegalArgumentException e)
// TODO Auto-generated catch block
e.printStackTrace();
return;
catch (IllegalAccessException e)
// TODO Auto-generated catch block
e.printStackTrace();
return;
catch (InvocationTargetException e)
// TODO Auto-generated catch block
e.printStackTrace();
return;
for(Method method: wmMethods)
if(method.getName().equals("tether"))
try
code = (Integer) method.invoke(cm, available[0]);
catch (IllegalArgumentException e)
// TODO Auto-generated catch block
e.printStackTrace();
return;
catch (IllegalAccessException e)
// TODO Auto-generated catch block
e.printStackTrace();
return;
catch (InvocationTargetException e)
// TODO Auto-generated catch block
e.printStackTrace();
return;
break;
if (code==0)
Log.d(TAG,"Enable usb tethering successfully!");
else
Log.d(TAG,"Enable usb tethering failed!");
要禁用usb tethering,只需将反射方法名称“getTetherableIfaces”更改为“getTetheredIfaces”,将“tether”更改为“untether”即可。
请检查。
【讨论】:
应该不用多说,但这当然是一种非标准的做法,开发者应该意识到这一点,所以我还是随便说吧。 我试用了您的代码并将其置于网络共享模式。然而,该设备并没有真正处于网络共享模式,它只显示“网络共享或启用热点”通知(中间图标中有一个不寻常的带点的有趣圆圈),并且网络共享设置显示热点已启用但开关已设置关闭。没有检查热点,因为那不是我想要的(我想要 USB)。然而,糟糕的事情是在应用程序的每次后续运行中(即使在重新启动后),它也没有显示任何已绑定、可绑定或错误的接口!我可能需要从头开始重新加载。 我的设备是 AT&T Samsung Galaxy Note SGH-I717 running stock 4.1.2 tether 方法在 Android M 上需要 WRITE_SETTINGS 权限,可能是因为 android Lolipop 以后,没有任何 getTether 状态,只是一个 set 方法【参考方案6】:查看 Settings.System 文档,答案是否定的,这是不可能的。
Link to said documentation
【讨论】:
难道连使用java.lang.reflection都不可能吗?我使用它实现了 Wifi Tethering 的状态检查......但对于 USB,我无法弄清楚。以上是关于在android上检测USB网络共享的主要内容,如果未能解决你的问题,请参考以下文章