You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android局域网中如何根据已知主机名获取对应IP地址?

Solution for Retrieving LAN Hostname-to-IP Mapping in Android

Hey there, let's break down how to fix your issues with getting hostnames for known LAN IPs, and work through each problem you're facing:

Why InetAddress.getHostName() Returns IP Instead of Hostname

The methods getHostName() and getCanonicalHostName() rely on reverse DNS (PTR) records, which most home LAN devices don't register with a local DNS server. Additionally, Android's network stack might restrict reverse lookups unless the device has been actively communicated with (like a ping to populate the ARP cache).

Fix for This:

  • First, ensure your app has the required permissions in AndroidManifest.xml:
    <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" />
    
  • Try pinging the target IP first to populate the ARP cache, then attempt the hostname lookup. Here's a quick ping implementation snippet:
    private boolean pingHost(String ip) {
        try {
            Process process = Runtime.getRuntime().exec("ping -c 1 " + ip);
            int exitCode = process.waitFor();
            return exitCode == 0;
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            return false;
        }
    }
    
    // Usage
    String targetIp = "192.168.1.100";
    if (pingHost(targetIp)) {
        InetAddress address = InetAddress.getByName(targetIp);
        String hostname = address.getHostName();
        // Use the hostname here
    }
    

Why nslookup Doesn't Work in Android

Android's system environment doesn't include nslookup by default on most devices, unlike desktop Java. Calling system commands like this is also unreliable across different Android versions and OEM skins. Instead, use a dedicated DNS library or Android's built-in APIs for DNS queries.

Fixing NoClassDefFoundError for dnsjava

Adding the JAR to the libs directory isn't enough in Android Studio—you need to explicitly declare the dependency in your build file, and handle ProGuard if you're using it:

  1. Update your app-level build.gradle:
    dependencies {
        // Add this line to include the local JAR
        implementation files('libs/dnsjava-2.1.7.jar')
    }
    
  2. Add ProGuard rules (if enabled):
    If you're using code shrinking, add these lines to proguard-rules.pro to prevent dnsjava classes from being obfuscated:
    -keep class org.xbill.** { *; }
    -keep interface org.xbill.** { *; }
    
  3. Clean and rebuild your project:
    Go to Build > Clean Project, then Build > Rebuild Project to ensure the dependency is properly linked.

Using dnsjava for Reverse Lookups

Once the library is set up, you can use it to perform reverse DNS queries directly:

import org.xbill.DNS.*;
import java.net.InetAddress;

public String getHostnameFromIp(String ip) {
    try {
        InetAddress address = InetAddress.getByName(ip);
        Name name = ReverseMap.fromAddress(address);
        Lookup lookup = new Lookup(name, Type.PTR);
        Record[] records = lookup.run();
        if (records != null && records.length > 0) {
            return records[0].rdataToString();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return ip; // Fallback to IP if lookup fails
}

Better Alternative: Android's NsdManager (ZeroConf/mDNS)

For LAN device discovery, Android's built-in NsdManager is a more reliable option—it uses mDNS (Bonjour) to find devices that advertise their hostnames on the network. Here's a quick implementation outline:

private NsdManager nsdManager;
private NsdManager.DiscoveryListener discoveryListener;

private void startDiscovery() {
    nsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE);
    discoveryListener = new NsdManager.DiscoveryListener() {
        @Override
        public void onDiscoveryStarted(String serviceType) {
            // Discovery started
        }

        @Override
        public void onServiceFound(NsdServiceInfo serviceInfo) {
            // Get hostname and IP
            String hostname = serviceInfo.getServiceName();
            InetAddress ip = serviceInfo.getHost();
            // Process the device info here
        }

        @Override
        public void onServiceLost(NsdServiceInfo serviceInfo) {
            // Device lost
        }

        @Override
        public void onDiscoveryStopped(String serviceType) {
            // Discovery stopped
        }

        @Override
        public void onStartDiscoveryFailed(String serviceType, int errorCode) {
            // Handle error
        }

        @Override
        public void onStopDiscoveryFailed(String serviceType, int errorCode) {
            // Handle error
        }
    };
    nsdManager.discoverServices("_http._tcp.", NsdManager.PROTOCOL_DNS_SD, discoveryListener);
}

// Don't forget to stop discovery when done
private void stopDiscovery() {
    if (nsdManager != null && discoveryListener != null) {
        nsdManager.stopServiceDiscovery(discoveryListener);
    }
}

This method doesn't require third-party libraries and works natively on Android, making it a great choice for LAN device hostname/IP mapping.

内容的提问来源于stack exchange,提问作者Hamza Hajeir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:20:12