15

I want to see all the connected devices on my network with java, but I can't get it working. I have attached some screenshots below of how I want it to be output. I would like to have the name (for example "TP Link Router" or "Nexus 5X") and the IP address.

I have searched a lot on google and stackoverflow, but nothing seemed to work for me. Even GitHub has no effective code. I tried searching for UPnP, Local Area Network, subnets, etc, but found nothing.

InetAddress localhost = InetAddress.getLocalHost();
byte[] ip = localhost.getAddress();
for (int i = 1; i <= 254; i++) {
    ip[3] = (byte)i;
    InetAddress address = InetAddress.getByAddress(ip);
    if (address.isReachable(1000)) {
        System.out.println(address + address.getHostAddress() + address.getAddress() + address.getHostName() + address.getCanonicalHostName());
    }
}

Example 1 Example 2

I did in fact find a duplicate (sort of) question, but it hasn't been answered for over a year. Source

Community
  • 1
  • 1
Jason
  • 1,658
  • 3
  • 20
  • 51
  • where did you get those identicons from? – lelloman Sep 06 '16 at 12:48
  • By the way, commenting on another question doesn't bump it into the front page – OneCricketeer Sep 06 '16 at 12:53
  • @lelloman those were from the app, I think they just generate it based on the name of it – Jason Sep 06 '16 at 14:22
  • @cricket_007 I wasn't aiming for that... :P . I was hoping that the original questioner has already solved it and wanted to share it – Jason Sep 06 '16 at 14:23
  • @Jason how did you get mac address? – Anuj Nov 11 '22 at 11:47
  • 1
    @Anuj sorry for the very late response, I've looked at my source code from ages ago and copied the respective code, though I suspect there are better ways nowadays. https://pastebin.com/pxEmTAUz – Jason Feb 04 '23 at 11:52

1 Answers1

21

The main problem is that you're grabbing the wrong IP address. InetAddress.getLocalHost() is returning 127.0.0.1 and that's just your device.

Use the Wifi IP address in instead:

ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
WifiManager wm = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);

WifiInfo connectionInfo = wm.getConnectionInfo();
int ipAddress = connectionInfo.getIpAddress();
String ipString = Formatter.formatIpAddress(ipAddress);

Here is a quick and dirty AsyncTask that does that:

static class NetworkSniffTask extends AsyncTask<Void, Void, Void> {

  private static final String TAG = Constants.TAG + "nstask";

  private WeakReference<Context> mContextRef;

  public NetworkSniffTask(Context context) {
    mContextRef = new WeakReference<Context>(context);
  }

  @Override
  protected Void doInBackground(Void... voids) {
    Log.d(TAG, "Let's sniff the network");

    try {
      Context context = mContextRef.get();

      if (context != null) {

        ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        WifiManager wm = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);

        WifiInfo connectionInfo = wm.getConnectionInfo();
        int ipAddress = connectionInfo.getIpAddress();
        String ipString = Formatter.formatIpAddress(ipAddress);


        Log.d(TAG, "activeNetwork: " + String.valueOf(activeNetwork));
        Log.d(TAG, "ipString: " + String.valueOf(ipString));

        String prefix = ipString.substring(0, ipString.lastIndexOf(".") + 1);
        Log.d(TAG, "prefix: " + prefix);

        for (int i = 0; i < 255; i++) {
          String testIp = prefix + String.valueOf(i);

          InetAddress address = InetAddress.getByName(testIp);
          boolean reachable = address.isReachable(1000);
          String hostName = address.getCanonicalHostName();

          if (reachable)
            Log.i(TAG, "Host: " + String.valueOf(hostName) + "(" + String.valueOf(testIp) + ") is reachable!");
        }
      }
    } catch (Throwable t) {
      Log.e(TAG, "Well that's not good.", t);
    }

  return null;
}

Here are the permissions:

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

Not all routers allow this, so to get the names in a other way is to send the mac adress to an api and get the brand name back in return.

String macAdress = "5caafd1b0019";
String dataUrl = "http://api.macvendors.com/" + macAdress;
HttpURLConnection connection = null;
try {
    URL url = new URL(dataUrl);
    connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("POST");
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    connection.setDoInput(true);
    connection.setDoOutput(true);
    DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
    wr.flush();
    wr.close();
    InputStream is = connection.getInputStream();
    BufferedReader rd = new BufferedReader(new InputStreamReader(is));
    StringBuffer response = new StringBuffer();
    String line;
    while ((line = rd.readLine()) != null) {response.append(line);response.append('\r');}
    rd.close();
    String responseStr = response.toString();
    Log.d("Server response", responseStr);
} catch (Exception e) {e.printStackTrace();} finally {if (connection != null) {connection.disconnect();}}
Jason
  • 1,658
  • 3
  • 20
  • 51
DataDino
  • 1,507
  • 1
  • 15
  • 30
  • It does not work the way I want it :( . First of all it tries 0.0.0.1, 0.0.0.2, etc. and I would like it to check 192.168.0.1, 192.168.0.2, etc. Second of all I am only getting this: `Trying ip: 192.168.0.193` . I want it to say this for example: Found IP 192.168.0.130 with name "MY-PC". How can I do so? – Jason Sep 06 '16 at 12:11
  • 0.0.0.0? make sure you are on WiFi on a real device. And the edited code only prints out reachable IPs with the associated host name. – DataDino Sep 06 '16 at 12:20
  • 2
    jup you're right, I tested it on an emulator (stupid me), that's why it didn't work. The problem now is that I am not getting any names. Why not? This is what I'm getting. For example 192.168.0.105 is sonos, but I don't see it's name, and other apps do. `Host: 192.168.0.105(192.168.0.105) is reachable! Trying ip: 192.168.0.106 Trying ip: 192.168.0.107 Host: 192.168.0.107(192.168.0.107) is reachable! Trying ip: 192.168.0.108 Host: 192.168.0.108(192.168.0.108) is reachable! Trying ip: 192.168.0.109 Host: 192.168.0.109(192.168.0.109) is reachable!` – Jason Sep 06 '16 at 12:39
  • Odd. When I run it I can see hostname when available. For my router is listed as: `Host: router.asus.com(192.168.1.1) is reachable!` I also see a lot of other devices floating around like my cell phones and printer with hostnames. I added the permissions used, btw. – DataDino Sep 06 '16 at 12:49
  • I don't :( . I find it strange that other applications can see it but not this script. But yeah.. if it works for you, what should you change then to make it work for me :P . – Jason Sep 06 '16 at 13:03
  • I tried it on a different wifi network, and it worked! Maybe it is because of my router not wanting to share the name, although that's weird because other apps do see the name – Jason Sep 06 '16 at 13:11
  • 3
    Other apps might try something more sophisticated. If you find an app that does what you want to do, you can always reach out the the developer or decompile it to see how stuff is done. – DataDino Sep 06 '16 at 13:16
  • I think he is using the IP to get the DNS name, any idea how I can do that? `if (name.isEmpty()) { String dns = ""; try { dns = InetAddress.getByName(MainActivity.this.IPS[i]).getHostName(); } catch (UnknownHostException e2) { } if (dns.equals("")) { name = "Unknown host"; } else { name = dns; } }` – Jason Sep 06 '16 at 14:40
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/122756/discussion-between-datadino-and-jason). – DataDino Sep 06 '16 at 14:49
  • it's pretty work for IP addresses ...... how can we get mac address of connected devices to get device's name ? – Arash Hatami Apr 25 '17 at 14:40
  • I it will be slow! – Michał Ziobro May 13 '17 at 19:35
  • @DataDino I find your solution great. Is there any possibility to get also the mac address of each particular device that is reachable? I already got it for the router. – AlexAndro Dec 07 '17 at 08:43
  • Hey, This is very time consuming process. it will take too much time for check isReachable(). is there other way for fast discovery as like fing app do. ? – Vrajesh Jan 07 '18 at 19:28
  • @DataDino use jcifs lib for get name from ip address. https://www.programcreek.com/java-api-examples/index.php?api=jcifs.netbios.NbtAddress check this link for get host name – Vrajesh Jan 07 '18 at 19:30
  • How can i find the Mac Address also along with Reachable IP addresses – Dhiru Aug 09 '18 at 07:42