当前位置: 首页 > 知识库问答 >
问题:

Android-jmdns不发现设备

夏谦
2023-03-14

我试图实现一个类来发现网络上的服务。我尝试使用Android的NSD,它确实发现了服务,但它只支持API级别16及以上,我似乎无法检索服务信息中的txtRecord字段(出于某种原因,它返回null)。原来这是一个已知的问题...

所以现在我正在尝试使用jmDNS,它似乎根本找不到服务。这是我的类(我正在使用AndroidAnnotations框架)MDnsHelper:

@EBean
public class MDnsHelper implements ServiceListener {

public static final String SERVICE_TYPE = "_http._tcp.local";

Activity activity;
private JmDNS jmdns;
private MulticastLock multicastLock;
WifiManager wm;
InetAddress bindingAddress;
boolean isDiscovering;

public void init(Activity activity) {
    this.activity = activity;
    isDiscovering = false;
    wm = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
    multicastLock = wm.createMulticastLock(activity.getPackageName());
    multicastLock.setReferenceCounted(false);
}

@Background
public void startDiscovery() {
    if (isDiscovering)
        return;
    System.out.println("starting...");
    multicastLock.acquire();
    try {
        System.out.println("creating jmdns");
        jmdns = JmDNS.create();
        System.out.println("jmdns created");
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (jmdns != null) {
            jmdns.addServiceListener(SERVICE_TYPE, MDnsHelper.this);
            isDiscovering = true;
            System.out.println("discovering services of type: " + SERVICE_TYPE);
        }
    }
}

@Background
public void stopDiscovery() {
    if (!isDiscovering || jmdns == null)
        return;
    System.out.println("stopping...");
    multicastLock.release();
    jmdns.removeServiceListener(SERVICE_TYPE, MDnsHelper.this);
    System.out.println("listener for " + SERVICE_TYPE + " removed");
    try {
        jmdns.close();
        isDiscovering = false;
        System.out.println("jmdns closed");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void serviceAdded(ServiceEvent service) {
    System.out.println("found: " + service.getInfo().toString());
}

@Override
public void serviceRemoved(ServiceEvent service) {
    System.out.println("lost: " + service.getInfo().toString());
}

@Override
public void serviceResolved(ServiceEvent service) {
    System.out.println("resolved: " + service.getInfo().toString());
}
}

在我的应用程序中,我调用:

init(getActivity());

然后< code > start discovery();开始扫描并< code >停止discovery();停止扫描。

当然,我在清单中给了应用html" target="_blank">程序所需的权限...我错过了什么?如果你需要我提供额外的代码/信息-只是问。谢谢!!

共有2个答案

袁炳
2023-03-14

如果你在Android Oreo 8.x中遇到这个错误,这可能对你有所帮助。

首先,请记住确保您已将这些权限添加到您的Androidmanifest.xml中。

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

获取多播锁以允许多播数据包。

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
MulticastLock lock = wifi.createMulticastLock("jmdns-multicast-lock");
lock.setReferenceCounted(true);
lock.acquire();

现在,仅使用此构造函数< code > JmDNS . create(inet address addr,String name)创建一个JM DNS实例,并将其绑定到给定IP地址的特定网络接口,如下所示:

try {
    jmDNS = JmDNS.create(InetAddress.getByName(obtainIPv4Address(info)), HOST_NAME);
} catch (IOException e) {
    LogHelper.e(TAG, "Error in JmDNS creation: " + e);
}

最后,只需确保调用JmDNSunreisterAllServices()JmDNS.close()来停止JmDNS流并释放与之关联的任何系统资源。此外,在完成后调用MulticastLock.release()来解锁多播锁。

try {
    if (jmDNS != null) {
        jmDNS.unregisterAllServices();
        jmDNS.close();
        jmDNS = null;
    }
    if (lock != null) {
        lock.release();
        lock = null;
    }
} catch (Exception e) {
    e.printStackTrace();
}
齐英耀
2023-03-14

我是Android ZeroConf浏览器的作者,我使用开源库JmDNS进行所有解析。它工作得很好,但有一些技巧可以让它正常工作。

>

  • 在你的Androidmanifest.xml确保你至少有这些权限。

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

    在启动活动之前,必须通过获取多播锁来允许多播数据包。

    @Override
    protected void onStart() {
        Log.i(TAG, "Starting ServiceActivity...");
        super.onStart();
        try {
            Log.i(TAG, "Starting Mutlicast Lock...");
            WifiManager wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
            // get the device ip address
            final InetAddress deviceIpAddress = getDeviceIpAddress(wifi);
            multicastLock = wifi.createMulticastLock(getClass().getName());
            multicastLock.setReferenceCounted(true);
            multicastLock.acquire();
            Log.i(TAG, "Starting ZeroConf probe....");
            jmdns = JmDNS.create(deviceIpAddress, HOSTNAME);
            jmdns.addServiceTypeListener(this);
        } catch (IOException ex) {
            Log.e(TAG, ex.getMessage(), ex);
        }
        Log.i(TAG, "Started ZeroConf probe....");
    }
    
    private InetAddress getDeviceIpAddress(WifiManager wifi) {
       InetAddress result = null;
       try {
          // default to Android localhost
          result = InetAddress.getByName("10.0.0.2");
    
          // figure out our wifi address, otherwise bail
          WifiInfo wifiinfo = wifi.getConnectionInfo();
          int intaddr = wifiinfo.getIpAddress();
          byte[] byteaddr = new byte[] { (byte) (intaddr & 0xff), (byte) (intaddr >> 8 & 0xff),
              (byte) (intaddr >> 16 & 0xff), (byte) (intaddr >> 24 & 0xff) };
          result = InetAddress.getByAddress(byteaddr);
       } catch (UnknownHostException ex) {
          Log.w(TAG, String.format("getDeviceIpAddress Error: %s", ex.getMessage()));
       }
    
       return result;
    }
    

    不要忘记在停止扫描时解锁多播锁并关闭JmDNS。

    @Override
    protected void onStop() {
        Log.i(TAG, "Stopping ServiceActivity...");
        super.onStop();
    
        stopScan();
    }
    
    private static void stopScan() {
        try {
            if (jmdns != null) {
                Log.i(TAG, "Stopping ZeroConf probe....");
                jmdns.unregisterAllServices();
                jmdns.close();
                jmdns = null;
            }
            if (multicastLock != null) {
                Log.i(TAG, "Releasing Mutlicast Lock...");
                multicastLock.release();
                multicastLock = null;
            }
        } catch (Exception ex) {
            Log.e(TAG, ex.getMessage(), ex);
        }
    }
    

    最重要的是不要使用默认构造函数。您必须使用IP地址构造函数。我注意到在您的代码中,您只是在执行JmDNS.create()。我认为出于某种原因,它在Android上工作的唯一方法是使用下面的构造函数。

    jmdns = JmDNS.create(deviceIpAddress, HOSTNAME);
    

  •  类似资料:
    • 我正在编写一个Android应用程序,它应该可以通过蓝牙发现设备。 我没有得到任何例外,但设备只是没有找到,即使我的windows pc找到他们(并可以找到自己)。 我肯定他们是好的,但我两种方法都试过了。当然我也分别试过了。 下面是我的ListActivity,它搜索设备: 日志显示扫描后MLEDeviceListAdapter:0和扫描后isEmpty():true。 则从不调用该日志(onS

    • JmDNS 是 multi-cast DNS 的一个 Java 实现并可被用来在本地广域网中实现 DNS 服务注册与发现。

    • 我目前正在开发一个小应用程序,以开始使用蓝牙Android应用编程接口可以提供的服务。 编辑- 问题似乎是由特定的Nexus 5设备造成的。他们的蓝牙接收器好像不太好用。以下解决方案适用于其他设备 备注: > 我已经完成了几乎所有我感兴趣的功能(例如检查适配器是否存在,启用/禁用蓝牙,查询成对的部分,设置适配器可发现)。 问题: 实际上,当我启动. onDiscovery()方法时,没有找到设备,

    • 问题内容: 我正在尝试使用JmDNS在客户端服务器应用程序中启用服务发现。我完全理解服务器端的服务注册表,其代码类似于以下内容: 但是,我在弄清楚如何让我的客户端从注册的服务中检索端口号和IP地址并使用此数据打开TCP连接时遇到了麻烦。我搜索了有关如何使用JmDNS的示例,但无济于事。这里有人可以给我一些基本的例子吗?或者,如果有人在JmDNS上有指向良好资源/教程的链接,可以请他们提供吗? 注意

    • 我正在开发一个蓝牙4.0低能耗应用程序来快速扫描周围的广告专用设备(每秒10次或更多),并用RSSI获取他们的地址。根据Android蓝牙应用编程接口,发现是异步的,大约需要12秒。有什么办法可以设置这个时间吗?或者可以使用HCI或蓝牙堆栈直接与设备通信?

    • 最近,我们在Android应用程序中增加了对Chromecast的支持,但在对各种移动设备(手机和平板电脑)的扩展测试中,发现在许多移动设备上,Flipps应用程序都没有发现Chromecast。在相同的设备上,我们使用了最新版本的官方Chromecast SDK演示应用程序进行测试,该应用程序从https://github.com/googlecast/castvideo-Android下载(主