首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android - jmdns没有发现设备。

Android - jmdns没有发现设备。
EN

Stack Overflow用户
提问于 2014-05-22 11:44:31
回答 2查看 8.3K关注 0票数 18

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

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

代码语言:javascript
复制
@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());
}
}

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

代码语言:javascript
复制
init(getActivity());

然后startDiscovery();开始扫描,stopDiscovery();停止扫描。

当然,我给了应用程序在清单中所需的权限.我在这里错过了什么?如果你需要我提供额外的代码/信息-问问就行了。谢谢!!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-05-25 11:32:10

我是安卓ZeroConf浏览器的作者,我使用开源库JmDNS来解决所有问题。它很好用,但是要让它正常工作有一些窍门。

  1. 在你的安卓manifest.xml中,至少要确保你有这些权限。
  2. 在开始活动之前,必须通过获取多播锁来允许多播数据包。 @重写受保护的onStart() {Log.i(标记,“启动ServiceActivity.”);super.onStart();尝试{Log.i(标记,“启动多点锁.”);WifiManager wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);//获取设备ip地址最终的InetAddress deviceIpAddress = getDeviceIpAddress(wifi);multicastLock =WifiManagermulticastLock.setReferenceCounted(true);multicastLock.acquire();Log.i(标记,“启动ZeroConf探针.”);jmdns = JmDNS.create(deviceIpAddress,主机名);jmdns.addServiceTypeListener(this);} catch (IOException ex) {Log.e(标记,ex.getMessage(),ex);}Log.i(标记,“已启动的ZeroConf探测.”);} InetAddress getDeviceIpAddress(WifiManager wifi) { InetAddress结果= null;尝试{ //默认到Android本地主机结果= InetAddress.getByName("10.0.0.2");//算出我们的wifi地址,否则保释WifiInfo wifiinfo = wifi.getConnectionInfo();int intaddr = wifiinfo.getIpAddress();byte[] byteaddr =新的byte[] {(字节) (intaddr & 0xff),(字节) (intaddr >> 8& 0xff),(字节) (intaddr >> 16 & 0xff),(字节) (intaddr >> 24 & 0xff) };结果= InetAddress.getByAddress(byteaddr);} catch (UnknownHostException ){Log.w(标记,String.format("getDeviceIpAddress错误:%s",ex.getMessage();}返回结果;}
  3. 不要忘记停止扫描以解锁多播锁定并关闭JmDNS。 @重写受保护的void onStop() {Log.i(标记,“停止ServiceActivity.”);super.onStop();stopScan();}私有静态无效stopScan() { try { if (jmdns != null) {Log.i(标记,“停止ZeroConf探测.”);jmdns.unregisterAllServices();jmdns.close();jmdns =空;} if (multicastLock != null) {Log.i(标记,“释放multicastLock .”);multicastLock.release();multicastLock= null;}multicastLock(异常ex) {Log.e(标记,ex.getMessage(),ex);}
  4. 最重要的是不要使用默认的构造函数。您必须使用IP地址构造器。在您的代码中,我注意到您只是在执行JmDNS.create()。我认为,出于某种原因,它在Android上工作的唯一方法就是使用下面的构造器。 jmdns = JmDNS.create(deviceIpAddress,主机名);
票数 37
EN

Stack Overflow用户

发布于 2019-05-27 03:10:37

如果您在AndroidOreo8.x中有此错误,这可能会对您有所帮助。

首先,记住要确保您已经将这些权限添加到您的Android manifest.xml中。

代码语言:javascript
复制
<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" />

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

代码语言:javascript
复制
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
MulticastLock lock = wifi.createMulticastLock("jmdns-multicast-lock");
lock.setReferenceCounted(true);
lock.acquire();

现在,只使用此构造函数JmDNS.create(InetAddress addr, String name)创建JmDNS实例,并将其绑定到特定的网络接口(给定其IP地址),如下所示:

代码语言:javascript
复制
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()来解锁它。

代码语言:javascript
复制
try {
    if (jmDNS != null) {
        jmDNS.unregisterAllServices();
        jmDNS.close();
        jmDNS = null;
    }
    if (lock != null) {
        lock.release();
        lock = null;
    }
} catch (Exception e) {
    e.printStackTrace();
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23805893

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档