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.
6 Answers
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
- 
                    2A much better answer than the other one since this simply returns a boolean value. – Mridang Agarwalla Jul 02 '13 at 11:07
 - 
                    The code does not compile: needs to cast invoke's return to Object. – Denis Gladkiy Dec 06 '13 at 19:01
 - 
                    1AndroidStudio wants the invoke() result to be cast: boolean isWifiAPenabled = (Boolean)method.invoke(wifi); – pmont Mar 26 '14 at 15:12
 
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
- 2,992
 - 30
 - 28
 
- 
                    
 - 
                    
 - 
                    Does that require a permission in the manifest? I do `registerReceiver` with them, but my `onReceive` is never triggered. – JonasVautherin Nov 24 '22 at 17:21
 - 
                    @JonasVautherin If your app targets API level 26 or higher, you cannot use the manifest to declare a receiver for implicit broadcasts (broadcasts that do not target your app specifically) – Umer Farooq Nov 26 '22 at 13:31
 - 
                    Yes, I register the `IntentFilter` as described above. It just does not trigger my `onReceive` function, which is why I wonder if I am missing a permission in the Manifest (I have ACCESS_NETWORK_STATE and ACCESS_WIFI_STATE already) – JonasVautherin Nov 26 '22 at 17:03
 - 
                    @JonasVautherin have you tried reflection method shown in accepted answer ? – Umer Farooq Nov 27 '22 at 11:33
 - 
                    
 - 
                    Yeah I'm fine with reflection, I just wanted those broadcasts :-) – JonasVautherin Nov 27 '22 at 18:57
 - 
                    @JonasVautherin okay but `android.net.wifi.WIFI_AP_STATE_CHANGED` works. I checked in android 7,11 and 12. I Think you are missing something maybe not properly registering them – Umer Farooq Nov 28 '22 at 11:38
 
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"/>
- 2,084
 - 1
 - 26
 - 40
 
- 
                    1Thanks. Refactored it a little: http://pastebin.com/GEUaLh44 - added Method caching, logging. – YetAnotherUser Feb 08 '16 at 19:37
 
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;
    }
- 3,782
 - 1
 - 12
 - 13
 
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
}
- 94
 - 4
 
(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.
- 1
 - 1