简体   繁体   English

如何检测 WiFi 网络共享 state

[英]How to detect WiFi tethering state

I want to know how to detect state of WiFi tethering.我想知道如何检测 state 的 WiFi 网络共享。 I've seen an article: Android 2.3 wifi hotspot API But it doesn't work.看过一篇文章: Android 2.3 wifi热点API但是不行。 It returns always WIFI_AP_STATE_DISABLED = 1. It doesn't depend on real state of WiFi tethering.它始终返回 WIFI_AP_STATE_DISABLED = 1。它不依赖于 WiFi 网络共享的真实 state。

Using reflection:使用反射:

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
Method[] wmMethods = wifi.getClass().getDeclaredMethods();
for (Method method: wmMethods) {
  if (method.getName().equals("isWifiApEnabled")) {

    try {
      boolean isWifiAPenabled = method.invoke(wifi);
    } catch (IllegalArgumentException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      e.printStackTrace();
  }
}

As you can see here正如你在这里看到的

First, you need to get WifiManager:首先,您需要获取 WifiManager:

Context context = ...
final WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

Then:然后:

public static boolean isSharingWiFi(final WifiManager manager)
{
    try
    {
        final Method method = manager.getClass().getDeclaredMethod("isWifiApEnabled");
        method.setAccessible(true); //in the case of visibility change in future APIs
        return (Boolean) method.invoke(manager);
    }
    catch (final Throwable ignored)
    {
    }

    return false;
}

Also you need to request a permission in AndroidManifest.xml:您还需要在 AndroidManifest.xml 中请求权限:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

In addition to the reflexion, to get the Wifi tethering status update, you can listen to this broadcast Action :除了反射,要获取 Wifi 网络共享状态更新,您可以收听此广播 Action :

IntentFilter filter = new IntentFilter("android.net.wifi.WIFI_AP_STATE_CHANGED");

To get all tethering option update :要获取所有网络共享选项更新:

IntentFilter filter = new IntentFilter("android.net.conn.TETHER_STATE_CHANGED");

Those actions are hidden inside the Android source code这些操作隐藏在 Android 源代码中

Here is the Xamarin C# version if anyone is looking:如果有人在看,这里是 Xamarin C# 版本:

    static Method isWifiApEnabledMethod;

    public static bool IsWifiApEnabled ()
    {
        var wifiManager = WifiManager.FromContext (Application.Context);
        if (isWifiApEnabledMethod == null)
        {
            try
            {
                isWifiApEnabledMethod = wifiManager.Class.GetDeclaredMethod ("isWifiApEnabled");
                isWifiApEnabledMethod.Accessible = true; //in the case of visibility change in future APIs
            }
            catch (NoSuchMethodException e)
            {
                Debug.WriteLine ("Can't get method by reflection" + e);
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine ("Can't get method by reflection" + ex);

            }
        }

        if (isWifiApEnabledMethod != null)
        {
            try
            {
                return (bool)isWifiApEnabledMethod.Invoke (wifiManager);
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine ("Can't invoke by reflection" + ex);

            }
        }

        return false;
    }

(without using reflection since they say google is restricting it) (不使用反射,因为他们说谷歌正在限制它)

I'm writting this answer 10 years later. 10 年后,我正在写这个答案。 also I don't know if this can be considered a good aproach or not but I first get the Wlan.network interface IPs and if there is no address I assume that it tethering isn't enabled.我也不知道这是否可以被认为是一个好的方法,但我首先获得 Wlan.network 接口 IP,如果没有地址,我假设它没有启用网络共享。 if there is an address, I check using the connectivity manger whether WI-FI is connected to a.network or not.如果有地址,我会使用连接管理器检查 WI-FI 是否连接到网络。 if there is an IP for the Wlan.network interface but it isn't connected to a.network, I assume tethering is enabled.如果 Wlan.network 接口有一个 IP 但它没有连接到 a.network,我假设启用了网络共享。

you probably would need to add this line to your manifest file您可能需要将此行添加到您的清单文件中

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

code to get the ip of an inteface (this only gets the IPv4, you can modify it to get the IPv6 or both if you want)获取接口 ip 的代码(这仅获取 IPv4,您可以根据需要修改它以获取 IPv6 或两者)

// method used to retrieve Wlan ip addresses IPv4 of the device.
public static String IpAddresses() throws NoAddressFoundException, SocketException {

    Enumeration<NetworkInterface> Nics = NetworkInterface.getNetworkInterfaces();
    while (Nics.hasMoreElements()) {
        NetworkInterface NIC = Nics.nextElement();
        if (NIC.isUp() && !NIC.isLoopback() && NIC.getName().contains("wlan")) {
            Enumeration<InetAddress> Addresses = NIC.getInetAddresses();
            while (Addresses.hasMoreElements()) {
                InetAddress WlanAddress = Addresses.nextElement();
                if (WlanAddress instanceof Inet4Address)
                    return WlanAddress.getHostAddress();
            }
        }

    }

    throw new NoAddressFoundException("No suitable wifi address found");
}

then if there is an address i check if wifi is connected by this method:然后,如果有地址,我会检查是否通过这种方法连接了 wifi:

//method to check if the device is connected to a Wi-Fi network; it doesn't matter if network has access to internet
public static boolean isWifiConnected(Context context) {
   
    ConnectivityManager ConMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo WifiInfo = ConMan.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    return WifiInfo.isConnected();
}

NOTE: the "NoAddressFoundException" is a custom exception in my app if anyone is wondering.注意:如果有人想知道,“NoAddressFoundException”是我应用程序中的自定义异常。 it won't exist in your case.它不会存在于你的情况下。

Reflection is a poor way to achieve this.反射是实现这一目标的糟糕方法。

We can inspect the DhcpInfo to determine if the device is allocating addresses (mobile hotspot) or is being allocated by another DHCP server.我们可以检查DhcpInfo以确定设备是否正在分配地址(移动热点)或正在由另一个 DHCP 服务器分配。

Here is a kotlin function that will determine if a device is a mobile hotspot, it has not been widely tested so YMMV.这是一个 kotlin 函数,它将确定设备是否是移动热点,它尚未经过广泛测试,所以 YMMV。

fun isMobileHotspot(manager: WifiManager): Boolean {
  val info = manager.dhcpInfo
  return (
      info.ipAddress == 0
          && info.netmask == 0
          && info.gateway == 0
          && info.serverAddress == 16885952) // 192.168.1.1
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM