网络发现服务(NSD)给你的应用程序访问服务,其他设备提供本地网络。设备支持NSD包括打印机、网络摄像头、HTTPS服务器,和其他移动设备。
NSD实现基于DNS发现服务(DNS-SD)机制,允许你的应用请求服务通过指定的服务类型和设备的名字实例提供需求的服务类型。DNS-SD支持android和其他移动设备。
添加NSD在你的应用允许你的使用者识别其他设备在本地网络,这是非常有用的对于多种对等应用,例如文本共享或者多玩家游戏。android的NSD API简化了为你实现这样的功能所需的精力。
在网络上注册你的服务
注:这一步是可选的。如果你不关心通过本地网络广播你的应用程序的服务。
首先创建一个NsdServiceInfo对象,其他设备在网上使用时,当他们下决心是否连接你的设备时这个对象提供信息。
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void registerService(int port){
NsdServiceInfo serviceInfo = new NsdServiceInfo();
//当网络上名字相同有冲突时,会自动更该
//设置服务名称
serviceInfo.setServiceName("NsdChat");
//设置服务类型
serviceInfo.setServiceType("_nsdchat._tcp");
serviceInfo.setPort(port);
}
setServiceType()传入参数的语法是”_ <协议>._ <传输层>.”。例如:一个应用提供打印服务(“_ipp._tcp.”)。
如果您正在使用sockets,这里是如何将sockets初始化为任何可用端口,只需将其设置为0。(避免硬编码)
public void initializeServerSocket() throws IOException {
mServerSocket = new ServerSocket(0);
//存储选择的端口
mLocalPort = mServerSocket.getLocalPort();
}
现在你已经定义了NsdServiceInfo类,你需要继承RegistrationListener接口,这个接口包含回调使用,提醒你的应用服务注册和注销是否成功。
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void initalizeRegistrationListener(){
mRegistrationListener = new NsdManager.RegistrationListener() {
@Override
public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
//注册失败
}
@Override
public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
//注销失败
}
@Override
public void onServiceRegistered(NsdServiceInfo serviceInfo) {
//保存服务的名字,为了避免名字冲突,
// 更新你实际上使用的名字
mServiceName = serviceInfo.getServiceName();
}
@Override
public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
//当你调用NsdManager.unregisterService()服务被注销
}
};
}
现在你可以注册你的服务了。调用registerService()。
注意:这个方法是异步的所以其他代码需要在注册之后运行
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);
}
注意:你还需要权限
<uses-permission android:name="android.permission.INTERNET"/>
在网络上发现设备
您的应用程序需要在网络上收听服务广播以查看可用的服务,并筛选出应用程序无法使用的内容。
发现服务,像注册服务,有两个步骤:设置一个发现监听回调,使用单一的异步API调用discoverServices()。
例如:
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void initializeDiscoveryListener(){
final String TAG = "发现服务";
mDiscoveryListener = new NsdManager.DiscoveryListener() {
@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
}
@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
}
@Override
public void onDiscoveryStarted(String serviceType) {
Log.d(TAG,"发现服务开始");
}
@Override
public void onDiscoveryStopped(String serviceType) {
}
@Override
public void onServiceFound(NsdServiceInfo serviceInfo) {
//当一个服务找到时,处理它
Log.d(TAG,"服务发现成功"+serviceInfo);
if(!serviceInfo.getServiceType().equals(SERVICE_TYPE)){
Log.d(TAG,"服务类型不符合"+serviceInfo.getServiceType());
} else if(serviceInfo.getServiceName().equals(mServiceName)){
Log.d(TAG,mServiceName);
} else if(serviceInfo.getServiceName().contains("NsdChat")){
mNsdManager.resolveService(serviceInfo,mResolveListener);
}
}
@Override
public void onServiceLost(NsdServiceInfo serviceInfo) {
//当网络服务不再可用时,内部记录在这里
}
};
}
设置完监听后调用discoverServices()。
mNsdManager.discoverServices(
SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
连接网络服务
调用NsdManager.resolveService()并且继承 NsdManager.ResolveListener接口。
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void initializeResolveListener(){
final String TAG = "连接服务";
mResolveListener = new NsdManager.ResolveListener() {
@Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
}
@Override
public void onServiceResolved(NsdServiceInfo serviceInfo) {
Log.d(TAG,"连接成功"+serviceInfo);
if(serviceInfo.getServiceName().equals(mServiceName)){
Log.d(TAG,"相同的IP");
return;
}
NsdServiceInfo mService = serviceInfo;
int port = mService.getPort();
InetAddress host = mService.getHost();
Log.d(TAG,host.toString()+port);
}
};
}
在应用关闭时注销服务
在应用生命周期里调用服务的发现注册或注销
@Override
protected void onPause() {
tearDown();
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
//启动发现和注册服务
}
@Override
protected void onDestroy() {
//取消注册和连接的服务
super.onDestroy();
}
public void tearDown() {
mNsdManager.unregisterService(mRegistrationListener);
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}