【问题标题】:Cannot detect service using Network Service Discovery (NSD) on Android无法在 Android 上使用网络服务发现 (NSD) 检测服务
【发布时间】:2016-04-15 19:43:21
【问题描述】:

我是一个新手,试图在我正在构建的应用程序中使用 NSD 来查找在同一个 wifi 网络上运行相同服务的对等点并连接到它。

[参考代码] 我有一台运行 HostActivity.java 的设备和一台运行 GuestActivity.java 的设备。单击 Host 中的浮动按钮会在端口 9000(暂时预设)上注册一个服务,然后在 Guest 中单击它会开始为其运行服务发现。两者都连接到同一个wifi网络。

在我的 logcat 中,我观察到来自 HostActivity.java 的注册工作正常 - 我从 NsdHelper.java 获得了必要的日志消息。但是,运行 GuestActivity.java 只会记录“服务发现已启动”,并且永远不会解析到网络上存在的服务。

我做错了什么?请帮忙。

相关代码——

HostActivity.java

NsdHelper mNsdHelper;

public static final String TAG = "ABC";
private final int ABC_PORT = 9000;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shared_list);


    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);


    mNsdHelper = new NsdHelper(this);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Started Registration", Snackbar.LENGTH_LONG)
                    .setAction("CLOSE", null).show();
            mNsdHelper.initializeNsd();
            mNsdHelper.registerService(ABC_PORT);
            Snackbar.make(view, "Completed Registration", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();

        }
    });
}

@Override
protected void onPause() {
    super.onPause();
}

@Override
protected void onResume() {
    super.onResume();
    if (mNsdHelper != null) {
        mNsdHelper.initializeNsd();
        mNsdHelper.registerService(ABC_PORT);
    }
}

@Override
protected void onDestroy() {
    mNsdHelper.tearDown();
    super.onDestroy();
}

GuestActivity.java

NsdHelper mNsdHelper;

public static final String TAG = "ABC";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shared_list);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    mNsdHelper = new NsdHelper(this);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Searching for available services", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
            mNsdHelper.initializeNsd();
            mNsdHelper.discoverServices();
        }
    });
}

@Override
protected void onPause() {
    super.onPause();
}

@Override
protected void onResume() {
    super.onResume();
    if(mNsdHelper != null) {
        mNsdHelper.initializeNsd();
        mNsdHelper.discoverServices();
    }
}

@Override
protected void onDestroy() {
    mNsdHelper.tearDown();
    super.onDestroy();
}

NsdHelper.java - 这包含所有 NSD 实现细节

public class NsdHelper {
    Context mContext;

    NsdManager mNsdManager;
    NsdManager.ResolveListener mResolveListener;
    NsdManager.DiscoveryListener mDiscoveryListener;
    NsdManager.RegistrationListener mRegistrationListener;

    private static final String SERVICE_TYPE = "_http._tcp.";

    private static final String TAG = "NsdHelper";
    private String mServiceName = "ABC";

    // First step : register a NsdServiceInfo object to advertise your service
    NsdServiceInfo mService;

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


public void initializeNsd() {
    initializeRegistrationListener();
    initializeDiscoveryListener();
    initializeResolveListener();

}


// Check success of service registration
public void initializeRegistrationListener() {
    mRegistrationListener = new NsdManager.RegistrationListener() {

        @Override
        public void onServiceRegistered(NsdServiceInfo nsdServiceInfo) {
            mServiceName = nsdServiceInfo.getServiceName();
            Log.d(TAG, "Registered name : " + mServiceName);
        }

        @Override
        public void onRegistrationFailed(NsdServiceInfo nsdServiceInfo, int arg1) {
            Log.d(TAG, "Registration Failed");
        }

        @Override
        public void onServiceUnregistered(NsdServiceInfo nsdServiceInfo) {
            Log.d(TAG, "Unregistered");
        }

        @Override
        public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
        }

    };
}

public void registerService(int port) {
    NsdServiceInfo serviceInfo  = new NsdServiceInfo();
    serviceInfo.setPort(port);
    serviceInfo.setServiceName(mServiceName);
    serviceInfo.setServiceType(SERVICE_TYPE);

    mNsdManager.registerService(
            serviceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);

}

// To discover services of the type you're looking for on the network
public void initializeDiscoveryListener() {
    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 : " + service);
            Log.d(TAG, "Host = "+ service.getServiceName());
            Log.d(TAG, "port = " + String.valueOf(service.getPort()));

            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)){
                mNsdManager.resolveService(service, mResolveListener);
            }
        }

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

        @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 void discoverServices() {
    mNsdManager.discoverServices(
            SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}


// Connection handshake
public void initializeResolveListener() {
    mResolveListener = new NsdManager.ResolveListener() {

        @Override
        public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
            Log.e(TAG, "Resolve failed" + errorCode);
        }

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

            if (serviceInfo.getServiceName().equals(mServiceName)) {
                Log.d(TAG, "Same IP.");
                return;
            }
            mService = serviceInfo;
            int port = mService.getPort();
            InetAddress host = mService.getHost();
        }
    };
}

public void stopDiscovery() {
    if (mNsdManager != null) {
        mNsdManager.stopServiceDiscovery(mDiscoveryListener);
    }
}

public NsdServiceInfo getChosenServiceInfo() {
    return mService;
}

public void tearDown() {
    if (mNsdManager != null) {
        if (mRegistrationListener != null) {
            mNsdManager.unregisterService(mRegistrationListener);
        }
        if (mDiscoveryListener != null) {
            mNsdManager.stopServiceDiscovery(mDiscoveryListener);
        }
    }
}

}

【问题讨论】:

  • 我从来没有玩过NSD,所以我对这段代码没有任何建议。在这种情况下,我会尝试找到一些现有的工作代码,然后慢慢修改该代码,直到它完成我需要它做的事情。要么我最终会弄清楚我在哪里破坏了东西,要么我得到了工作代码。 :-) Google 可能有一个 NSD 示例,我似乎记得看到最近的一次 Android 会议(droidcon.it 2016?)有一个关于 NSD 的演示文稿,其中可能包括一个工作示例。
  • 大部分(全部?)核心 NSD 代码基本上是从developer.android.com/training/connect-devices-wirelessly/… 中逐字提取的——所以如果 Google 本身的基础代码不起作用,我将无法对其进行更改。我还在这里查看了声称可以工作的类似代码(尽管是从 2 年前开始的)-jayrambhia.com/blog/android-wireless-connection-1 但这也站不住脚。我会寻找相同的 droidcon 演示文稿 - 希望我能找到一些东西。感谢您的提示。
  • 如果 public void onServiceFound(NsdServiceInfo service) 被调用,你至少会看到你的日志语句。我在几个通用的 android 平板电脑上运行了一个类似的程序。一旦找不到该服务,我必须关闭两个设备,然后再次打开它们。使用快速启动重启不起作用。这是一种解决方法,我愿意接受更好的方法来做到这一点。

标签: android nsd


【解决方案1】:

您似乎遵循了 Android 开发者网站上的代码示例,但有两个错误阻碍了我们:

  1. public void onServiceFound(NsdServiceInfo service) 方法中,检查服务名称的代码不正确。据我了解,同一网络中的其他设备也可以使用相同的服务命名,因此删除if (service.getServiceName().equals(mServiceName))代码块。
  2. 同样的事情发生在public void onServiceResolved(NsdServiceInfo serviceInfo) 代码块中。请删除if (serviceInfo.getServiceName().equals(mServiceName)) 代码块。

【讨论】:

  • 我同意你的 cmets,但这里的问题是“onServiceFound(NsdServiceInfo service)”方法没有被调用,即使有多个设备连接到网络。我使用的 SERVICE_TYPE 是“_http._tcp”。
猜你喜欢
  • 1970-01-01
  • 2014-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-03
  • 2012-06-30
相关资源
最近更新 更多