Android NSD未发现所有服务

Android NSD未发现所有服务,android,zeroconf,service-discovery,wifi-direct,Android,Zeroconf,Service Discovery,Wifi Direct,我正在尝试使用Android本机服务发现来运行应用程序,但有时当我运行应用程序时,它无法从我的网络中发现所有服务。我使用四个galaxy nexus运行代码,大多数情况下,它们同时发现了不同数量的服务 基本上,我使用ServerSocket运行服务: ServerSocket server = new ServerSocket(0); Log.i(TAG, "IP " + server.getInetAddress() + ", running on port " + serve

我正在尝试使用Android本机服务发现来运行应用程序,但有时当我运行应用程序时,它无法从我的网络中发现所有服务。我使用四个galaxy nexus运行代码,大多数情况下,它们同时发现了不同数量的服务

基本上,我使用ServerSocket运行服务:

ServerSocket server = new ServerSocket(0);
Log.i(TAG, "IP " + server.getInetAddress()
        + ", running on port " + server.getLocalPort());

Intent intent = new Intent(MySocket.this,
        MyPresence.class);
intent.putExtra("PORT", server.getLocalPort());
startService(intent);
然后,我使用NsdManager中的registerService方法发布它:

NsdServiceInfo serviceInfo = new NsdServiceInfo();

serviceInfo.setServiceName(Build.SERIAL + "-" + new Date().getTime());
serviceInfo.setServiceType(SERVICE_TYPE);
serviceInfo.setPort(port);

mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD,
        mRegistrationListener);
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD,
        mDiscoveryListener);
为了发现服务,我使用了来自NsdManager的discoverServices方法:

NsdServiceInfo serviceInfo = new NsdServiceInfo();

serviceInfo.setServiceName(Build.SERIAL + "-" + new Date().getTime());
serviceInfo.setServiceType(SERVICE_TYPE);
serviceInfo.setPort(port);

mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD,
        mRegistrationListener);
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD,
        mDiscoveryListener);
使用mDiscoveryListener,如下所示:

mDiscoveryListener = new NsdManager.DiscoveryListener() {

    @Override
    public void onDiscoveryStarted(String regType) {
        Log.d(TAG, "Service discovery started");
    }

    @Override
    public void onServiceFound(NsdServiceInfo service) {
        Log.d(TAG, "Service discovery success");
        Log.d(TAG, String.format("%s %s %s %d",
                service.getServiceName(), service.getServiceType(),
                service.getHost(), service.getPort()));
        if (!service.getServiceType().contains(SERVICE_TYPE)) {
            Log.d(TAG,
                    "Unknown Service Type: " + service.getServiceType());
        } else if (service.getServiceName().equals(mServiceName)) {
            Log.d(TAG, "Same machine: " + mServiceName);
        } else {
            mNsdManager.resolveService(service, mResolveListener);
        }
    }

    @Override
    public void onServiceLost(NsdServiceInfo service) {
        Log.e(TAG, "service lost" + service);
    }

    @Override
    public void onDiscoveryStopped(String serviceType) {
        Log.i(TAG, serviceType + " Discovery stopped: " + serviceType);
    }

    @Override
    public void onStartDiscoveryFailed(String serviceType, int errorCode) {
        Log.e(TAG, serviceType + " Discovery failed: Error code:"
                + errorCode);
        mNsdManager.stopServiceDiscovery(this);
    }

    @Override
    public void onStopDiscoveryFailed(String serviceType, int errorCode) {
        Log.e(TAG, serviceType + " Discovery failed: Error code:"
                + errorCode);
        mNsdManager.stopServiceDiscovery(this);
    }
};

我做错什么了吗?有人知道这方面的解决方案或解决方法吗?

我也有同样的问题,请帮助。尝试使用:)

我担心在实现中仍然存在导致它错过服务的bug。我已经用多台Android设备和一台MacBook做了几天的测试,但它不是一直都能工作。我在Android bug tracker中记录了我在bug报告中的发现:

我倾向于认为整个NSD在Android中的实现一定有点不稳定。我还有一个简单的活动来演示生命周期(没有打开任何套接字),有时它可以工作,有时它不工作。我就是不明白。如果任何人有一些见解,以下是活动:

另一方面,基于Wifi Direct的NSD对我来说似乎非常可靠:


请注意,这两个活动都没有任何资源,因此只需使用适当的权限将活动添加到清单中即可

现在回答这个问题可能有点晚了,但我在他们的开发者网站上找到了一个很好的针对android give的NSD解决方案。我做了一些修改,效果非常好

public class NsdClient {
private Context mContext;

private NsdManager mNsdManager;
NsdManager.DiscoveryListener mDiscoveryListener;

//To find all the available networks SERVICE_TYPE = "_services._dns-sd._udp"
public static final String SERVICE_TYPE = "_hap._tcp.";
public static final String TAG = "NsdClient";

private static ArrayList<NsdServiceInfo> ServicesAvailable = new ArrayList<>();

public NsdClient(Context context) {
    mContext = context;
    mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
}

public void initializeNsd() {
    initializeDiscoveryListener();
}

public void initializeDiscoveryListener() {
    mDiscoveryListener = new NsdManager.DiscoveryListener() {

        @Override
        public void onDiscoveryStarted(String regType) {
            Log.d(TAG, "Service discovery started " + regType);
        }

        @Override
        public void onServiceFound(NsdServiceInfo service) {
            Log.d(TAG, "Service discovery success " + service);
            AVAILABLE_NETWORKS.add(service);

            if (!service.getServiceType().equals(SERVICE_TYPE)) {
                Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
            } else if (service.getServiceName().equals(mServiceName)) {
                Log.d(TAG, "Same Machine: " + mServiceName);
            } else if (service.getServiceName().contains(mServiceName)) {
                Log.d(TAG, "Resolving Services: " + service);
                mNsdManager.resolveService(service, new initializeResolveListener());
            }
        }

        @Override
        public void onServiceLost(NsdServiceInfo service) {
            Log.e(TAG, "service lost" + service);
            if (ServicesAvailable.equals(service)) {
                ServicesAvailable = null;
            }
        }

        @Override
        public void onDiscoveryStopped(String serviceType) {
            Log.i(TAG, "Discovery stopped: " + serviceType);
        }

        @Override
        public void onStartDiscoveryFailed(String serviceType, int errorCode) {
            Log.e(TAG, "Discovery failed: Error code:" + errorCode);
            mNsdManager.stopServiceDiscovery(this);
        }

        @Override
        public void onStopDiscoveryFailed(String serviceType, int errorCode) {
            Log.e(TAG, "Discovery failed: Error code:" + errorCode);
            mNsdManager.stopServiceDiscovery(this);
        }
    };
}

public class initializeResolveListener implements NsdManager.ResolveListener {

    @Override
    public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
        Log.e(TAG, "Resolve failed " + errorCode);
        switch (errorCode) {
            case NsdManager.FAILURE_ALREADY_ACTIVE:
                Log.e(TAG, "FAILURE ALREADY ACTIVE");
                mNsdManager.resolveService(serviceInfo, new initializeResolveListener());
                break;
            case NsdManager.FAILURE_INTERNAL_ERROR:
                Log.e(TAG, "FAILURE_INTERNAL_ERROR");
                break;
            case NsdManager.FAILURE_MAX_LIMIT:
                Log.e(TAG, "FAILURE_MAX_LIMIT");
                break;
        }
    }

    @Override
    public void onServiceResolved(NsdServiceInfo serviceInfo) {
        Log.e(TAG, "Resolve Succeeded. " + serviceInfo);


        if (serviceInfo.getServiceName().equals(mServiceName)) {
            Log.d(TAG, "Same IP.");
            return;
        }

    }
}

public void stopDiscovery() {
    mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}

public List<NsdServiceInfo> getChosenServiceInfo() {
    return ServicesAvailable;
}

public void discoverServices() {
    mNsdManager.discoverServices(
            SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}
}
公共类NSD客户端{
私有上下文;
私人NSD经理mNsdManager;
NsdManager.DiscoveryListener mDiscoveryListener;
//要查找所有可用网络服务,请键入=“\u服务.\u dns-sd.\u udp”
公共静态最终字符串服务\u TYPE=“\u hap.\u tcp.”;
公共静态最终字符串TAG=“NsdClient”;
private static ArrayList ServicesAvailable=new ArrayList();
公共NSD客户端(上下文){
mContext=上下文;
mNsdManager=(NsdManager)context.getSystemService(context.NSD_SERVICE);
}
public void initializeNsd(){
初始化DiscoveryListener();
}
public void initializeDiscoveryListener(){
mDiscoveryListener=新的NsdManager.DiscoveryListener(){
@凌驾
public void onDiscoveryStarted(字符串regType){
Log.d(标记“服务发现已启动”+regType);
}
@凌驾
公共无效OnServiceFund(NsdServiceInfo服务){
Log.d(标签“服务发现成功”+服务);
可用网络。添加(服务);
如果(!service.getServiceType().equals(服务类型)){
Log.d(标记“未知服务类型:”+Service.getServiceType());
}else if(service.getServiceName().equals(MSServiceName)){
Log.d(标签,“同一台机器:+mServiceName”);
}else if(service.getServiceName()包含(msServiceName)){
Log.d(标签“解析服务:”+服务);
mNsdManager.resolveService(服务,新的初始化项resolveListener());
}
}
@凌驾
ServiceLost上的公共void(NsdServiceInfo服务){
日志e(标签“服务丢失”+服务);
if(服务可用。等于(服务)){
ServicesAvailable=null;
}
}
@凌驾
public void onDiscoveryStopped(字符串服务类型){
Log.i(标记“发现已停止:“+serviceType”);
}
@凌驾
public void onStartDiscoveryFailed(字符串服务类型,int errorCode){
Log.e(标记“发现失败:错误代码:”+errorCode);
mNsdManager.stopServiceDiscovery(此);
}
@凌驾
public void onStopDiscoveryFailed(字符串服务类型,整数错误代码){
Log.e(标记“发现失败:错误代码:”+errorCode);
mNsdManager.stopServiceDiscovery(此);
}
};
}
公共类initializeResolveListener实现NsdManager.ResolveListener{
@凌驾
public void onresolvefiled(NsdServiceInfo serviceInfo,int errorCode){
Log.e(标签“解决失败”+错误代码);
开关(错误代码){
案例NsdManager.FAILURE_已处于活动状态:
Log.e(标签“故障已激活”);
mNsdManager.resolveService(serviceInfo,新的初始值设定项resolveListener());
打破
案例NsdManager.FAILURE\u内部错误:
Log.e(标记“故障\内部错误”);
打破
案例NsdManager.FAILURE_MAX_LIMIT:
Log.e(标签“故障最大极限”);
打破
}
}
@凌驾
已解决服务上的公共无效(NsdServiceInfo服务信息){
Log.e(标记“Resolve Successed.”+serviceInfo);
if(serviceInfo.getServiceName().equals(msservicename)){
Log.d(标签“相同IP”);
返回;
}
}
}
公共发现{
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
公共列表getChosenServiceInfo(){
返回服务可用;
}
公共空间发现服务(){
mNsdManager.discoverServices(
服务类型、NsdManager.PROTOCOL、DNS、mDiscoveryListener);
}
}

希望这有助于

发现连接网络的所有服务只需更改正在发现的服务类型

public static final String SERVICE_TYPE = "_services._dns-sd._udp";

我发现未发现设备存在同样的问题,并能够通过在发现服务之前获取WifiManager多播锁来解决该问题:

val multicastLock: WifiManager.MulticastLock = (mContext.getSystemService(Context.WIFI_SERVICE) as WifiManager).createMulticastLock(TAG)
multicastLock.setReferenceCounted(true)
    
multicastLock.acquire()
    
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener)
mNsdManager.stopServiceDiscovery(mDiscoveryListener)
    
multicastLock.release()
然后在发现服务后释放锁:

val multicastLock: WifiManager.MulticastLock = (mContext.getSystemService(Context.WIFI_SERVICE) as WifiManager).createMulticastLock(TAG)
multicastLock.setReferenceCounted(true)
    
multicastLock.acquire()
    
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener)
mNsdManager.stopServiceDiscovery(mDiscoveryListener)
    
multicastLock.release()

当我在网络中有两台设备具有相同的N时,我试图修复一个似乎弹出的NPE时,我在你的帖子上出现了一个摄像头