在我们的app中添加网络服务发现功能(NSD)以方便在不同的设备上响应局域网中的请求。这种功能对于多设备之间点对点服务来说很有用,例如多人游戏,多人通话,文件共享等。

一,在网络中注册你的服务

注意:这一步是可选操作,如果你对通过局域网广播你的应用服务不关心,这一步大可省去。

在局域网中注册你的服务,首先需要创建一个NsdServiceInfo对象。这个对象封装了局域网内其他设备连接你的服务的信息。

public void registerService(int port){

// Create the NsdServiceInfo object, and populate it.

NsdServiceInfo serviceInfo
= newNsdServiceInfo();



// 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);

....

}

这个代码片段设置了服务的名称为“NsdChat”。这个名字在网络中是可见的,它使用NSD来搜索局域网内的服务。此外,需要注意的是这个名字在局域网中一定是唯一的,如果冲突的话也不用担心,因为Android会自动处理这种冲突。例如如果在同一个局域网中的两个设备都安装了具备NsdChat服务的应用程序,其中一个应用程序会自动修改服务的名称,如”NsdChat(2)“。

此外这个代码片段也设置了服务的类型,以定义应用程序所使用的传输层和传输协议。具体语法规则中为”_<protocol>._<transportlayer>".在代码片段中使用HTTP协议和TCP传输控制协议。如果一个应用程序提供了打印服务就需要设置服务类型为"_ipp._tcp"。

为了便于集中管理,互联网名称和数字地址分配机构制定了一些权威的服务发现协议标准,其中包括NSD和Bonjour。

在为你的服务设置端口的时候,应该避免与其他应用程序产生冲突。

如果你正在使用套接字,下面的代码片段可以告诉你如何简单地初始化一个套接字 :

public void initializeServerSocket(){

    // Initialize a server socket on the next available port.

    mServerSocket = newServerSocket(0);



    // Store the chosen port.

    mLocalPort =  mServerSocket.getLocalPort();

    ...

}

现在你可以定义一个NsdServiceInfo对象了。此时你需要实现RegistrationListener接口。这个接口包涵了一些回调函数,这些回调函数用来警告你的应用程序是否能够成功注册你的服务,或者告诉你是否能够成功取消注册服务。

public void initializeRegistrationListener(){

mRegistrationListener =
new NsdManager.RegistrationListener(){



@Override

public void onServiceRegistered(NsdServiceInfoNsdServiceInfo){

// 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.

}

};

}

二,在网络中发现你的服务

在网络中发现我们的服务,就需要我们的应用程序时刻监听网络中可用的服务广播并且进行过滤。服务发现,就像注册服务一样分两步,第一设置一个搜索服务的监听器和与之相关的回调函数,并且创建一个异步的方法discoverServices()。

public void initializeDiscoveryListener(){



// Instantiate a new DiscoveryListener

mDiscoveryListener = newNsdManager.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());

} elseif(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);

} elseif(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);

}

};

}

NSD的API使用这个接口中的回调函数来同志你的应用程序何时开始你的发现服务,合适你的发现服务失败,合适你的发现服务对其他应用程序可见或者不可见。从上面的代码片断中我们可以看到,当你的服务被发现的时候会做出一系列的检查操作:

1.检查搜索到的服务名称是否时自己发出的

2.检查搜索到的服务类型是否是可连接的

3.检查服务名称是否可以被正确的应用程序成功的验证连接。

设置好监听器后,调用discoverServices()方法

mNsdManager.discoverServices(SERVICE_TYPE,NsdManager.PROTOCOL_NSD_SD,mDsicoveryListener);

三,在服务中连接你的服务

当你的应用程序在网络中发现了一个可连接的服务的时候,首先使用resolveService()方法确定可连接服务的信息,实现NsdManager.ResolverListener接口,并且从NsdServiceInfo中得到其中所封装的消息。

public void initializeResolveListener(){

    mResolveListener = newNsdManager.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();

        }

    };

}

四,应用程序关闭时应取消注册的服务

//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设备之间相同应用程序的网络服务发现功能的更多相关文章

  1. Android网络服务发现(NSD)协议的使用

    Android的网络服务发现协议(NSD)能够用于在小范围的网络中发现邻近设备上的某个应用.这对于一些社交网络.多人游戏类的应用会很有帮助. Android的NSD的用法大致上分为四种操作: 1. 注 ...

  2. Android设备之间通过Wifi通信

    之前写过PC与Android之间通过WIFI通信(通过Socket,可以在博客里面搜索),PC作为主机,Android作为客户机,现在手头有一台仪器通过wifi传输数据,如果仪器作为主机发射WIFI热 ...

  3. android设备之间屏幕共享

    近期公司在开发一款android的设备把屏幕投射到手机上.同一时候手机还能够触控.键盘操作.这样.就达到了屏幕共享的目的. 思考了一下.主要思路: 1.将截图所获取的位图用ffmpeg编码成视频流. ...

  4. Android(java)学习笔记124:Android权限大全

    访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permissio ...

  5. Android(java)学习笔记64:Android权限大全

    访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permissio ...

  6. Android Studio快速集成讯飞SDK实现文字朗读功能

    今天,我们来学习一下怎么在Android Studio快速集成讯飞SDK实现文字朗读功能,先看一下效果图: 第一步 :了解TTS语音服务 TTS的全称为Text To Speech,即“从文本到语音” ...

  7. etcd学习(3)-grpc使用etcd做服务发现

    grpc通过etcd实现服务发现 前言 服务注册 服务发现 负载均衡 集中式LB(Proxy Model) 进程内LB(Balancing-aware Client) 独立 LB 进程(Externa ...

  8. 使用Broadcast实现android组件之间的通信 分类: android 学习笔记 2015-07-09 14:16 110人阅读 评论(0) 收藏

    android组件之间的通信有多种实现方式,Broadcast就是其中一种.在activity和fragment之间的通信,broadcast用的更多本文以一个activity为例. 效果如图: 布局 ...

  9. [转] Android应用程序与SurfaceFlinger服务的关系概述和学习计划

    转自:Android应用程序与SurfaceFlinger服务的关系概述和学习计划 SurfaceFlinger服务负责绘制Android应用程序的UI,它的实现相当复杂,要从正面分析它的实现不是一件 ...

随机推荐

  1. Qt之属性系统

    简述 Qt提供一个类似于其它编译器供应商提供的复杂属性系统(Property System).然而,作为一个编译器和平台无关的库,Qt不能够依赖于那些非标准的编译器特性,比如:__property或者 ...

  2. 超实用的JavaScript代码段 Item8 -- js对象的(深)拷贝

    js 对象 浅拷贝 和 深拷贝 1.浅拷贝 拷贝就是把父对像的属性,全部拷贝给子对象. 下面这个函数,就是在做拷贝: var Chinese = { nation:'中国' } var Doctor ...

  3. 今天同事给介绍了一个LINQ的工具,LINQPad

    今天刚知道LINQPad,详细信息参照http://www.linqpad.net/,免费下载,安装之后样子如下所示,根据向导,链接上本地数据库,比较熟悉的操作风格. 对LINQ的了解太浅,还没有更多 ...

  4. 使用nexus搭建maven仓库(本地私服)

    我们在使用maven的时候,对于项目所依赖的jar包,maven默认会在中央仓库下载jar包,到本地的磁盘目录(如果没有配置则是用户目录下/.m2/repository文件夹下).如果公司内部搭了一个 ...

  5. 如何删除href=""中的链接?

    答案:在dw中操作,删除 HTML文件的href的链接地址\href="[^"]*"href="" 同理可以在title="[^" ...

  6. Android动画效果生动有趣的通知NiftyNotification(Android Toast替代品)

    NiftyNotification在github上的项目主页是:https://github.com/sd6352051/NiftyNotification NiftyNotification本身又依 ...

  7. lazyload 分页加载

    http://www.neoease.com/lazy-load-jquery-plugin-delay-load-image/ echo $d['pic']; ?>" src=&qu ...

  8. 带你揭开ATM的神秘面纱

    相信大家都用过ATM取过money吧,但是有多少人真正是了解ATM的呢?相信除了ATM从业者外了解的人寥寥无几吧,鄙人作为一个从事ATM软件开发的伪专业人士就站在我的角度为大家揭开ATM的神秘面纱吧. ...

  9. Achieving High Availability and Scalability - ARR and NLB

    Achieving High Availability and Scalability: Microsoft Application Request Routing (ARR) for IIS 7.0 ...

  10. Android利用ContentProviderOperation添加联系人

    Android添加联系人有两种方式: 1. 直接调用插入语句,先插入一个空Item,得到一个id,然后给这个id对应的插入其他信息,如姓名,号码,邮件等: 2. 利用ContentProviderOp ...