Search code examples
androidprocesspingsubnetnetwork-scan

Android subnet scan


In my application I need to scan the local subnet (192.168.1.*) to collect the list of MAC addresses of all connected devices.

I currently use the following strategy:

  1. start simultaneously 255 ping commands with Runtime.exec("ping -c 1 <addr>")
  2. use waitFor() on each of the returned process to collect the exit code
  3. close input streams of processes and destroy them
  4. read the /proc/net/arp file and parse the MAC addresses

In most cases, this works very well and provides a fast scan.

But on some devices (such as android 1.5, and sometimes on >=4.0), the execution gets stuck at process creation (after a few ones have been successfully started) and there's no way to kill the running thread.

Do you see anything I could try to solve this issue? Or any other strategy that would not take too long?


Solution

  • This can be solved by using a pool of thread running the INetAddress.isReachable() method (instead of running the ping command in native processes).

    private static final int NB_THREADS = 10;
    
    public void doScan() {
        Log.i(LOG_TAG, "Start scanning");
    
        ExecutorService executor = Executors.newFixedThreadPool(NB_THREADS);
        for(int dest=0; dest<255; dest++) {
            String host = "192.168.1." + dest;
            executor.execute(pingRunnable(host));
        }
    
        Log.i(LOG_TAG, "Waiting for executor to terminate...");
        executor.shutdown();
        try { executor.awaitTermination(60*1000, TimeUnit.MILLISECONDS); } catch (InterruptedException ignored) { }
    
        Log.i(LOG_TAG, "Scan finished");
    }
    
    private Runnable pingRunnable(final String host) {
        return new Runnable() {
            public void run() {
                Log.d(LOG_TAG, "Pinging " + host + "...");
                try {
                    InetAddress inet = InetAddress.getByName(host);
                    boolean reachable = inet.isReachable(1000);
                    Log.d(LOG_TAG, "=> Result: " + (reachable ? "reachable" : "not reachable"));
                } catch (UnknownHostException e) {
                    Log.e(LOG_TAG, "Not found", e);
                } catch (IOException e) {
                    Log.e(LOG_TAG, "IO Error", e);
                }
            }
        };
    }