android jmdns,Android - jmdns doesn't discover devices

问题

I'm trying to implement a class to discover services on the network.

I've tried working with Android's NSD and it does discover the services fine, but it supports only API levels 16 and up, and I can't seem to retrieve the txtRecord field within the service info (it returns null for some reason). Turns out it's a known problem...

So now I'm trying to work with jmDNS, which doesn't seem to find services at all.

here's my class (I'm working with the AndroidAnnotations framework) 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());

}

}

And in my app I call:

init(getActivity());

And then startDiscovery(); to start scanning and stopDiscovery(); to stop scanning.

And of course, I gave the app the required permissions in the manifest...

What am I missing here?

If you need me to provide additional code/info - just ask.

thanks!!

回答1:

I am the author of ZeroConf Browser for Android and I use the open source Library JmDNS for all my resolving. It works great but there are a few tricks to getting it to work properly.

In your Android manifest.xml make sure you have these permissions at least.

Before starting the activity you must allow multi-cast packets by acquiring a multicast lock.

@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;

}

And don't forget on stopping the scan to unlock the multicast lock and shut down 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);

}

}

Most importanty don't use the default constructor. You must use the IP Address Constructor. I noticed in your code you are just doing JmDNS.create(). I think for some reason the only way it works on Android is to use the contructor below.

jmdns = JmDNS.create(deviceIpAddress, HOSTNAME);

回答2:

If you are having this error in Android Oreo 8.x, this might help you.

First, Remember to make sure you have added these permissions into your Android manifest.xml.

Acquire a multicast lock to allow multi-cast packets.

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);

MulticastLock lock = wifi.createMulticastLock("jmdns-multicast-lock");

lock.setReferenceCounted(true);

lock.acquire();

Now, use only this constructor JmDNS.create(InetAddress addr, String name) to create an instance of JmDNS and bind it to a specific network interface given its IP-address, like this:

try {

jmDNS = JmDNS.create(InetAddress.getByName(obtainIPv4Address(info)), HOST_NAME);

} catch (IOException e) {

LogHelper.e(TAG, "Error in JmDNS creation: " + e);

}

Finally, just make sure to call JmDNSunreisterAllServices(), and JmDNS.close() to stop JmDNS stream and releases any system resources associated with it. Also, call MulticastLock.release() to unlock the multicast lock when you're done with it.

try {

if (jmDNS != null) {

jmDNS.unregisterAllServices();

jmDNS.close();

jmDNS = null;

}

if (lock != null) {

lock.release();

lock = null;

}

} catch (Exception e) {

e.printStackTrace();

}

来源:https://stackoverflow.com/questions/23805893/android-jmdns-doesnt-discover-devices

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值