7

I want to know how to detect state of WiFi tethering. I've seen an article: Android 2.3 wifi hotspot API But it doesn't work! It returns always WIFI_AP_STATE_DISABLED = 1. It doesn't depend on real state of WiFi tethering.

Community
  • 1
  • 1
Nolesh
  • 6,848
  • 12
  • 75
  • 112

6 Answers6

17

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

Community
  • 1
  • 1
Jayyrus
  • 12,961
  • 41
  • 132
  • 214
6

In addition to the reflexion, to get the Wifi tethering status update, you can listen to this broadcast 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

Tobliug
  • 2,992
  • 30
  • 28
4

First, you need to get 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:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
Denis Gladkiy
  • 2,084
  • 1
  • 26
  • 40
1

Here is the Xamarin C# version if anyone is looking:

    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;
    }
JamesMontemagno
  • 3,782
  • 1
  • 12
  • 13
0

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.

Here is a kotlin function that will determine if a device is a mobile hotspot, it has not been widely tested so 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
}
tmpfs
  • 94
  • 4
0

(without using reflection since they say google is restricting it)

I'm writting this answer 10 years later. 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. if there is an address, I check using the connectivity manger whether WI-FI is connected to a network or not. if there is an IP for the Wlan network interface but it isn't connected to a network, I assume tethering is enabled.

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)

// 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:

//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. it won't exist in your case.

Amr Ehab
  • 1
  • 1