如何在Android上获取本地网络中所有设备的IP地址和名称

15

我想使用Java查看我网络上的所有连接设备,但是我无法让它正常工作。 我在下面附上了一些截图,展示了我希望输出的样子。我想要设备名称(例如“TP Link路由器”或“Nexus 5X”)和IP地址。

我在谷歌和stackoverflow上做了很多搜索,但似乎没有什么对我有用的。即使GitHub也没有有效的代码。我尝试搜索UPnP,局域网,子网等,但是什么都找不到。

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());
    }
}

示例1 示例2

实际上,我找到了一个相似的问题,但已经超过一年没有得到答案。来源


你从哪里获取这些身份图标的? - lelloman
顺便说一下,对另一个问题进行评论不会将其推到首页。 - OneCricketeer
@lelloman,那些是来自应用程序的,我认为它们只是根据名称生成的。 - Jason
1
@Anuj,非常抱歉回复晚了。我查看了很久以前的源代码,并复制了相应的代码,尽管我怀疑如今可能有更好的方法。https://pastebin.com/pxEmTAUz - Jason
1
@Anuj,非常抱歉回复得这么晚,我翻看了很久以前的源代码,并复制了相应的代码,不过我怀疑现在可能有更好的方法。https://pastebin.com/pxEmTAUz - undefined
显示剩余2条评论
1个回答

21
主要问题在于你获取了错误的IP地址。InetAddress.getLocalHost()返回的是127.0.0.1,这只是你设备的地址。
应该使用Wifi IP地址代替:
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);

这里有一个快速且简单的AsyncTask,可以完成这个任务:
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;
}

以下是权限列表:

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

并非所有路由器都支持此功能,因此获取名称的另一种方法是将MAC地址发送到API,并返回品牌名称。

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();}}

2
是的,你说得对,我在模拟器上测试了它(我真笨),所以它没能工作。现在的问题是,我没有得到任何名称。为什么?我得到的信息如下。例如192.168.0.105是sonos,但我看不到它的名称,其他应用程序可以看到。 主机:192.168.0.105(192.168.0.105)可达! 尝试IP:192.168.0.106 尝试IP:192.168.0.107 主机:192.168.0.107(192.168.0.107)可达! 尝试IP:192.168.0.108 主机:192.168.0.108(192.168.0.108)可达! 尝试IP:192.168.0.109 主机:192.168.0.109(192.168.0.109)可达! - Jason
我不知道为什么 :( 。我觉得很奇怪,其他应用程序可以看到它,但是这个脚本却看不到。但是,如果它对你有效,那么你应该改变什么才能让它对我也有效 :P 。 - Jason
3
其他应用程序可能会尝试更高级的功能。如果你找到了一个能完成你想要做的事情的应用程序,你可以联系开发者或反编译它以查看它是如何完成这些操作的。 - DataDino
这是一个关于IP地址的问题......我们如何获取连接设备的MAC地址以获取设备名称? - Arash Hatami
这会很慢! - Michał Ziobro
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接