在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”(在 BroadcastReceiveronReceive() 中检索收到的附加信息将为“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网络共享的主要内容,如果未能解决你的问题,请参考以下文章

怎么把电脑的网络共享到手机上使用

openwrt不识别小米usb网络共享

如何将手机USB网络共享转到路由器上

手机怎么用usb共享网络给电脑

电脑用网线连接,手机如何共享此上网?

如何利用Android手机usb接口当WIFI热点