How can I programmatically get information about local hotspot?

553 Views Asked by At

I need to perform a scan of the devices connected to the hotspot I broadcast with my mobile in order to start a communication only with these devices. The basic information I need is the broadcast address, but any other information leading to that would be good (the IP address of a connected device, for instance).

On my mobile it is actually straightforward: the NetworkInterface has always the name "wlan1", so it is pretty easy to get IP information ("wlan0" being the main WiFi interface).

However this name might change on other mobiles (for instance becoming "ap0" or "ap1"). Even worse, on one model I have verified that if both WiFi and hotspot are enabled, they are respectively "wlan0" and "wlan1" but, if I turn off WiFi, the hotspot interface becomes "wlan0"!

This is the code I use:

 for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                InetAddress inetAddress = enumIpAddr.nextElement();
                if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                    String ipadd = inetAddress.getHostAddress();
                    if (name.equals("wlan0") || name.equals("wlan1"))
                    {
                        System.out.println("Found WLAN= " + name);
                        System.out.println("IP Address = " + ipadd);
                        for (InterfaceAddress interfaceAddress : intf.getInterfaceAddresses()) {
                            if (interfaceAddress != null) {
                                InetAddress broadcastadd = interfaceAddress.getBroadcast();
                                if (broadcastadd != null) {
                                    found_bcast_address = broadcastadd.toString();
                                    found_bcast_address = found_bcast_address.substring(1);
                                    System.out.println("Broadcast Address = " + found_bcast_address);
                                }
                            }
                        }
                    }
                }
            }

The main problem is that I do not know which is the name of the Interface related to the hotspot, so with this code I don't know if the device that will answer when I send messages to the broadcast address is connected to my mobile hotspot or the WLAN my mobile is connected.

In other posts I've seen solutions based on:

  1. reading the file "/proc/net/arp" -> but on modern Android this is not feasible
  2. using reflection and calling "getWifiApConfiguration", but again this is not feasible anymore on modern Android

Any way to get this information on recent Android?

1

There are 1 best solutions below

2
Isuru On

One possible solution is to use the Android Network Service Discovery (NSD) API doc. NSD allows devices on a local network to discover and communicate with each other without requiring any configuration. With NSD, you can advertise your service (e.g., your mobile hotspot) and discover other devices that are connected to it.

Here is an example code to advertise your service:

NsdServiceInfo serviceInfo  = new NsdServiceInfo();
serviceInfo.setServiceName("My Hotspot");
serviceInfo.setServiceType("_http._tcp.");
serviceInfo.setPort(8080);
NsdManager nsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE);
nsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, new NsdManager.RegistrationListener() {
    @Override
    public void onServiceRegistered(NsdServiceInfo serviceInfo) {
        Log.d(TAG, "Service registered: " + serviceInfo);
    }

    @Override
    public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
        Log.e(TAG, "Registration failed: " + errorCode);
    }

    @Override
    public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
        Log.d(TAG, "Service unregistered: " + serviceInfo);
    }

    @Override
    public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
        Log.e(TAG, "Unregistration failed: " + errorCode);
    }
});

This code advertises a service with the name "My Hotspot" and the type "_http._tcp." on port 8080. Other devices on the local network can discover this service by using the NSD API.

To discover other devices that are connected to your hotspot, you can use the NSD discovery API:

nsdManager.discoverServices("_http._tcp.", NsdManager.PROTOCOL_DNS_SD, new NsdManager.DiscoveryListener() {
    @Override
    public void onStartDiscoveryFailed(String serviceType, int errorCode) {
        Log.e(TAG, "Discovery failed: " + errorCode);
    }

    @Override
    public void onStopDiscoveryFailed(String serviceType, int errorCode) {
        Log.e(TAG, "Discovery stopped: " + errorCode);
    }

    @Override
    public void onDiscoveryStarted(String serviceType) {
        Log.d(TAG, "Discovery started");
    }

    @Override
    public void onDiscoveryStopped(String serviceType) {
        Log.d(TAG, "Discovery stopped");
    }

    @Override
    public void onServiceFound(NsdServiceInfo serviceInfo) {
        Log.d(TAG, "Service found: " + serviceInfo);
        // Get the IP address of the device that advertises this service
        InetAddress deviceAddress = serviceInfo.getHost();
        String deviceIpAddress = deviceAddress.getHostAddress();
        // Do something with the IP address
    }

    @Override
    public void onServiceLost(NsdServiceInfo serviceInfo) {
        Log.d(TAG, "Service lost: " + serviceInfo);
    }
});

This code discovers services of the type "_http._tcp." and logs the IP address of the device that advertises each service. You can use this IP address to communicate with the device.

Note that NSD requires the ACCESS_WIFI_STATE and CHANGE_WIFI_STATE permissions, as well as the NSD API level 16 or higher.