标签:
作者:郭孝星
微博:郭孝星的新浪微博
邮箱:allenwells@163.com
博客:http://blog.csdn.net/allenwells
Github:https://github.com/AllenWells
下面我们来演示一下如何使用Android的NSD服务,文章最后会给出工程源码。
NsdServiceInfo对象包含的信息可以帮助其他设备决定是否要连接到我们所提供的服务。
我们会为NsdServiceInfo设置以下参数:
public void registerService(int port) {
// Create the NsdServiceInfo object, and populate it.
NsdServiceInfo serviceInfo = new NsdServiceInfo();
// The name is subject to change based on conflicts
// with other services advertised on the same network.
serviceInfo.setServiceName("NsdChat");
serviceInfo.setServiceType("_http._tcp.");
serviceInfo.setPort(port);
....
}
RegistrationListener接口包含了注册到Android系统中的一系列回调函数,用来通知应用程序服务注册/注销的成功和失败。
public void initializeRegistrationListener() {
mRegistrationListener = new NsdManager.RegistrationListener() {
@Override
public void onServiceRegistered(NsdServiceInfo NsdServiceInfo) {
// Save the service name. Android may have changed it in order to
// resolve a conflict, so update the name you initially requested
// with the name Android actually used.
mServiceName = NsdServiceInfo.getServiceName();
}
@Override
public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
// Registration failed! Put debugging code here to determine why.
}
@Override
public void onServiceUnregistered(NsdServiceInfo arg0) {
// Service has been unregistered. This only happens when you call
// NsdManager.unregisterService() and pass in this listener.
}
@Override
public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
// Unregistration failed. Put debugging code here to determine why.
}
};
}
registerService()方法是异步方法,所以进一步的操作需要在onServiceRegistered()方法中进行。
public void registerService(int port) {
NsdServiceInfo serviceInfo = new NsdServiceInfo();
serviceInfo.setServiceName("NsdChat");
serviceInfo.setServiceType("_http._tcp.");
serviceInfo.setPort(port);
mNsdManager = Context.getSystemService(Context.NSD_SERVICE);
mNsdManager.registerService(
serviceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);
}
NSD API通过使用该接口中的方法通知用户程序:
- 何时发现开始
- 何时发现失败
- 何时找到可用服务
- 何时服务丢失
在上述代码中,当发现了可用的服务时,程序做了以下检查:
我们并不需要每次都检查服务名称,仅当想要接入特定的应用时,再去判断。例如:应用只想与运行在其他设备上的相同应用通信。然而,如果应用仅仅想接入到一台网络打印机,那么看到服务类型是“_ipp._tcp”的服务就足够了。
public void initializeDiscoveryListener() {
// Instantiate a new DiscoveryListener
mDiscoveryListener = new NsdManager.DiscoveryListener() {
// Called as soon as service discovery begins.
@Override
public void onDiscoveryStarted(String regType) {
Log.d(TAG, "Service discovery started");
}
@Override
public void onServiceFound(NsdServiceInfo service) {
// A service was found! Do something with it.
Log.d(TAG, "Service discovery success" + service);
if (!service.getServiceType().equals(SERVICE_TYPE)) {
// Service type is the string containing the protocol and
// transport layer for this service.
Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
} else if (service.getServiceName().equals(mServiceName)) {
// The name of the service tells the user what they‘d be
// connecting to. It could be "Bob‘s Chat App".
Log.d(TAG, "Same machine: " + mServiceName);
} else if (service.getServiceName().contains("NsdChat")){
mNsdManager.resolveService(service, mResolveListener);
}
}
@Override
public void onServiceLost(NsdServiceInfo service) {
// When the network service is no longer available.
// Internal bookkeeping code goes here.
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);
}
};
}
当我们配置好发现回调函数后,就可以调用discoverService()函数, 该函数的参数包括试图发现的服务种类、发现使用的协议、以及上一步创建的监听者。
mNsdManager.discoverServices(
SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
当发现了网上可接入的网络服务,调用resolveService()方法,并将实现了的NsdManager.RelolveListener的对象和在服务发现过程中得到的NsdServiceInfo对象传入,连接信息可以从NsdServiceInfo对象中解析出来。
public void initializeResolveListener() {
mResolveListener = new NsdManager.ResolveListener() {
@Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
// Called when the resolve fails. Use the error code to debug.
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();
}
};
}
在应用的生命周期中正确的开启和关闭NSD服务是十分关键的。 在程序退出时注销服务可以防止其他程序因为不知道服务退出而反复尝试连接的行为。另外,服务发现是一种开销很大的操作,应该随着父Activity的暂停而停止,当用户返回该界面是再开启。 因此,我们应该重载Activity的生命周期函数,并正确操作服务的广播和发现。
//In your application‘s Activity
@Override
protected void onPause() {
if (mNsdHelper != null) {
mNsdHelper.tearDown();
}
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
if (mNsdHelper != null) {
mNsdHelper.registerService(mConnection.getLocalPort());
mNsdHelper.discoverServices();
}
}
@Override
protected void onDestroy() {
mNsdHelper.tearDown();
mConnection.tearDown();
super.onDestroy();
}
// NsdHelper‘s tearDown method
public void tearDown() {
mNsdManager.unregisterService(mRegistrationListener);
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
版权声明:当我们认真的去做一件事的时候,就能发现其中的无穷乐趣,丰富多彩的技术宛如路上的风景,边走边欣赏。
【Android应用开发技术:网络通信】网络服务可发现使用方法
标签:
原文地址:http://blog.csdn.net/allenwells/article/details/47315337